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
)