st/dri: remove unused variables
[mesa.git] / src / gallium / state_trackers / vega / shader.c
index d9074a377b39588b3acbe8c2889a43de8e6c2a40..bee6d84001d03de92430f5f3f660eef06808fa88 100644 (file)
 #include "paint.h"
 #include "mask.h"
 #include "image.h"
+#include "renderer.h"
 
 #include "pipe/p_context.h"
-#include "pipe/p_screen.h"
 #include "pipe/p_state.h"
-#include "pipe/p_inlines.h"
 #include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
 
-#define MAX_CONSTANTS 20
+#define MAX_CONSTANTS 28
 
 struct shader {
    struct vg_context *context;
 
+   VGboolean color_transform;
    VGboolean masking;
    struct vg_paint *paint;
    struct vg_image *image;
 
+   struct matrix modelview;
+   struct matrix paint_matrix;
+
    VGboolean drawing_image;
    VGImageMode image_mode;
 
    float constants[MAX_CONSTANTS];
-   struct pipe_constant_buffer cbuf;
+   struct pipe_resource *cbuf;
    struct pipe_shader_state fs_state;
    void *fs;
 };
@@ -68,7 +73,12 @@ struct shader * shader_create(struct vg_context *ctx)
 
 void shader_destroy(struct shader *shader)
 {
-   free(shader);
+   FREE(shader);
+}
+
+void shader_set_color_transform(struct shader *shader, VGboolean set)
+{
+   shader->color_transform = set;
 }
 
 void shader_set_masking(struct shader *shader, VGboolean set)
@@ -91,56 +101,74 @@ struct vg_paint * shader_paint(struct shader *shader)
    return shader->paint;
 }
 
-
-static void setup_constant_buffer(struct shader *shader)
+static VGint setup_constant_buffer(struct shader *shader)
 {
-   struct vg_context *ctx = shader->context;
-   struct pipe_context *pipe = shader->context->pipe;
-   struct pipe_constant_buffer *cbuf = &shader->cbuf;
+   const struct vg_state *state = &shader->context->state.vg;
    VGint param_bytes = paint_constant_buffer_size(shader->paint);
-   float temp_buf[MAX_CONSTANTS];
+   VGint i;
+
+   param_bytes += sizeof(VGfloat) * 8;
+   assert(param_bytes <= sizeof(shader->constants));
+
+   if (state->color_transform) {
+      for (i = 0; i < 8; i++) {
+         VGfloat val = (i < 4) ? 127.0f : 1.0f;
+         shader->constants[i] =
+            CLAMP(state->color_transform_values[i], -val, val);
+      }
+   }
+   else {
+      memset(shader->constants, 0, sizeof(VGfloat) * 8);
+   }
 
-   assert(param_bytes <= sizeof(temp_buf));
-   paint_fill_constant_buffer(shader->paint, temp_buf);
+   paint_fill_constant_buffer(shader->paint,
+         &shader->paint_matrix, shader->constants + 8);
 
-   if (cbuf->buffer == NULL ||
-       memcmp(temp_buf, shader->constants, param_bytes) != 0)
-   {
-      pipe_buffer_reference(&cbuf->buffer, NULL);
+   return param_bytes;
+}
 
-      memcpy(shader->constants, temp_buf, param_bytes);
-      cbuf->buffer = pipe_user_buffer_create(pipe->screen,
-                                             &shader->constants,
-                                             sizeof(shader->constants));
+static VGboolean blend_use_shader(struct vg_context *ctx)
+{
+   VGboolean advanced_blending;
+
+   switch (ctx->state.vg.blend_mode) {
+   case VG_BLEND_SRC_OVER:
+      advanced_blending =
+         (!paint_is_opaque(ctx->state.vg.fill_paint) ||
+          !paint_is_opaque(ctx->state.vg.stroke_paint)) &&
+         util_format_has_alpha(ctx->draw_buffer->strb->format);
+      break;
+   case VG_BLEND_DST_OVER:
+   case VG_BLEND_MULTIPLY:
+   case VG_BLEND_SCREEN:
+   case VG_BLEND_DARKEN:
+   case VG_BLEND_LIGHTEN:
+   case VG_BLEND_ADDITIVE:
+      advanced_blending = VG_TRUE;
+      break;
+   default:
+      advanced_blending = VG_FALSE;
+      break;
    }
 
-   ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+   return advanced_blending;
 }
 
 static VGint blend_bind_samplers(struct vg_context *ctx,
                                  struct pipe_sampler_state **samplers,
-                                 struct pipe_texture **textures)
+                                 struct pipe_sampler_view **sampler_views)
 {
-   VGBlendMode bmode = ctx->state.vg.blend_mode;
-
-   if (bmode == VG_BLEND_MULTIPLY ||
-       bmode == VG_BLEND_SCREEN ||
-       bmode == VG_BLEND_DARKEN ||
-       bmode == VG_BLEND_LIGHTEN) {
-      struct st_framebuffer *stfb = ctx->draw_buffer;
-
-      vg_prepare_blend_surface(ctx);
-
+   if (blend_use_shader(ctx)) {
       samplers[2] = &ctx->blend_sampler;
-      textures[2] = stfb->blend_texture;
+      sampler_views[2] = vg_prepare_blend_surface(ctx);
 
-      if (!samplers[0] || !textures[0]) {
-         samplers[1] = samplers[2];
-         textures[1] = textures[2];
+      if (!samplers[0] || !sampler_views[0]) {
+         samplers[0] = samplers[2];
+         sampler_views[0] = sampler_views[2];
       }
-      if (!samplers[1] || !textures[1]) {
+      if (!samplers[1] || !sampler_views[1]) {
          samplers[1] = samplers[0];
-         textures[1] = textures[0];
+         sampler_views[1] = sampler_views[0];
       }
 
       return 1;
@@ -148,10 +176,10 @@ static VGint blend_bind_samplers(struct vg_context *ctx,
    return 0;
 }
 
-static void setup_samplers(struct shader *shader)
+static VGint setup_samplers(struct shader *shader,
+                            struct pipe_sampler_state **samplers,
+                            struct pipe_sampler_view **sampler_views)
 {
-   struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
-   struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
    struct vg_context *ctx = shader->context;
    /* a little wonky: we use the num as a boolean that just says
     * whether any sampler/textures have been set. the actual numbering
@@ -167,21 +195,18 @@ static void setup_samplers(struct shader *shader)
    samplers[1] = NULL;
    samplers[2] = NULL;
    samplers[3] = NULL;
-   textures[0] = NULL;
-   textures[1] = NULL;
-   textures[2] = NULL;
-   textures[3] = NULL;
-
-   num += paint_bind_samplers(shader->paint, samplers, textures);
-   num += mask_bind_samplers(samplers, textures);
-   num += blend_bind_samplers(ctx, samplers, textures);
+   sampler_views[0] = NULL;
+   sampler_views[1] = NULL;
+   sampler_views[2] = NULL;
+   sampler_views[3] = NULL;
+
+   num += paint_bind_samplers(shader->paint, samplers, sampler_views);
+   num += mask_bind_samplers(samplers, sampler_views);
+   num += blend_bind_samplers(ctx, samplers, sampler_views);
    if (shader->drawing_image && shader->image)
-      num += image_bind_samplers(shader->image, samplers, textures);
+      num += image_bind_samplers(shader->image, samplers, sampler_views);
 
-   if (num) {
-      cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
-      cso_set_sampler_textures(ctx->cso_context, 4, textures);
-   }
+   return (num) ? 4 : 0;
 }
 
 static INLINE VGboolean is_format_bw(struct shader *shader)
@@ -226,6 +251,9 @@ static void setup_shader_program(struct shader *shader)
       default:
          abort();
       }
+
+      if (paint_is_degenerate(shader->paint))
+         shader_id = VEGA_PAINT_DEGENERATE_SHADER;
    }
 
    /* second stage image */
@@ -245,43 +273,86 @@ static void setup_shader_program(struct shader *shader)
       }
    }
 
-   if (shader->masking)
-      shader_id |= VEGA_MASK_SHADER;
+   if (shader->color_transform)
+      shader_id |= VEGA_COLOR_TRANSFORM_SHADER;
 
-   switch(blend_mode) {
-   case VG_BLEND_MULTIPLY:
-      shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
-      break;
-   case VG_BLEND_SCREEN:
-      shader_id |= VEGA_BLEND_SCREEN_SHADER;
-      break;
-   case VG_BLEND_DARKEN:
-      shader_id |= VEGA_BLEND_DARKEN_SHADER;
-      break;
-   case VG_BLEND_LIGHTEN:
-      shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
-      break;
-   default:
-      /* handled by pipe_blend_state */
-      break;
+   if (blend_use_shader(ctx)) {
+      if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
+         shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
+      else
+         shader_id |= VEGA_ALPHA_NORMAL_SHADER;
+
+      switch(blend_mode) {
+      case VG_BLEND_SRC:
+         shader_id |= VEGA_BLEND_SRC_SHADER;
+         break;
+      case VG_BLEND_SRC_OVER:
+         shader_id |= VEGA_BLEND_SRC_OVER_SHADER;
+         break;
+      case VG_BLEND_DST_OVER:
+         shader_id |= VEGA_BLEND_DST_OVER_SHADER;
+         break;
+      case VG_BLEND_SRC_IN:
+         shader_id |= VEGA_BLEND_SRC_IN_SHADER;
+         break;
+      case VG_BLEND_DST_IN:
+         shader_id |= VEGA_BLEND_DST_IN_SHADER;
+         break;
+      case VG_BLEND_MULTIPLY:
+         shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
+         break;
+      case VG_BLEND_SCREEN:
+         shader_id |= VEGA_BLEND_SCREEN_SHADER;
+         break;
+      case VG_BLEND_DARKEN:
+         shader_id |= VEGA_BLEND_DARKEN_SHADER;
+         break;
+      case VG_BLEND_LIGHTEN:
+         shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
+         break;
+      case VG_BLEND_ADDITIVE:
+         shader_id |= VEGA_BLEND_ADDITIVE_SHADER;
+         break;
+      default:
+         assert(0);
+         break;
+      }
+   }
+   else {
+      /* update alpha of the source */
+      if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
+         shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
    }
 
+   if (shader->masking)
+      shader_id |= VEGA_MASK_SHADER;
+
    if (black_white)
       shader_id |= VEGA_BW_SHADER;
 
    shader->fs = shaders_cache_fill(ctx->sc, shader_id);
-   cso_set_fragment_shader_handle(ctx->cso_context, shader->fs);
 }
 
 
 void shader_bind(struct shader *shader)
 {
+   struct vg_context *ctx = shader->context;
+   struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+   struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
+   VGint num_samplers, param_bytes;
+
    /* first resolve the real paint type */
    paint_resolve_type(shader->paint);
 
-   setup_constant_buffer(shader);
-   setup_samplers(shader);
+   num_samplers = setup_samplers(shader, samplers, sampler_views);
+   param_bytes = setup_constant_buffer(shader);
    setup_shader_program(shader);
+
+   renderer_validate_for_shader(ctx->renderer,
+         (const struct pipe_sampler_state **) samplers,
+         sampler_views, num_samplers,
+         &shader->modelview,
+         shader->fs, (const void *) shader->constants, param_bytes);
 }
 
 void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
@@ -308,3 +379,28 @@ void shader_set_image(struct shader *shader, struct vg_image *img)
 {
    shader->image = img;
 }
+
+/**
+ * Set the transformation to map a vertex to the surface coordinates.
+ */
+void shader_set_surface_matrix(struct shader *shader,
+                               const struct matrix *mat)
+{
+   shader->modelview = *mat;
+}
+
+/**
+ * Set the transformation to map a pixel to the paint coordinates.
+ */
+void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat)
+{
+   const struct st_framebuffer *stfb = shader->context->draw_buffer;
+   const VGfloat px_center_offset = 0.5f;
+
+   memcpy(&shader->paint_matrix, mat, sizeof(*mat));
+
+   /* make it window-to-paint for the shaders */
+   matrix_translate(&shader->paint_matrix, px_center_offset,
+         stfb->height - 1.0f + px_center_offset);
+   matrix_scale(&shader->paint_matrix, 1.0f, -1.0f);
+}