etnaviv: use surface format directly
[mesa.git] / src / gallium / drivers / etnaviv / etnaviv_blend.c
index ebef75daa7a7094a790421eae6a81842bdaa48cf..0e2299a50b3005ee1eeeb7ca3245fd3f82b7b6e0 100644 (file)
@@ -27,7 +27,9 @@
 #include "etnaviv_blend.h"
 
 #include "etnaviv_context.h"
+#include "etnaviv_screen.h"
 #include "etnaviv_translate.h"
+#include "hw/common.xml.h"
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
 
@@ -35,8 +37,10 @@ void *
 etna_blend_state_create(struct pipe_context *pctx,
                         const struct pipe_blend_state *so)
 {
+   struct etna_context *ctx = etna_context(pctx);
    const struct pipe_rt_blend_state *rt0 = &so->rt[0];
    struct etna_blend_state *co = CALLOC_STRUCT(etna_blend_state);
+   bool alpha_enable, logicop_enable;
 
    if (!co)
       return NULL;
@@ -48,7 +52,7 @@ etna_blend_state_create(struct pipe_context *pctx,
     * - NOT source factor is ONE and destination factor ZERO for both rgb and
     *   alpha (which would mean that blending is effectively disabled)
     */
-   bool enable = rt0->blend_enable &&
+   alpha_enable = rt0->blend_enable &&
                  !(rt0->rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
                    rt0->rgb_dst_factor == PIPE_BLENDFACTOR_ZERO &&
                    rt0->alpha_src_factor == PIPE_BLENDFACTOR_ONE &&
@@ -59,17 +63,11 @@ etna_blend_state_create(struct pipe_context *pctx,
     * - NOT source factor is equal to destination factor for both rgb abd
     *   alpha (which would effectively that mean alpha is not separate)
     */
-   bool separate_alpha = enable &&
+   bool separate_alpha = alpha_enable &&
                          !(rt0->rgb_src_factor == rt0->alpha_src_factor &&
                            rt0->rgb_dst_factor == rt0->alpha_dst_factor);
 
-   /* If the complete render target is written, set full_overwrite:
-    * - The color mask is 1111
-    * - No blending is used
-    */
-   bool full_overwrite = (rt0->colormask == 15) && !enable;
-
-   if (enable) {
+   if (alpha_enable) {
       co->PE_ALPHA_CONFIG =
          VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR |
          COND(separate_alpha, VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA) |
@@ -83,14 +81,15 @@ etna_blend_state_create(struct pipe_context *pctx,
       co->PE_ALPHA_CONFIG = 0;
    }
 
-   co->PE_COLOR_FORMAT =
-         VIVS_PE_COLOR_FORMAT_COMPONENTS(rt0->colormask) |
-         COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE);
+   logicop_enable = so->logicop_enable &&
+                    VIV_FEATURE(ctx->screen, chipMinorFeatures2, LOGIC_OP);
 
    co->PE_LOGIC_OP =
-         VIVS_PE_LOGIC_OP_OP(so->logicop_enable ? so->logicop_func : LOGIC_OP_COPY) |
+         VIVS_PE_LOGIC_OP_OP(logicop_enable ? so->logicop_func : LOGIC_OP_COPY) |
          0x000E4000 /* ??? */;
 
+   co->fo_allowed = !alpha_enable && !logicop_enable;
+
    /* independent_blend_enable not needed: only one rt supported */
    /* XXX alpha_to_coverage / alpha_to_one? */
    /* Set dither registers based on dither status. These registers set the
@@ -107,3 +106,71 @@ etna_blend_state_create(struct pipe_context *pctx,
 
    return co;
 }
+
+bool
+etna_update_blend(struct etna_context *ctx)
+{
+   struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s;
+   struct pipe_blend_state *pblend = ctx->blend;
+   struct etna_blend_state *blend = etna_blend_state(pblend);
+   const struct pipe_rt_blend_state *rt0 = &pblend->rt[0];
+   uint32_t colormask;
+
+   if (pfb->cbufs[0] &&
+       translate_rs_format_rb_swap(pfb->cbufs[0]->format)) {
+      colormask = rt0->colormask & (PIPE_MASK_A | PIPE_MASK_G);
+      if (rt0->colormask & PIPE_MASK_R)
+         colormask |= PIPE_MASK_B;
+      if (rt0->colormask & PIPE_MASK_B)
+         colormask |= PIPE_MASK_R;
+   } else {
+      colormask = rt0->colormask;
+   }
+
+   /* If the complete render target is written, set full_overwrite:
+    * - The color mask is 1111
+    * - No blending is used
+    */
+   bool full_overwrite = ((rt0->colormask == 0xf) && blend->fo_allowed) ||
+                         !pfb->cbufs[0];
+   blend->PE_COLOR_FORMAT =
+            VIVS_PE_COLOR_FORMAT_COMPONENTS(colormask) |
+            COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE);
+
+   return true;
+}
+
+void
+etna_set_blend_color(struct pipe_context *pctx, const struct pipe_blend_color *bc)
+{
+   struct etna_context *ctx = etna_context(pctx);
+   struct compiled_blend_color *cs = &ctx->blend_color;
+
+   memcpy(cs->color, bc->color, sizeof(float) * 4);
+
+   ctx->dirty |= ETNA_DIRTY_BLEND_COLOR;
+}
+
+bool
+etna_update_blend_color(struct etna_context *ctx)
+{
+   struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s;
+   struct compiled_blend_color *cs = &ctx->blend_color;
+
+   if (pfb->cbufs[0] &&
+       translate_rs_format_rb_swap(pfb->cbufs[0]->format)) {
+      cs->PE_ALPHA_BLEND_COLOR =
+         VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(cs->color[2])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(cs->color[1])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(cs->color[0])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(cs->color[3]));
+   } else {
+      cs->PE_ALPHA_BLEND_COLOR =
+         VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(cs->color[0])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(cs->color[1])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(cs->color[2])) |
+         VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(cs->color[3]));
+       }
+
+       return true;
+}