From: Vladimir Dergachev Date: Tue, 4 Jan 2005 20:25:11 +0000 (+0000) Subject: Port code from r200 that implements color blending. Seems to work. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6b185aaedfacf3cc435d575585cc5f2e029bece6;p=mesa.git 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. --- diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c index 0b876d576e9..b4b1aebc4d8 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 b122927e1f3..aad85703784 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 f97af907a8d..f67025494f0 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;iTexture.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;