st/mesa: handle EXT_draw_buffers2 per rendertarget blend enables / colormasks
authorRoland Scheidegger <sroland@vmware.com>
Mon, 25 Jan 2010 18:27:05 +0000 (19:27 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Mon, 25 Jan 2010 18:27:05 +0000 (19:27 +0100)
uses the new gallium per-rt blend functionality

src/gallium/state_trackers/dri/dri_extensions.c
src/mesa/state_tracker/st_atom_blend.c
src/mesa/state_tracker/st_extensions.c

index 8b014a2a8b8bf897b5939febdfb72114a3ca664e..1259813a4129273fd834a7b781ca296c3c621424 100644 (file)
@@ -50,6 +50,7 @@
 #define need_GL_EXT_blend_func_separate
 #define need_GL_EXT_blend_minmax
 #define need_GL_EXT_cull_vertex
+#define need_GL_EXT_draw_buffers2
 #define need_GL_EXT_fog_coord
 #define need_GL_EXT_framebuffer_object
 #define need_GL_EXT_multi_draw_arrays
@@ -98,6 +99,7 @@ static const struct dri_extension card_extensions[] = {
    {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
    {"GL_EXT_blend_subtract", NULL},
    {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
+   {"GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions},
    {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
    {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
    {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
@@ -130,6 +132,9 @@ dri_init_extensions(struct dri_context *ctx)
    /* The card_extensions list should be pruned according to the
     * capabilities of the pipe_screen. This is actually something
     * that can/should be done inside st_create_context().
+    * XXX Not pruning is very bogus. Always all these extensions above
+    * will be advertized, regardless what st_init_extensions
+    * (which depends on the pipe cap bits) does.
     */
    driInitExtensions(ctx->st->ctx, card_extensions, GL_TRUE);
 }
index 75c14183350ea328ebc699679815e25c149f10aa..809b10d4799a4671a2d3269c3ed060ba0cead256 100644 (file)
@@ -152,14 +152,40 @@ translate_logicop(GLenum logicop)
    }
 }
 
+static boolean
+colormask_perrt(GLcontext *ctx)
+{
+   /* XXX this is ugly beyond belief */
+   unsigned i;
+   for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
+      if (!TEST_EQ_4V(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i])) {
+         return true;
+      }
+   }
+   return false;
+}
 
 static void 
 update_blend( struct st_context *st )
 {
    struct pipe_blend_state *blend = &st->state.blend;
+   unsigned num_state = 1;
+   unsigned i;
 
    memset(blend, 0, sizeof(*blend));
 
+   if ((st->ctx->Color.BlendEnabled &&
+      (st->ctx->Color.BlendEnabled != ((1 << st->ctx->Const.MaxDrawBuffers) - 1))) ||
+      colormask_perrt(st->ctx)) {
+      num_state = st->ctx->Const.MaxDrawBuffers;
+      blend->independent_blend_enable = 1;
+   }
+   /* Note it is impossible to correctly deal with EXT_blend_logic_op and
+      EXT_draw_buffers2/EXT_blend_equation_separate at the same time.
+      These combinations would require support for per-rt logicop enables
+      and separate alpha/rgb logicop/blend support respectively. Neither
+      possible in gallium nor most hardware. Assume these combinations
+      don't happen. */
    if (st->ctx->Color.ColorLogicOpEnabled ||
        (st->ctx->Color.BlendEnabled &&
         st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) {
@@ -169,30 +195,33 @@ update_blend( struct st_context *st )
    }
    else if (st->ctx->Color.BlendEnabled) {
       /* blending enabled */
-      blend->rt[0].blend_enable = 1;
-
-      blend->rt[0].rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
-      if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
-          st->ctx->Color.BlendEquationRGB == GL_MAX) {
-         /* Min/max are special */
-         blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-         blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
-      }
-      else {
-         blend->rt[0].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
-         blend->rt[0].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
-      }
+      for (i = 0; i < num_state; i++) {
 
-      blend->rt[0].alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
-      if (st->ctx->Color.BlendEquationA == GL_MIN ||
-          st->ctx->Color.BlendEquationA == GL_MAX) {
-         /* Min/max are special */
-         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
-      }
-      else {
-         blend->rt[0].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
-         blend->rt[0].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
+         blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
+
+         blend->rt[i].rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
+         if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
+             st->ctx->Color.BlendEquationRGB == GL_MAX) {
+            /* Min/max are special */
+            blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+            blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+         }
+         else {
+            blend->rt[i].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
+            blend->rt[i].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
+         }
+
+         blend->rt[i].alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
+         if (st->ctx->Color.BlendEquationA == GL_MIN ||
+             st->ctx->Color.BlendEquationA == GL_MAX) {
+            /* Min/max are special */
+            blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+            blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+         }
+         else {
+            blend->rt[i].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
+            blend->rt[i].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
+         }
       }
    }
    else {
@@ -200,14 +229,16 @@ update_blend( struct st_context *st )
    }
 
    /* Colormask - maybe reverse these bits? */
-   if (st->ctx->Color.ColorMask[0][0])
-      blend->rt[0].colormask |= PIPE_MASK_R;
-   if (st->ctx->Color.ColorMask[0][1])
-      blend->rt[0].colormask |= PIPE_MASK_G;
-   if (st->ctx->Color.ColorMask[0][2])
-      blend->rt[0].colormask |= PIPE_MASK_B;
-   if (st->ctx->Color.ColorMask[0][3])
-      blend->rt[0].colormask |= PIPE_MASK_A;
+   for (i = 0; i < num_state; i++) {
+      if (st->ctx->Color.ColorMask[i][0])
+         blend->rt[i].colormask |= PIPE_MASK_R;
+      if (st->ctx->Color.ColorMask[i][1])
+         blend->rt[i].colormask |= PIPE_MASK_G;
+      if (st->ctx->Color.ColorMask[i][2])
+         blend->rt[i].colormask |= PIPE_MASK_B;
+      if (st->ctx->Color.ColorMask[i][3])
+         blend->rt[i].colormask |= PIPE_MASK_A;
+   }
 
    if (st->ctx->Color.DitherFlag)
       blend->dither = 1;
index 2a5fb27d8f3db7a15a6fb8752dea94c407422704..a7411c86439687aa8d3b1d37921c827ddfeba717 100644 (file)
@@ -315,4 +315,14 @@ void st_init_extensions(struct st_context *st)
    if (st->pipe->render_condition) {
       ctx->Extensions.NV_conditional_render = GL_TRUE;
    }
+
+   if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_ENABLE)) {
+      ctx->Extensions.EXT_draw_buffers2 = GL_TRUE;
+   }
+
+#if 0 /* not yet */
+   if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_FUNC)) {
+      ctx->Extensions.ARB_draw_buffers_blend = GL_TRUE;
+   }
+#endif
 }