summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/vega/shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/vega/shader.c')
-rw-r--r--src/gallium/state_trackers/vega/shader.c211
1 files changed, 153 insertions, 58 deletions
diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c
index eab1349639..0ed721376c 100644
--- a/src/gallium/state_trackers/vega/shader.c
+++ b/src/gallium/state_trackers/vega/shader.c
@@ -31,22 +31,29 @@
#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 "util/u_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;
@@ -71,6 +78,11 @@ void shader_destroy(struct shader *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)
{
shader->masking = set;
@@ -91,49 +103,64 @@ 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_resource **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 == NULL ||
- memcmp(temp_buf, shader->constants, param_bytes) != 0)
- {
- pipe_resource_reference(cbuf, NULL);
+ return param_bytes;
+}
+
+static VGboolean blend_use_shader(struct vg_context *ctx)
+{
+ VGboolean advanced_blending;
- memcpy(shader->constants, temp_buf, param_bytes);
- *cbuf = pipe_user_buffer_create(pipe->screen,
- &shader->constants,
- sizeof(shader->constants),
- PIPE_BIND_VERTEX_BUFFER);
+ switch (ctx->state.vg.blend_mode) {
+ case VG_BLEND_SRC_OVER:
+ advanced_blending =
+ 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_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;
- sampler_views[2] = stfb->blend_texture_view;
+ sampler_views[2] = vg_prepare_blend_surface(ctx);
if (!samplers[0] || !sampler_views[0]) {
samplers[0] = samplers[2];
@@ -149,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_sampler_view *sampler_views[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
@@ -179,10 +206,7 @@ static void setup_samplers(struct shader *shader)
if (shader->drawing_image && shader->image)
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_fragment_sampler_views(ctx->cso_context, 4, sampler_views);
- }
+ return (num) ? 4 : 0;
}
static INLINE VGboolean is_format_bw(struct shader *shader)
@@ -227,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 */
@@ -246,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)
@@ -309,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);
+}