Ok, here's a patch to enable separate blend function / equation on r200, as well as fix glBlendColor. It needs drm changes, I've tried to make it backward/forward compatible in all ways, except the driver will not build with old drm sources (so this needs to be applied first, could someone do this for me if the patch looks ok? I don't have drm/dri write access nor do I usually need it.)

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" },
 };
 
 

Reply via email to