1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
29 #include "vg_context.h"
30 #include "shaders_cache.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "pipe/p_state.h"
38 #include "util/u_inlines.h"
39 #include "util/u_memory.h"
41 #define MAX_CONSTANTS 20
44 struct vg_context *context;
47 struct vg_paint *paint;
48 struct vg_image *image;
50 VGboolean drawing_image;
51 VGImageMode image_mode;
53 float constants[MAX_CONSTANTS];
54 struct pipe_resource *cbuf;
55 struct pipe_shader_state fs_state;
59 struct shader * shader_create(struct vg_context *ctx)
61 struct shader *shader = 0;
63 shader = CALLOC_STRUCT(shader);
64 shader->context = ctx;
69 void shader_destroy(struct shader *shader)
74 void shader_set_masking(struct shader *shader, VGboolean set)
76 shader->masking = set;
79 VGboolean shader_is_masking(struct shader *shader)
81 return shader->masking;
84 void shader_set_paint(struct shader *shader, struct vg_paint *paint)
86 shader->paint = paint;
89 struct vg_paint * shader_paint(struct shader *shader)
95 static void setup_constant_buffer(struct shader *shader)
97 struct vg_context *ctx = shader->context;
98 struct pipe_context *pipe = shader->context->pipe;
99 struct pipe_resource **cbuf = &shader->cbuf;
100 VGint param_bytes = paint_constant_buffer_size(shader->paint);
101 float temp_buf[MAX_CONSTANTS];
103 assert(param_bytes <= sizeof(temp_buf));
104 paint_fill_constant_buffer(shader->paint, temp_buf);
107 memcmp(temp_buf, shader->constants, param_bytes) != 0)
109 pipe_resource_reference(cbuf, NULL);
111 memcpy(shader->constants, temp_buf, param_bytes);
112 *cbuf = pipe_user_buffer_create(pipe->screen,
114 sizeof(shader->constants),
115 PIPE_BIND_VERTEX_BUFFER);
118 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
121 static VGint blend_bind_samplers(struct vg_context *ctx,
122 struct pipe_sampler_state **samplers,
123 struct pipe_sampler_view **sampler_views)
125 VGBlendMode bmode = ctx->state.vg.blend_mode;
127 if (bmode == VG_BLEND_MULTIPLY ||
128 bmode == VG_BLEND_SCREEN ||
129 bmode == VG_BLEND_DARKEN ||
130 bmode == VG_BLEND_LIGHTEN) {
131 struct st_framebuffer *stfb = ctx->draw_buffer;
133 vg_prepare_blend_surface(ctx);
135 samplers[2] = &ctx->blend_sampler;
136 sampler_views[2] = stfb->blend_texture_view;
138 if (!samplers[0] || !sampler_views[0]) {
139 samplers[0] = samplers[2];
140 sampler_views[0] = sampler_views[2];
142 if (!samplers[1] || !sampler_views[1]) {
143 samplers[1] = samplers[0];
144 sampler_views[1] = sampler_views[0];
152 static void setup_samplers(struct shader *shader)
154 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
155 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
156 struct vg_context *ctx = shader->context;
157 /* a little wonky: we use the num as a boolean that just says
158 * whether any sampler/textures have been set. the actual numbering
159 * for samplers is always the same:
160 * 0 - paint sampler/texture for gradient/pattern
161 * 1 - mask sampler/texture
162 * 2 - blend sampler/texture
163 * 3 - image sampler/texture
171 sampler_views[0] = NULL;
172 sampler_views[1] = NULL;
173 sampler_views[2] = NULL;
174 sampler_views[3] = NULL;
176 num += paint_bind_samplers(shader->paint, samplers, sampler_views);
177 num += mask_bind_samplers(samplers, sampler_views);
178 num += blend_bind_samplers(ctx, samplers, sampler_views);
179 if (shader->drawing_image && shader->image)
180 num += image_bind_samplers(shader->image, samplers, sampler_views);
183 cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
184 cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views);
188 static INLINE VGboolean is_format_bw(struct shader *shader)
191 struct vg_context *ctx = shader->context;
192 struct st_framebuffer *stfb = ctx->draw_buffer;
195 if (shader->drawing_image && shader->image) {
196 if (shader->image->format == VG_BW_1)
203 static void setup_shader_program(struct shader *shader)
205 struct vg_context *ctx = shader->context;
207 VGBlendMode blend_mode = ctx->state.vg.blend_mode;
208 VGboolean black_white = is_format_bw(shader);
210 /* 1st stage: fill */
211 if (!shader->drawing_image ||
212 (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) {
213 switch(paint_type(shader->paint)) {
214 case VG_PAINT_TYPE_COLOR:
215 shader_id |= VEGA_SOLID_FILL_SHADER;
217 case VG_PAINT_TYPE_LINEAR_GRADIENT:
218 shader_id |= VEGA_LINEAR_GRADIENT_SHADER;
220 case VG_PAINT_TYPE_RADIAL_GRADIENT:
221 shader_id |= VEGA_RADIAL_GRADIENT_SHADER;
223 case VG_PAINT_TYPE_PATTERN:
224 shader_id |= VEGA_PATTERN_SHADER;
232 /* second stage image */
233 if (shader->drawing_image) {
234 switch(shader->image_mode) {
235 case VG_DRAW_IMAGE_NORMAL:
236 shader_id |= VEGA_IMAGE_NORMAL_SHADER;
238 case VG_DRAW_IMAGE_MULTIPLY:
239 shader_id |= VEGA_IMAGE_MULTIPLY_SHADER;
241 case VG_DRAW_IMAGE_STENCIL:
242 shader_id |= VEGA_IMAGE_STENCIL_SHADER;
245 debug_printf("Unknown image mode!");
250 shader_id |= VEGA_MASK_SHADER;
253 case VG_BLEND_MULTIPLY:
254 shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
256 case VG_BLEND_SCREEN:
257 shader_id |= VEGA_BLEND_SCREEN_SHADER;
259 case VG_BLEND_DARKEN:
260 shader_id |= VEGA_BLEND_DARKEN_SHADER;
262 case VG_BLEND_LIGHTEN:
263 shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
266 /* handled by pipe_blend_state */
271 shader_id |= VEGA_BW_SHADER;
273 shader->fs = shaders_cache_fill(ctx->sc, shader_id);
274 cso_set_fragment_shader_handle(ctx->cso_context, shader->fs);
278 void shader_bind(struct shader *shader)
280 /* first resolve the real paint type */
281 paint_resolve_type(shader->paint);
283 setup_constant_buffer(shader);
284 setup_samplers(shader);
285 setup_shader_program(shader);
288 void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
290 shader->image_mode = image_mode;
293 VGImageMode shader_image_mode(struct shader *shader)
295 return shader->image_mode;
298 void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image)
300 shader->drawing_image = drawing_image;
303 VGboolean shader_drawing_image(struct shader *shader)
305 return shader->drawing_image;
308 void shader_set_image(struct shader *shader, struct vg_image *img)