diff options
| author | Vladimir Dergachev <volodya@freedesktop.org> | 2005-01-04 20:25:11 +0000 | 
|---|---|---|
| committer | Vladimir Dergachev <volodya@freedesktop.org> | 2005-01-04 20:25:11 +0000 | 
| commit | 6b185aaedfacf3cc435d575585cc5f2e029bece6 (patch) | |
| tree | 2844dfa281566efc3f36065f347c964d9542c1e3 | |
| parent | 55ee1daaf929b9dca436a238f87715caec184445 (diff) | |
Port code from r200 that implements color blending. Seems to work.
This can be tested with lesson19 from NeHe.
This has also shown that the alpha code does not work - we pick up a red tint
for transparent pixels somewhere.
| -rw-r--r-- | src/mesa/drivers/dri/r300/r300_ioctl.c | 7 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/r300/r300_render.c | 2 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/r300/r300_state.c | 282 | 
3 files changed, 288 insertions, 3 deletions
| diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c index 0b876d576e..b4b1aebc4d 100644 --- a/src/mesa/drivers/dri/r300/r300_ioctl.c +++ b/src/mesa/drivers/dri/r300/r300_ioctl.c @@ -109,6 +109,13 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)  	r300->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(1.0);  	r300->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(0.0); +	R300_STATECHANGE(r300, at); +	r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0; +	 +	R300_STATECHANGE(r300, bld); +	r300->hw.bld.cmd[R300_BLD_CBLEND] = 0; +	r300->hw.bld.cmd[R300_BLD_ABLEND] = 0; +	  	R300_STATECHANGE(r300, cb);  	r300->hw.cb.cmd[R300_CB_OFFSET] = cboffset;  	r300->hw.cb.cmd[R300_CB_PITCH] = cbpitch | R300_COLOR_UNKNOWN_22_23; diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index b122927e1f..aad8570378 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -585,7 +585,7 @@ static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)  	#if 0 /* This should work now.. */  	FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST  	#endif -	FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND +	//FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND  	FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG  	FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH  	FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index f97af907a8..f67025494f 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -100,6 +100,273 @@ static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)  	rmesa->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc;  } +static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4]) +{ +	GLubyte color[4]; +	r300ContextPtr rmesa = R300_CONTEXT(ctx); +	fprintf(stderr, "%s:%s is not implemented yet. Fixme !\n", __FILE__, __FUNCTION__); +	#if 0 +	R200_STATECHANGE(rmesa, ctx); +	CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); +	CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); +	CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); +	CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); +	if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) +		rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = +		    radeonPackColor(4, color[0], color[1], color[2], color[3]); +	#endif +} + +/** + * Calculate the hardware blend factor setting.  This same function is used + * for source and destination of both alpha and RGB. + * + * \returns + * The hardware register value for the specified blend factor.  This value + * will need to be shifted into the correct position for either source or + * destination factor. + * + * \todo + * Since the two cases where source and destination are handled differently + * are essentially error cases, they should never happen.  Determine if these + * cases can be removed. + */ +static int blend_factor(GLenum factor, GLboolean is_src) +{ +	int func; + +	switch (factor) { +	case GL_ZERO: +		func = R200_BLEND_GL_ZERO; +		break; +	case GL_ONE: +		func = R200_BLEND_GL_ONE; +		break; +	case GL_DST_COLOR: +		func = R200_BLEND_GL_DST_COLOR; +		break; +	case GL_ONE_MINUS_DST_COLOR: +		func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; +		break; +	case GL_SRC_COLOR: +		func = R200_BLEND_GL_SRC_COLOR; +		break; +	case GL_ONE_MINUS_SRC_COLOR: +		func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; +		break; +	case GL_SRC_ALPHA: +		func = R200_BLEND_GL_SRC_ALPHA; +		break; +	case GL_ONE_MINUS_SRC_ALPHA: +		func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; +		break; +	case GL_DST_ALPHA: +		func = R200_BLEND_GL_DST_ALPHA; +		break; +	case GL_ONE_MINUS_DST_ALPHA: +		func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; +		break; +	case GL_SRC_ALPHA_SATURATE: +		func = +		    (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : +		    R200_BLEND_GL_ZERO; +		break; +	case GL_CONSTANT_COLOR: +		func = R200_BLEND_GL_CONST_COLOR; +		break; +	case GL_ONE_MINUS_CONSTANT_COLOR: +		func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; +		break; +	case GL_CONSTANT_ALPHA: +		func = R200_BLEND_GL_CONST_ALPHA; +		break; +	case GL_ONE_MINUS_CONSTANT_ALPHA: +		func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; +		break; +	default: +		func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; +	} +	return func; +} + +/** + * Sets both the blend equation and the blend function. + * This is done in a single + * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) + * change the interpretation of the blend function. + * Also, make sure that blend function and blend equation are set to their default + * value if color blending is not enabled, since at least blend equations GL_MIN + * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for + * unknown reasons. + */ +static void r300_set_blend_state(GLcontext * ctx) +{ +	r300ContextPtr rmesa = R300_CONTEXT(ctx); +	#if 0 +	GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & +	    ~(R300_ROP_ENABLE | R300_ALPHA_BLEND_ENABLE | +	      R300_SEPARATE_ALPHA_ENABLE); +	#endif + +	int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +	    (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); +	int eqn = R200_COMB_FCN_ADD_CLAMP; +	int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +	    (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); +	int eqnA = R200_COMB_FCN_ADD_CLAMP; + +	R300_STATECHANGE(rmesa, bld); + +	if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) { +		if (ctx->Color._LogicOpEnabled) { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = +			    cntl | R300_ROP_ENABLE; +			#endif +			rmesa->hw.bld.cmd[R300_BLD_ABLEND] = eqn | func; +			rmesa->hw.bld.cmd[R300_BLD_CBLEND] = eqn | func; +			return; +		} else if (ctx->Color.BlendEnabled) { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = +			    cntl | R300_ALPHA_BLEND_ENABLE | +			    R300_SEPARATE_ALPHA_ENABLE; +			#endif +		} else { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; +			#endif +			rmesa->hw.bld.cmd[R300_BLD_ABLEND] = eqn | func; +			rmesa->hw.bld.cmd[R300_BLD_CBLEND] = eqn | func; +			return; +		} +	} else { +		if (ctx->Color._LogicOpEnabled) { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = +			    cntl | R300_ROP_ENABLE; +			rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +			#endif +			return; +		} else if (ctx->Color.BlendEnabled) { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = +			    cntl | R300_ALPHA_BLEND_ENABLE; +			#endif +		} else { +			#if 0 +			rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; +			rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +			#endif +			return; +		} +	} + +	func = +	    (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << +	     R200_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstRGB, +						   GL_FALSE) << +				      R200_DST_BLEND_SHIFT); + +	switch (ctx->Color.BlendEquationRGB) { +	case GL_FUNC_ADD: +		eqn = R300_COMB_FCN_ADD_CLAMP; +		break; + +	case GL_FUNC_SUBTRACT: +		eqn = R300_COMB_FCN_SUB_CLAMP; +		break; + +	case GL_FUNC_REVERSE_SUBTRACT: +		eqn = R200_COMB_FCN_RSUB_CLAMP; +		break; + +	case GL_MIN: +		eqn = R200_COMB_FCN_MIN; +		func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +		    (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); +		break; + +	case GL_MAX: +		eqn = R200_COMB_FCN_MAX; +		func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +		    (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); +		break; + +	default: +		fprintf(stderr, +			"[%s:%u] Invalid RGB blend equation (0x%04x).\n", +			__func__, __LINE__, ctx->Color.BlendEquationRGB); +		return; +	} + +	if (!rmesa->radeon.radeonScreen->drmSupportsBlendColor) { +		#if 0 +		rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +		#endif +		return; +	} + +	funcA = +	    (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << +	     R200_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstA, +						   GL_FALSE) << +				      R200_DST_BLEND_SHIFT); + +	switch (ctx->Color.BlendEquationA) { +	case GL_FUNC_ADD: +		eqnA = R300_COMB_FCN_ADD_CLAMP; +		break; + +	case GL_FUNC_SUBTRACT: +		eqnA = R300_COMB_FCN_SUB_CLAMP; +		break; + +	case GL_FUNC_REVERSE_SUBTRACT: +		eqnA = R200_COMB_FCN_RSUB_CLAMP; +		break; + +	case GL_MIN: +		eqnA = R200_COMB_FCN_MIN; +		funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +		    (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); +		break; + +	case GL_MAX: +		eqnA = R200_COMB_FCN_MAX; +		funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | +		    (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); +		break; + +	default: +		fprintf(stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", +			__func__, __LINE__, ctx->Color.BlendEquationA); +		return; +	} + +	rmesa->hw.bld.cmd[R300_BLD_ABLEND] = eqnA | funcA; +	rmesa->hw.bld.cmd[R300_BLD_CBLEND] = eqn | func ; +	if(rmesa->hw.bld.cmd[R300_BLD_ABLEND] == rmesa->hw.bld.cmd[R300_BLD_CBLEND]){ +		rmesa->hw.bld.cmd[R300_BLD_CBLEND] |= R300_BLEND_UNKNOWN | R300_BLEND_ENABLE | R300_BLEND_NO_SEPARATE; +		} else { +		rmesa->hw.bld.cmd[R300_BLD_CBLEND] |= R300_BLEND_UNKNOWN | R300_BLEND_ENABLE; +		} + +} + +static void r300BlendEquationSeparate(GLcontext * ctx, +				      GLenum modeRGB, GLenum modeA) +{ +	r300_set_blend_state(ctx); +} + +static void r300BlendFuncSeparate(GLcontext * ctx, +				  GLenum sfactorRGB, GLenum dfactorRGB, +				  GLenum sfactorA, GLenum dfactorA) +{ +	r300_set_blend_state(ctx); +} +  /**   * Update our tracked culling state based on Mesa's state.   */ @@ -524,7 +791,7 @@ void r300_setup_textures(GLcontext *ctx)  		exit(-1);  		}  	for(i=0;i<mtu;i++){ -		if(ctx->Texture.Unit[i].Enabled!=NULL){ +		if(ctx->Texture.Unit[i].Enabled){  			t=r300->state.texture.unit[i].texobj;  			r300->state.texture.tc_count++;  			if(t==NULL){ @@ -668,6 +935,10 @@ void r300ResetHwState(r300ContextPtr r300)  	r300UpdateTextureState(ctx);  	r300_setup_textures(ctx);  	r300_setup_rs_unit(ctx); +	 +	 +	r300_set_blend_state(ctx); +	r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);  //BEGIN: TODO  	r300->hw.unk2080.cmd[1] = 0x0030045A; @@ -813,14 +1084,18 @@ void r300ResetHwState(r300ContextPtr r300)  	r300->hw.unk4BC8.cmd[2] = 0;  	r300->hw.unk4BC8.cmd[3] = 0; +	#if 0  	r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0; +	#endif  	r300->hw.unk4BD8.cmd[1] = 0;  	r300->hw.unk4E00.cmd[1] = 0; +	#if 0  	r300->hw.bld.cmd[R300_BLD_CBLEND] = 0;  	r300->hw.bld.cmd[R300_BLD_ABLEND] = 0; +	#endif  	r300->hw.unk4E10.cmd[1] = 0;  	r300->hw.unk4E10.cmd[2] = 0; @@ -937,7 +1212,10 @@ void r300InitStateFuncs(struct dd_function_table* functions)  	radeonInitStateFuncs(functions);  	functions->UpdateState = r300InvalidateState; -	functions->AlphaFunc = r300AlphaFunc; +	//functions->AlphaFunc = r300AlphaFunc; +	functions->BlendColor = r300BlendColor; +	functions->BlendEquationSeparate = r300BlendEquationSeparate; +	functions->BlendFuncSeparate = r300BlendFuncSeparate;  	functions->Enable = r300Enable;  	functions->ColorMask = r300ColorMask;  	functions->DepthFunc = r300DepthFunc; | 
