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 "pipe/p_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_constant_buffer 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_constant_buffer
*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
);
106 if (cbuf
->buffer
== NULL
||
107 memcmp(temp_buf
, shader
->constants
, param_bytes
) != 0)
109 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
111 memcpy(shader
->constants
, temp_buf
, param_bytes
);
112 cbuf
->buffer
= pipe_user_buffer_create(pipe
->screen
,
114 sizeof(shader
->constants
));
117 ctx
->pipe
->set_constant_buffer(ctx
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
120 static VGint
blend_bind_samplers(struct vg_context
*ctx
,
121 struct pipe_sampler_state
**samplers
,
122 struct pipe_texture
**textures
)
124 VGBlendMode bmode
= ctx
->state
.vg
.blend_mode
;
126 if (bmode
== VG_BLEND_MULTIPLY
||
127 bmode
== VG_BLEND_SCREEN
||
128 bmode
== VG_BLEND_DARKEN
||
129 bmode
== VG_BLEND_LIGHTEN
) {
130 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
132 vg_prepare_blend_surface(ctx
);
134 samplers
[2] = &ctx
->blend_sampler
;
135 textures
[2] = stfb
->blend_texture
;
137 if (!samplers
[0] || !textures
[0]) {
138 samplers
[1] = samplers
[2];
139 textures
[1] = textures
[2];
141 if (!samplers
[1] || !textures
[1]) {
142 samplers
[1] = samplers
[0];
143 textures
[1] = textures
[0];
151 static void setup_samplers(struct shader
*shader
)
153 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
154 struct pipe_texture
*textures
[PIPE_MAX_SAMPLERS
];
155 struct vg_context
*ctx
= shader
->context
;
156 /* a little wonky: we use the num as a boolean that just says
157 * whether any sampler/textures have been set. the actual numbering
158 * for samplers is always the same:
159 * 0 - paint sampler/texture for gradient/pattern
160 * 1 - mask sampler/texture
161 * 2 - blend sampler/texture
162 * 3 - image sampler/texture
175 num
+= paint_bind_samplers(shader
->paint
, samplers
, textures
);
176 num
+= mask_bind_samplers(samplers
, textures
);
177 num
+= blend_bind_samplers(ctx
, samplers
, textures
);
178 if (shader
->drawing_image
&& shader
->image
)
179 num
+= image_bind_samplers(shader
->image
, samplers
, textures
);
182 cso_set_samplers(ctx
->cso_context
, 4, (const struct pipe_sampler_state
**)samplers
);
183 cso_set_sampler_textures(ctx
->cso_context
, 4, textures
);
187 static INLINE VGboolean
is_format_bw(struct shader
*shader
)
190 struct vg_context
*ctx
= shader
->context
;
191 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
194 if (shader
->drawing_image
&& shader
->image
) {
195 if (shader
->image
->format
== VG_BW_1
)
202 static void setup_shader_program(struct shader
*shader
)
204 struct vg_context
*ctx
= shader
->context
;
206 VGBlendMode blend_mode
= ctx
->state
.vg
.blend_mode
;
207 VGboolean black_white
= is_format_bw(shader
);
209 /* 1st stage: fill */
210 if (!shader
->drawing_image
||
211 (shader
->image_mode
== VG_DRAW_IMAGE_MULTIPLY
|| shader
->image_mode
== VG_DRAW_IMAGE_STENCIL
)) {
212 switch(paint_type(shader
->paint
)) {
213 case VG_PAINT_TYPE_COLOR
:
214 shader_id
|= VEGA_SOLID_FILL_SHADER
;
216 case VG_PAINT_TYPE_LINEAR_GRADIENT
:
217 shader_id
|= VEGA_LINEAR_GRADIENT_SHADER
;
219 case VG_PAINT_TYPE_RADIAL_GRADIENT
:
220 shader_id
|= VEGA_RADIAL_GRADIENT_SHADER
;
222 case VG_PAINT_TYPE_PATTERN
:
223 shader_id
|= VEGA_PATTERN_SHADER
;
231 /* second stage image */
232 if (shader
->drawing_image
) {
233 switch(shader
->image_mode
) {
234 case VG_DRAW_IMAGE_NORMAL
:
235 shader_id
|= VEGA_IMAGE_NORMAL_SHADER
;
237 case VG_DRAW_IMAGE_MULTIPLY
:
238 shader_id
|= VEGA_IMAGE_MULTIPLY_SHADER
;
240 case VG_DRAW_IMAGE_STENCIL
:
241 shader_id
|= VEGA_IMAGE_STENCIL_SHADER
;
244 debug_printf("Unknown image mode!");
249 shader_id
|= VEGA_MASK_SHADER
;
252 case VG_BLEND_MULTIPLY
:
253 shader_id
|= VEGA_BLEND_MULTIPLY_SHADER
;
255 case VG_BLEND_SCREEN
:
256 shader_id
|= VEGA_BLEND_SCREEN_SHADER
;
258 case VG_BLEND_DARKEN
:
259 shader_id
|= VEGA_BLEND_DARKEN_SHADER
;
261 case VG_BLEND_LIGHTEN
:
262 shader_id
|= VEGA_BLEND_LIGHTEN_SHADER
;
265 /* handled by pipe_blend_state */
270 shader_id
|= VEGA_BW_SHADER
;
272 shader
->fs
= shaders_cache_fill(ctx
->sc
, shader_id
);
273 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->fs
);
277 void shader_bind(struct shader
*shader
)
279 /* first resolve the real paint type */
280 paint_resolve_type(shader
->paint
);
282 setup_constant_buffer(shader
);
283 setup_samplers(shader
);
284 setup_shader_program(shader
);
287 void shader_set_image_mode(struct shader
*shader
, VGImageMode image_mode
)
289 shader
->image_mode
= image_mode
;
292 VGImageMode
shader_image_mode(struct shader
*shader
)
294 return shader
->image_mode
;
297 void shader_set_drawing_image(struct shader
*shader
, VGboolean drawing_image
)
299 shader
->drawing_image
= drawing_image
;
302 VGboolean
shader_drawing_image(struct shader
*shader
)
304 return shader
->drawing_image
;
307 void shader_set_image(struct shader
*shader
, struct vg_image
*img
)