X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fstate_trackers%2Fvega%2Fshader.c;h=bee6d84001d03de92430f5f3f660eef06808fa88;hb=d644a50dc328e54d513e4304378bb8c34148f7cc;hp=d9074a377b39588b3acbe8c2889a43de8e6c2a40;hpb=940ca2e837efe45caae1cf1d9665f6736347705d;p=mesa.git diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index d9074a377b3..bee6d84001d 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -31,27 +31,32 @@ #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); +}