From 6b185aaedfacf3cc435d575585cc5f2e029bece6 Mon Sep 17 00:00:00 2001 From: Vladimir Dergachev Date: Tue, 4 Jan 2005 20:25:11 +0000 Subject: [PATCH] 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. --- src/mesa/drivers/dri/r300/r300_ioctl.c | 7 + src/mesa/drivers/dri/r300/r300_render.c | 2 +- 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 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; -- 2.30.2