A couple of comments though:
- not sure if the radeon_common.h patch for dri is needed. The packets defined there are exactly the same as in radeon_drm.h, which I consider not a good idea. But if it's doubled, at least keep it in sync...
- drm changes are just a bunch of #defines, and a version number bump. I think the driver date always stays the same?
Compatiblity to old drm is achieved with a bunch of ifs. If you think this is too ugly, I'm open for other suggestions ;-). But it didn't seem like that much of a headache which would warrant ditching compatiblity to old drm neither.
Also, if old drm is used, glBlendColor will silently fail (that's already the case up till now), so will the glBlendSeparate functions if you use different RGB and alpha factors/equations (extensions are not announced, but you could still use them, no error will be generated).
Also, in case of color blending, always separate blending functions/equations are used for the chip. I think it might be possible to only set the CBLENDCNTL register if the factors/equations are the same and not enable seperate_alpha, but this looked like more complex control code without any benefits. Unless, of course, separate blending has a performance hit, I assumed no but haven't measured it. Is there a good demo/benchmark somewhere which would show such a hit (i.e. lots of blending, but not much else done)?
Testing seemed to show the new extensions work, though I couldn't find a good test. Mesa lacks a test for these extensions (as well as for blendColor).
Roland
Index: r200_context.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_context.c,v retrieving revision 1.23 diff -u -r1.23 r200_context.c --- r200_context.c 29 Apr 2004 12:23:41 -0000 1.23 +++ r200_context.c 14 May 2004 17:04:08 -0000 @@ -403,5 +403,9 @@ if (rmesa->r200Screen->drmSupportsCubeMaps) _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" ); + if (rmesa->r200Screen->drmSupportsBlendColor) { + _mesa_enable_extension( ctx, "GL_EXT_blend_equation_separate" ); + _mesa_enable_extension( ctx, "GL_EXT_blend_func_separate" ); + }
#if 0 r200InitDriverFuncs( ctx ); Index: r200_context.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_context.h,v retrieving revision 1.15 diff -u -r1.15 r200_context.h --- r200_context.h 5 May 2004 20:16:17 -0000 1.15 +++ r200_context.h 14 May 2004 17:04:11 -0000 @@ -213,7 +213,12 @@ #define CTX_RB3D_COLOROFFSET 11 #define CTX_CMD_2 12 /* why */ #define CTX_RB3D_COLORPITCH 13 /* why */ -#define CTX_STATE_SIZE 14 +#define CTX_STATE_SIZE_OLDDRM 14 +#define CTX_CMD_3 14 +#define CTX_RB3D_BLENDCOLOR 15 +#define CTX_RB3D_ABLENDCNTL 16 +#define CTX_RB3D_CBLENDCNTL 17 +#define CTX_STATE_SIZE_NEWDRM 18 #define SET_CMD_0 0 #define SET_SE_CNTL 1 Index: r200_reg.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_reg.h,v retrieving revision 1.4 diff -u -r1.4 r200_reg.h --- r200_reg.h 14 May 2004 13:01:08 -0000 1.4 +++ r200_reg.h 14 May 2004 17:04:20 -0000 @@ -1307,6 +1307,7 @@ #define R200_PP_TXABLEND_7 0x2f78 #define R200_PP_TXABLEND2_7 0x2f7c /* gap */ +#define R200_RB3D_BLENDCOLOR 0x3218 /* ARGB 8888 */ #define R200_RB3D_ABLENDCNTL 0x321C /* see BLENDCTL */ #define R200_RB3D_CBLENDCNTL 0x3220 /* see BLENDCTL */ Index: r200_screen.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_screen.c,v retrieving revision 1.18 diff -u -r1.18 r200_screen.c --- r200_screen.c 29 Apr 2004 12:23:41 -0000 1.18 +++ r200_screen.c 14 May 2004 17:04:23 -0000 @@ -351,6 +352,10 @@ /* Check if kernel module is new enough to support cube maps */ screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 7); + /* Check if kernel module is new enough to support blend color and + separate blend functions/eqations */ + screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11); + } } Index: r200_screen.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_screen.h,v retrieving revision 1.7 diff -u -r1.7 r200_screen.h --- r200_screen.h 17 Mar 2004 20:50:14 -0000 1.7 +++ r200_screen.h 14 May 2004 17:04:23 -0000 @@ -95,6 +95,7 @@ unsigned int gart_base; GLboolean drmSupportsCubeMaps; /* need radeon kernel module >=1.7 */ + GLboolean drmSupportsBlendColor; /* need radeon kernel module >= 1.11 */ /* Configuration cache with default values for all contexts */ driOptionCache optionCache; Index: r200_state.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_state.c,v retrieving revision 1.19 diff -u -r1.19 r200_state.c --- r200_state.c 14 May 2004 13:01:08 -0000 1.19 +++ r200_state.c 14 May 2004 17:04:32 -0000 @@ -104,6 +104,19 @@ rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; } +static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] ) +{ + GLubyte color[4]; + r200ContextPtr rmesa = R200_CONTEXT(ctx); + 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->r200Screen->drmSupportsBlendColor) + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = r200PackColor( 4, color[0], color[1], color[2], color[3] ); +} + /** * Calculate the hardware blend factor setting. This same function is used * for source and destination of both alpha and RGB. @@ -188,25 +201,46 @@ { r200ContextPtr rmesa = R200_CONTEXT(ctx); GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & - ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE); + ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE); 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; R200_STATECHANGE( rmesa, ctx ); - if (ctx->Color._LogicOpEnabled) { - rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; - rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; - return; - } else if (ctx->Color.BlendEnabled) { - rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE; + if (rmesa->r200Screen->drmSupportsBlendColor) { + if (ctx->Color._LogicOpEnabled) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; + rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; + return; + } else if (ctx->Color.BlendEnabled) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE; + } + else { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; + rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; + rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; + return; + } } else { - rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; - rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; - return; + if (ctx->Color._LogicOpEnabled) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; + return; + } else if (ctx->Color.BlendEnabled) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE; + } + else { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; + return; + } } func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | @@ -244,7 +278,49 @@ return; } - rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; + if (!rmesa->r200Screen->drmSupportsBlendColor) { + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; + 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: + case GL_LOGIC_OP: + eqnA = R200_COMB_FCN_ADD_CLAMP; + break; + + case GL_FUNC_SUBTRACT: + eqnA = R200_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.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA; + rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; + } static void r200BlendEquationSeparate( GLcontext *ctx, @@ -2208,6 +2284,7 @@ functions->ReadBuffer = r200ReadBuffer; functions->AlphaFunc = r200AlphaFunc; + functions->BlendColor = r200BlendColor; functions->BlendEquationSeparate = r200BlendEquationSeparate; functions->BlendFuncSeparate = r200BlendFuncSeparate; functions->ClearColor = r200ClearColor; Index: r200_state_init.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_state_init.c,v retrieving revision 1.10 diff -u -r1.10 r200_state_init.c --- r200_state_init.c 14 May 2004 13:01:08 -0000 1.10 +++ r200_state_init.c 14 May 2004 17:04:35 -0000 @@ -218,7 +218,10 @@ /* Allocate state buffers: */ - ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 ); + if (rmesa->r200Screen->drmSupportsBlendColor) + ALLOC_STATE( ctx, always, CTX_STATE_SIZE_NEWDRM, "CTX/context", 0 ); + else + ALLOC_STATE( ctx, always, CTX_STATE_SIZE_OLDDRM, "CTX/context", 0 ); ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 ); ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 ); ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 ); @@ -280,6 +283,8 @@ rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC); rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL); rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH); + if (rmesa->r200Screen->drmSupportsBlendColor) + rmesa->hw.ctx.cmd[CTX_CMD_3] = cmdpkt(R200_EMIT_RB3D_BLENDCOLOR); rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN); rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH); rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK); @@ -367,8 +372,18 @@ rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000; rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | - (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | - (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); + (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); + + if (rmesa->r200Screen->drmSupportsBlendColor) { + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = 0x00000000; + rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | + (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); + rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | + (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); + } rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] = rmesa->r200Screen->depthOffset + rmesa->r200Screen->fbLocation;
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h =================================================================== RCS file: /cvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v retrieving revision 1.15 diff -u -r1.15 radeon_common.h --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h 3 Dec 2003 17:20:24 -0000 1.15 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h 14 May 2004 18:41:31 -0000 @@ -360,7 +360,8 @@ #define RADEON_EMIT_PP_TEX_SIZE_0 73 #define RADEON_EMIT_PP_TEX_SIZE_1 74 #define RADEON_EMIT_PP_TEX_SIZE_2 75 -#define RADEON_MAX_STATE_PACKETS 76 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define RADEON_MAX_STATE_PACKETS 77 /* Commands understood by cmd_buffer ioctl. More can be added but
Index: shared/radeon.h =================================================================== RCS file: /cvs/dri/drm/shared/radeon.h,v retrieving revision 1.27 diff -u -r1.27 radeon.h --- shared/radeon.h 9 May 2004 06:45:17 -0000 1.27 +++ shared/radeon.h 14 May 2004 18:46:59 -0000 @@ -51,7 +51,7 @@ #define DRIVER_DATE "20020828" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 10 +#define DRIVER_MINOR 11 #define DRIVER_PATCHLEVEL 0 /* Interface history: @@ -84,6 +84,7 @@ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which * clients use to tell the DRM where they think the framebuffer is * located in the card's address space + * 1.11 Add packet R200_EMIT_RB3D_BLENDCOLOR */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ Index: shared/radeon_drm.h =================================================================== RCS file: /cvs/dri/drm/shared/radeon_drm.h,v retrieving revision 1.20 diff -u -r1.20 radeon_drm.h --- shared/radeon_drm.h 10 Apr 2004 13:52:43 -0000 1.20 +++ shared/radeon_drm.h 14 May 2004 18:47:02 -0000 @@ -144,7 +144,8 @@ #define RADEON_EMIT_PP_TEX_SIZE_0 73 #define RADEON_EMIT_PP_TEX_SIZE_1 74 #define RADEON_EMIT_PP_TEX_SIZE_2 75 -#define RADEON_MAX_STATE_PACKETS 76 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define RADEON_MAX_STATE_PACKETS 77 /* Commands understood by cmd_buffer ioctl. More can be added but Index: shared/radeon_drv.h =================================================================== RCS file: /cvs/dri/drm/shared/radeon_drv.h,v retrieving revision 1.24 diff -u -r1.24 radeon_drv.h --- shared/radeon_drv.h 16 Dec 2003 08:57:08 -0000 1.24 +++ shared/radeon_drv.h 14 May 2004 18:47:06 -0000 @@ -690,6 +690,7 @@ #define R200_SE_VTX_FMT_1 0x208c #define R200_RE_CNTL 0x1c50 +#define R200_RB3D_BLENDCOLOR 0x3218 /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ Index: shared/radeon_state.c =================================================================== RCS file: /cvs/dri/drm/shared/radeon_state.c,v retrieving revision 1.27 diff -u -r1.27 radeon_state.c --- shared/radeon_state.c 8 Apr 2004 12:05:25 -0000 1.27 +++ shared/radeon_state.c 14 May 2004 18:47:14 -0000 @@ -201,6 +201,7 @@ case RADEON_EMIT_PP_TEX_SIZE_0: case RADEON_EMIT_PP_TEX_SIZE_1: case RADEON_EMIT_PP_TEX_SIZE_2: + case R200_EMIT_RB3D_BLENDCOLOR: /* These packets don't contain memory offsets */ break; @@ -563,6 +564,7 @@ { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" }, { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" }, { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" }, + { R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" }, };