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"
36 #include "pipe/p_context.h"
37 #include "pipe/p_state.h"
38 #include "util/u_memory.h"
39 #include "util/u_math.h"
40 #include "util/u_format.h"
42 #define MAX_CONSTANTS 28
45 struct vg_context
*context
;
47 VGboolean color_transform
;
49 struct vg_paint
*paint
;
50 struct vg_image
*image
;
52 struct matrix modelview
;
53 struct matrix paint_matrix
;
55 VGboolean drawing_image
;
56 VGImageMode image_mode
;
58 float constants
[MAX_CONSTANTS
];
59 struct pipe_resource
*cbuf
;
60 struct pipe_shader_state fs_state
;
64 struct shader
* shader_create(struct vg_context
*ctx
)
66 struct shader
*shader
= 0;
68 shader
= CALLOC_STRUCT(shader
);
69 shader
->context
= ctx
;
74 void shader_destroy(struct shader
*shader
)
79 void shader_set_color_transform(struct shader
*shader
, VGboolean set
)
81 shader
->color_transform
= set
;
84 void shader_set_masking(struct shader
*shader
, VGboolean set
)
86 shader
->masking
= set
;
89 VGboolean
shader_is_masking(struct shader
*shader
)
91 return shader
->masking
;
94 void shader_set_paint(struct shader
*shader
, struct vg_paint
*paint
)
96 shader
->paint
= paint
;
99 struct vg_paint
* shader_paint(struct shader
*shader
)
101 return shader
->paint
;
104 static VGint
setup_constant_buffer(struct shader
*shader
)
106 const struct vg_state
*state
= &shader
->context
->state
.vg
;
107 VGint param_bytes
= paint_constant_buffer_size(shader
->paint
);
110 param_bytes
+= sizeof(VGfloat
) * 8;
111 assert(param_bytes
<= sizeof(shader
->constants
));
113 if (state
->color_transform
) {
114 for (i
= 0; i
< 8; i
++) {
115 VGfloat val
= (i
< 4) ? 127.0f
: 1.0f
;
116 shader
->constants
[i
] =
117 CLAMP(state
->color_transform_values
[i
], -val
, val
);
121 memset(shader
->constants
, 0, sizeof(VGfloat
) * 8);
124 paint_fill_constant_buffer(shader
->paint
,
125 &shader
->paint_matrix
, shader
->constants
+ 8);
130 static VGboolean
blend_use_shader(struct vg_context
*ctx
)
132 VGboolean advanced_blending
;
134 switch (ctx
->state
.vg
.blend_mode
) {
135 case VG_BLEND_SRC_OVER
:
137 util_format_has_alpha(ctx
->draw_buffer
->strb
->format
);
139 case VG_BLEND_DST_OVER
:
140 case VG_BLEND_MULTIPLY
:
141 case VG_BLEND_SCREEN
:
142 case VG_BLEND_DARKEN
:
143 case VG_BLEND_LIGHTEN
:
144 case VG_BLEND_ADDITIVE
:
145 advanced_blending
= VG_TRUE
;
148 advanced_blending
= VG_FALSE
;
152 return advanced_blending
;
155 static VGint
blend_bind_samplers(struct vg_context
*ctx
,
156 struct pipe_sampler_state
**samplers
,
157 struct pipe_sampler_view
**sampler_views
)
159 if (blend_use_shader(ctx
)) {
160 samplers
[2] = &ctx
->blend_sampler
;
161 sampler_views
[2] = vg_prepare_blend_surface(ctx
);
163 if (!samplers
[0] || !sampler_views
[0]) {
164 samplers
[0] = samplers
[2];
165 sampler_views
[0] = sampler_views
[2];
167 if (!samplers
[1] || !sampler_views
[1]) {
168 samplers
[1] = samplers
[0];
169 sampler_views
[1] = sampler_views
[0];
177 static VGint
setup_samplers(struct shader
*shader
,
178 struct pipe_sampler_state
**samplers
,
179 struct pipe_sampler_view
**sampler_views
)
181 struct vg_context
*ctx
= shader
->context
;
182 /* a little wonky: we use the num as a boolean that just says
183 * whether any sampler/textures have been set. the actual numbering
184 * for samplers is always the same:
185 * 0 - paint sampler/texture for gradient/pattern
186 * 1 - mask sampler/texture
187 * 2 - blend sampler/texture
188 * 3 - image sampler/texture
196 sampler_views
[0] = NULL
;
197 sampler_views
[1] = NULL
;
198 sampler_views
[2] = NULL
;
199 sampler_views
[3] = NULL
;
201 num
+= paint_bind_samplers(shader
->paint
, samplers
, sampler_views
);
202 num
+= mask_bind_samplers(samplers
, sampler_views
);
203 num
+= blend_bind_samplers(ctx
, samplers
, sampler_views
);
204 if (shader
->drawing_image
&& shader
->image
)
205 num
+= image_bind_samplers(shader
->image
, samplers
, sampler_views
);
207 return (num
) ? 4 : 0;
210 static INLINE VGboolean
is_format_bw(struct shader
*shader
)
213 struct vg_context
*ctx
= shader
->context
;
214 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
217 if (shader
->drawing_image
&& shader
->image
) {
218 if (shader
->image
->format
== VG_BW_1
)
225 static void setup_shader_program(struct shader
*shader
)
227 struct vg_context
*ctx
= shader
->context
;
229 VGBlendMode blend_mode
= ctx
->state
.vg
.blend_mode
;
230 VGboolean black_white
= is_format_bw(shader
);
232 /* 1st stage: fill */
233 if (!shader
->drawing_image
||
234 (shader
->image_mode
== VG_DRAW_IMAGE_MULTIPLY
|| shader
->image_mode
== VG_DRAW_IMAGE_STENCIL
)) {
235 switch(paint_type(shader
->paint
)) {
236 case VG_PAINT_TYPE_COLOR
:
237 shader_id
|= VEGA_SOLID_FILL_SHADER
;
239 case VG_PAINT_TYPE_LINEAR_GRADIENT
:
240 shader_id
|= VEGA_LINEAR_GRADIENT_SHADER
;
242 case VG_PAINT_TYPE_RADIAL_GRADIENT
:
243 shader_id
|= VEGA_RADIAL_GRADIENT_SHADER
;
245 case VG_PAINT_TYPE_PATTERN
:
246 shader_id
|= VEGA_PATTERN_SHADER
;
253 if (paint_is_degenerate(shader
->paint
))
254 shader_id
= VEGA_PAINT_DEGENERATE_SHADER
;
257 /* second stage image */
258 if (shader
->drawing_image
) {
259 switch(shader
->image_mode
) {
260 case VG_DRAW_IMAGE_NORMAL
:
261 shader_id
|= VEGA_IMAGE_NORMAL_SHADER
;
263 case VG_DRAW_IMAGE_MULTIPLY
:
264 shader_id
|= VEGA_IMAGE_MULTIPLY_SHADER
;
266 case VG_DRAW_IMAGE_STENCIL
:
267 shader_id
|= VEGA_IMAGE_STENCIL_SHADER
;
270 debug_printf("Unknown image mode!");
274 if (shader
->color_transform
)
275 shader_id
|= VEGA_COLOR_TRANSFORM_SHADER
;
277 if (blend_use_shader(ctx
)) {
278 if (shader
->drawing_image
&& shader
->image_mode
== VG_DRAW_IMAGE_STENCIL
)
279 shader_id
|= VEGA_ALPHA_PER_CHANNEL_SHADER
;
281 shader_id
|= VEGA_ALPHA_NORMAL_SHADER
;
285 shader_id
|= VEGA_BLEND_SRC_SHADER
;
287 case VG_BLEND_SRC_OVER
:
288 shader_id
|= VEGA_BLEND_SRC_OVER_SHADER
;
290 case VG_BLEND_DST_OVER
:
291 shader_id
|= VEGA_BLEND_DST_OVER_SHADER
;
293 case VG_BLEND_SRC_IN
:
294 shader_id
|= VEGA_BLEND_SRC_IN_SHADER
;
296 case VG_BLEND_DST_IN
:
297 shader_id
|= VEGA_BLEND_DST_IN_SHADER
;
299 case VG_BLEND_MULTIPLY
:
300 shader_id
|= VEGA_BLEND_MULTIPLY_SHADER
;
302 case VG_BLEND_SCREEN
:
303 shader_id
|= VEGA_BLEND_SCREEN_SHADER
;
305 case VG_BLEND_DARKEN
:
306 shader_id
|= VEGA_BLEND_DARKEN_SHADER
;
308 case VG_BLEND_LIGHTEN
:
309 shader_id
|= VEGA_BLEND_LIGHTEN_SHADER
;
311 case VG_BLEND_ADDITIVE
:
312 shader_id
|= VEGA_BLEND_ADDITIVE_SHADER
;
320 /* update alpha of the source */
321 if (shader
->drawing_image
&& shader
->image_mode
== VG_DRAW_IMAGE_STENCIL
)
322 shader_id
|= VEGA_ALPHA_PER_CHANNEL_SHADER
;
326 shader_id
|= VEGA_MASK_SHADER
;
329 shader_id
|= VEGA_BW_SHADER
;
331 shader
->fs
= shaders_cache_fill(ctx
->sc
, shader_id
);
335 void shader_bind(struct shader
*shader
)
337 struct vg_context
*ctx
= shader
->context
;
338 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
339 struct pipe_sampler_view
*sampler_views
[PIPE_MAX_SAMPLERS
];
340 VGint num_samplers
, param_bytes
;
342 /* first resolve the real paint type */
343 paint_resolve_type(shader
->paint
);
345 num_samplers
= setup_samplers(shader
, samplers
, sampler_views
);
346 param_bytes
= setup_constant_buffer(shader
);
347 setup_shader_program(shader
);
349 renderer_validate_for_shader(ctx
->renderer
,
350 (const struct pipe_sampler_state
**) samplers
,
351 sampler_views
, num_samplers
,
353 shader
->fs
, (const void *) shader
->constants
, param_bytes
);
356 void shader_set_image_mode(struct shader
*shader
, VGImageMode image_mode
)
358 shader
->image_mode
= image_mode
;
361 VGImageMode
shader_image_mode(struct shader
*shader
)
363 return shader
->image_mode
;
366 void shader_set_drawing_image(struct shader
*shader
, VGboolean drawing_image
)
368 shader
->drawing_image
= drawing_image
;
371 VGboolean
shader_drawing_image(struct shader
*shader
)
373 return shader
->drawing_image
;
376 void shader_set_image(struct shader
*shader
, struct vg_image
*img
)
382 * Set the transformation to map a vertex to the surface coordinates.
384 void shader_set_surface_matrix(struct shader
*shader
,
385 const struct matrix
*mat
)
387 shader
->modelview
= *mat
;
391 * Set the transformation to map a pixel to the paint coordinates.
393 void shader_set_paint_matrix(struct shader
*shader
, const struct matrix
*mat
)
395 const struct st_framebuffer
*stfb
= shader
->context
->draw_buffer
;
396 const VGfloat px_center_offset
= 0.5f
;
398 memcpy(&shader
->paint_matrix
, mat
, sizeof(*mat
));
400 /* make it window-to-paint for the shaders */
401 matrix_translate(&shader
->paint_matrix
, px_center_offset
,
402 stfb
->height
- 1.0f
+ px_center_offset
);
403 matrix_scale(&shader
->paint_matrix
, 1.0f
, -1.0f
);