gallium: prepare for per-rendertarget blend enables, writemasks, blend funcs
authorRoland Scheidegger <sroland@vmware.com>
Wed, 20 Jan 2010 17:26:49 +0000 (18:26 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Wed, 20 Jan 2010 17:26:49 +0000 (18:26 +0100)
GL 3.0 (EXT_draw_buffers2) and other APIs allow independent blend enables and
write masks per render target, ARB_draw_buffers_blend (and other APIs) also
allow independent blend functions. Things like dithering, logic ops however
are not extended to be per rendertarget, that might be conceptually possible
however it doesn't look like any API wants to expose this.

src/gallium/auxiliary/cso_cache/cso_context.c
src/gallium/include/pipe/p_state.h
src/mesa/state_tracker/st_atom_blend.c
src/mesa/state_tracker/st_cb_clear.c

index fdfb5faa59e4037b6cd4e2745fb82c6ab4671e1c..c8fdfc81248f7fdbeb02cf1332598c9bcafefcc0 100644 (file)
@@ -310,18 +310,21 @@ void cso_destroy_context( struct cso_context *ctx )
 enum pipe_error cso_set_blend(struct cso_context *ctx,
                               const struct pipe_blend_state *templ)
 {
-   unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
-   struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
-                                                       hash_key, CSO_BLEND,
-                                                       (void*)templ);
+   unsigned key_size, hash_key;
+   struct cso_hash_iter iter;
    void *handle;
 
+   key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) :
+              (void *)&(templ->rt[1]) - (void *)templ;
+   hash_key = cso_construct_key((void*)templ, key_size);
+   iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ);
+
    if (cso_hash_iter_is_null(iter)) {
       struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
       if (!cso)
          return PIPE_ERROR_OUT_OF_MEMORY;
 
-      memcpy(&cso->state, templ, sizeof(*templ));
+      memcpy(&cso->state, templ, key_size);
       cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
       cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
       cso->context = ctx->pipe;
index fdd29ed449269af45e5432d885de3ca8b4d84904..3c217645ab4b9edf4f00dcadef2af6b19c4084d3 100644 (file)
@@ -217,7 +217,7 @@ struct pipe_depth_stencil_alpha_state
 };
 
 
-struct pipe_blend_state
+struct pipe_rt_blend_state
 {
    unsigned blend_enable:1;
 
@@ -229,11 +229,16 @@ struct pipe_blend_state
    unsigned alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */
    unsigned alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
 
+   unsigned colormask:4;         /**< bitmask of PIPE_MASK_R/G/B/A */
+};
+
+struct pipe_blend_state
+{
+   unsigned independent_blend_enable:1;
    unsigned logicop_enable:1;
    unsigned logicop_func:4;      /**< PIPE_LOGICOP_x */
-
-   unsigned colormask:4;         /**< bitmask of PIPE_MASK_R/G/B/A */
    unsigned dither:1;
+   struct pipe_rt_blend_state rt[PIPE_MAX_COLOR_BUFS];
 };
 
 
index 43e62c29f3e4fc65a70f687f056f811436c35848..75c14183350ea328ebc699679815e25c149f10aa 100644 (file)
@@ -169,30 +169,30 @@ update_blend( struct st_context *st )
    }
    else if (st->ctx->Color.BlendEnabled) {
       /* blending enabled */
-      blend->blend_enable = 1;
+      blend->rt[0].blend_enable = 1;
 
-      blend->rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
+      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->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-         blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+         blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+         blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
       }
       else {
-         blend->rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
-         blend->rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
+         blend->rt[0].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
+         blend->rt[0].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
       }
 
-      blend->alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
+      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->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-         blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
       }
       else {
-         blend->alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
-         blend->alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
+         blend->rt[0].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
+         blend->rt[0].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
       }
    }
    else {
@@ -201,13 +201,13 @@ update_blend( struct st_context *st )
 
    /* Colormask - maybe reverse these bits? */
    if (st->ctx->Color.ColorMask[0][0])
-      blend->colormask |= PIPE_MASK_R;
+      blend->rt[0].colormask |= PIPE_MASK_R;
    if (st->ctx->Color.ColorMask[0][1])
-      blend->colormask |= PIPE_MASK_G;
+      blend->rt[0].colormask |= PIPE_MASK_G;
    if (st->ctx->Color.ColorMask[0][2])
-      blend->colormask |= PIPE_MASK_B;
+      blend->rt[0].colormask |= PIPE_MASK_B;
    if (st->ctx->Color.ColorMask[0][3])
-      blend->colormask |= PIPE_MASK_A;
+      blend->rt[0].colormask |= PIPE_MASK_A;
 
    if (st->ctx->Color.DitherFlag)
       blend->dither = 1;
index 192d765f45335a9846b3dcbf59fca93972c28857..2c1be41ad83b63fd1085682b0884b067d1acb350 100644 (file)
@@ -227,19 +227,19 @@ clear_with_quad(GLcontext *ctx,
    {
       struct pipe_blend_state blend;
       memset(&blend, 0, sizeof(blend));
-      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+      blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+      blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
       if (color) {
          if (ctx->Color.ColorMask[0][0])
-            blend.colormask |= PIPE_MASK_R;
+            blend.rt[0].colormask |= PIPE_MASK_R;
          if (ctx->Color.ColorMask[0][1])
-            blend.colormask |= PIPE_MASK_G;
+            blend.rt[0].colormask |= PIPE_MASK_G;
          if (ctx->Color.ColorMask[0][2])
-            blend.colormask |= PIPE_MASK_B;
+            blend.rt[0].colormask |= PIPE_MASK_B;
          if (ctx->Color.ColorMask[0][3])
-            blend.colormask |= PIPE_MASK_A;
+            blend.rt[0].colormask |= PIPE_MASK_A;
          if (st->ctx->Color.DitherFlag)
             blend.dither = 1;
       }