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 **************************************************************************/
27 #include "vg_context.h"
31 #include "shaders_cache.h"
34 #include "st_inlines.h"
35 #include "vg_manager.h"
38 #include "pipe/p_context.h"
39 #include "util/u_inlines.h"
41 #include "cso_cache/cso_context.h"
43 #include "util/u_simple_shaders.h"
44 #include "util/u_memory.h"
45 #include "util/u_blit.h"
46 #include "util/u_sampler.h"
48 struct vg_context
*_vg_context
= 0;
50 struct vg_context
* vg_current_context(void)
55 static void init_clear(struct vg_context
*st
)
57 struct pipe_context
*pipe
= st
->pipe
;
59 /* rasterizer state: bypass clipping */
60 memset(&st
->clear
.raster
, 0, sizeof(st
->clear
.raster
));
61 st
->clear
.raster
.gl_rasterization_rules
= 1;
63 /* fragment shader state: color pass-through program */
65 util_make_fragment_passthrough_shader(pipe
);
69 * A depth/stencil rb will be needed regardless of what the visual says.
72 choose_depth_stencil_format(struct vg_context
*ctx
)
74 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
75 enum pipe_format formats
[] = {
76 PIPE_FORMAT_Z24_UNORM_S8_USCALED
,
77 PIPE_FORMAT_S8_USCALED_Z24_UNORM
,
80 enum pipe_format
*fmt
;
82 for (fmt
= formats
; *fmt
!= PIPE_FORMAT_NONE
; fmt
++) {
83 if (screen
->is_format_supported(screen
, *fmt
,
84 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
, 0))
88 ctx
->ds_format
= *fmt
;
90 return (ctx
->ds_format
!= PIPE_FORMAT_NONE
);
93 void vg_set_current_context(struct vg_context
*ctx
)
96 api_make_dispatch_current((ctx
) ? ctx
->dispatch
: NULL
);
99 struct vg_context
* vg_create_context(struct pipe_context
*pipe
,
101 struct vg_context
*share
)
103 struct vg_context
*ctx
;
106 ctx
= CALLOC_STRUCT(vg_context
);
109 if (!choose_depth_stencil_format(ctx
)) {
114 ctx
->dispatch
= api_create_dispatch();
116 vg_init_state(&ctx
->state
.vg
);
117 ctx
->state
.dirty
= ALL_DIRTY
;
119 ctx
->cso_context
= cso_create_context(pipe
);
123 ctx
->default_paint
= paint_create(ctx
);
124 ctx
->state
.vg
.stroke_paint
= ctx
->default_paint
;
125 ctx
->state
.vg
.fill_paint
= ctx
->default_paint
;
128 ctx
->mask
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
129 ctx
->mask
.sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
130 ctx
->mask
.sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
131 ctx
->mask
.sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
132 ctx
->mask
.sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
133 ctx
->mask
.sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
134 ctx
->mask
.sampler
.normalized_coords
= 0;
136 ctx
->blend_sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
137 ctx
->blend_sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
138 ctx
->blend_sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
139 ctx
->blend_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
140 ctx
->blend_sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
141 ctx
->blend_sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
142 ctx
->blend_sampler
.normalized_coords
= 0;
144 for (i
= 0; i
< 2; i
++) {
145 ctx
->velems
[i
].src_offset
= i
* 4 * sizeof(float);
146 ctx
->velems
[i
].instance_divisor
= 0;
147 ctx
->velems
[i
].vertex_buffer_index
= 0;
148 ctx
->velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
151 vg_set_error(ctx
, VG_NO_ERROR
);
153 ctx
->owned_objects
[VG_OBJECT_PAINT
] = cso_hash_create();
154 ctx
->owned_objects
[VG_OBJECT_IMAGE
] = cso_hash_create();
155 ctx
->owned_objects
[VG_OBJECT_MASK
] = cso_hash_create();
156 ctx
->owned_objects
[VG_OBJECT_FONT
] = cso_hash_create();
157 ctx
->owned_objects
[VG_OBJECT_PATH
] = cso_hash_create();
159 ctx
->renderer
= renderer_create(ctx
);
160 ctx
->sc
= shaders_cache_create(ctx
);
161 ctx
->shader
= shader_create(ctx
);
163 ctx
->blit
= util_create_blit(ctx
->pipe
, ctx
->cso_context
);
168 void vg_destroy_context(struct vg_context
*ctx
)
170 struct pipe_resource
**cbuf
= &ctx
->mask
.cbuf
;
171 struct pipe_resource
**vsbuf
= &ctx
->vs_const_buffer
;
173 util_destroy_blit(ctx
->blit
);
174 renderer_destroy(ctx
->renderer
);
175 shaders_cache_destroy(ctx
->sc
);
176 shader_destroy(ctx
->shader
);
177 paint_destroy(ctx
->default_paint
);
180 pipe_resource_reference(cbuf
, NULL
);
183 pipe_resource_reference(vsbuf
, NULL
);
186 cso_delete_fragment_shader(ctx
->cso_context
, ctx
->clear
.fs
);
187 ctx
->clear
.fs
= NULL
;
191 vg_shader_destroy(ctx
, ctx
->plain_vs
);
192 ctx
->plain_vs
= NULL
;
195 vg_shader_destroy(ctx
, ctx
->clear_vs
);
196 ctx
->clear_vs
= NULL
;
198 if (ctx
->texture_vs
) {
199 vg_shader_destroy(ctx
, ctx
->texture_vs
);
200 ctx
->texture_vs
= NULL
;
203 if (ctx
->pass_through_depth_fs
)
204 vg_shader_destroy(ctx
, ctx
->pass_through_depth_fs
);
205 if (ctx
->mask
.union_fs
)
206 vg_shader_destroy(ctx
, ctx
->mask
.union_fs
);
207 if (ctx
->mask
.intersect_fs
)
208 vg_shader_destroy(ctx
, ctx
->mask
.intersect_fs
);
209 if (ctx
->mask
.subtract_fs
)
210 vg_shader_destroy(ctx
, ctx
->mask
.subtract_fs
);
211 if (ctx
->mask
.set_fs
)
212 vg_shader_destroy(ctx
, ctx
->mask
.set_fs
);
214 cso_release_all(ctx
->cso_context
);
215 cso_destroy_context(ctx
->cso_context
);
217 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PAINT
]);
218 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_IMAGE
]);
219 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_MASK
]);
220 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_FONT
]);
221 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PATH
]);
223 api_destroy_dispatch(ctx
->dispatch
);
228 void vg_init_object(struct vg_object
*obj
, struct vg_context
*ctx
, enum vg_object_type type
)
234 VGboolean
vg_context_is_object_valid(struct vg_context
*ctx
,
235 enum vg_object_type type
,
239 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
242 return cso_hash_contains(hash
, (unsigned)(long)ptr
);
247 void vg_context_add_object(struct vg_context
*ctx
,
248 enum vg_object_type type
,
252 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
255 cso_hash_insert(hash
, (unsigned)(long)ptr
, ptr
);
259 void vg_context_remove_object(struct vg_context
*ctx
,
260 enum vg_object_type type
,
264 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
267 cso_hash_take(hash
, (unsigned)(long)ptr
);
271 static void update_clip_state(struct vg_context
*ctx
)
273 struct pipe_depth_stencil_alpha_state
*dsa
= &ctx
->state
.g3d
.dsa
;
274 struct vg_state
*state
= &ctx
->state
.vg
;
276 memset(dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
278 if (state
->scissoring
) {
279 struct pipe_blend_state
*blend
= &ctx
->state
.g3d
.blend
;
280 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
283 dsa
->depth
.writemask
= 1;/*glDepthMask(TRUE);*/
284 dsa
->depth
.func
= PIPE_FUNC_ALWAYS
;
285 dsa
->depth
.enabled
= 1;
287 cso_save_blend(ctx
->cso_context
);
288 cso_save_fragment_shader(ctx
->cso_context
);
289 /* set a passthrough shader */
290 if (!ctx
->pass_through_depth_fs
)
291 ctx
->pass_through_depth_fs
= shader_create_from_text(ctx
->pipe
,
292 pass_through_depth_asm
,
294 PIPE_SHADER_FRAGMENT
);
295 cso_set_fragment_shader_handle(ctx
->cso_context
,
296 ctx
->pass_through_depth_fs
->driver
);
297 cso_set_depth_stencil_alpha(ctx
->cso_context
, dsa
);
299 ctx
->pipe
->clear(ctx
->pipe
, PIPE_CLEAR_DEPTHSTENCIL
, NULL
, 1.0, 0);
301 /* disable color writes */
302 blend
->rt
[0].colormask
= 0; /*disable colorwrites*/
303 cso_set_blend(ctx
->cso_context
, blend
);
305 /* enable scissoring */
306 for (i
= 0; i
< state
->scissor_rects_num
; ++i
) {
307 const float x
= state
->scissor_rects
[i
* 4 + 0].f
;
308 const float y
= state
->scissor_rects
[i
* 4 + 1].f
;
309 const float width
= state
->scissor_rects
[i
* 4 + 2].f
;
310 const float height
= state
->scissor_rects
[i
* 4 + 3].f
;
311 VGfloat minx
, miny
, maxx
, maxy
;
323 if (x
+ width
< maxx
)
325 if (y
+ height
< maxy
)
328 /* check for null space */
329 if (minx
>= maxx
|| miny
>= maxy
)
330 minx
= miny
= maxx
= maxy
= 0;
332 /*glClear(GL_DEPTH_BUFFER_BIT);*/
333 renderer_draw_quad(ctx
->renderer
, minx
, miny
, maxx
, maxy
, 0.0f
);
336 cso_restore_blend(ctx
->cso_context
);
337 cso_restore_fragment_shader(ctx
->cso_context
);
339 dsa
->depth
.enabled
= 1; /* glEnable(GL_DEPTH_TEST); */
340 dsa
->depth
.writemask
= 0;/*glDepthMask(FALSE);*/
341 dsa
->depth
.func
= PIPE_FUNC_GEQUAL
;
345 void vg_validate_state(struct vg_context
*ctx
)
347 vg_manager_validate_framebuffer(ctx
);
349 if ((ctx
->state
.dirty
& BLEND_DIRTY
)) {
350 struct pipe_blend_state
*blend
= &ctx
->state
.g3d
.blend
;
351 memset(blend
, 0, sizeof(struct pipe_blend_state
));
352 blend
->rt
[0].blend_enable
= 1;
353 blend
->rt
[0].colormask
= PIPE_MASK_RGBA
;
355 switch (ctx
->state
.vg
.blend_mode
) {
357 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
358 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
359 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
360 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
361 blend
->rt
[0].blend_enable
= 0;
363 case VG_BLEND_SRC_OVER
:
364 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
365 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
366 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
367 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
369 case VG_BLEND_DST_OVER
:
370 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_INV_DST_ALPHA
;
371 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_INV_DST_ALPHA
;
372 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_DST_ALPHA
;
373 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_DST_ALPHA
;
375 case VG_BLEND_SRC_IN
:
376 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_DST_ALPHA
;
377 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_DST_ALPHA
;
378 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
379 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
381 case VG_BLEND_DST_IN
:
382 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ZERO
;
383 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ZERO
;
384 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
385 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
387 case VG_BLEND_MULTIPLY
:
388 case VG_BLEND_SCREEN
:
389 case VG_BLEND_DARKEN
:
390 case VG_BLEND_LIGHTEN
:
391 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
392 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
393 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
394 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
395 blend
->rt
[0].blend_enable
= 0;
397 case VG_BLEND_ADDITIVE
:
398 blend
->rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
399 blend
->rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
400 blend
->rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ONE
;
401 blend
->rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
404 assert(!"not implemented blend mode");
406 cso_set_blend(ctx
->cso_context
, &ctx
->state
.g3d
.blend
);
408 if ((ctx
->state
.dirty
& RASTERIZER_DIRTY
)) {
409 struct pipe_rasterizer_state
*raster
= &ctx
->state
.g3d
.rasterizer
;
410 memset(raster
, 0, sizeof(struct pipe_rasterizer_state
));
411 raster
->gl_rasterization_rules
= 1;
412 cso_set_rasterizer(ctx
->cso_context
, &ctx
->state
.g3d
.rasterizer
);
414 if ((ctx
->state
.dirty
& VIEWPORT_DIRTY
)) {
415 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
416 const VGint param_bytes
= 8 * sizeof(VGfloat
);
417 VGfloat vs_consts
[8] = {
418 2.f
/fb
->width
, 2.f
/fb
->height
, 1, 1,
421 struct pipe_resource
**cbuf
= &ctx
->vs_const_buffer
;
423 vg_set_viewport(ctx
, VEGA_Y0_BOTTOM
);
425 pipe_resource_reference(cbuf
, NULL
);
426 *cbuf
= pipe_buffer_create(ctx
->pipe
->screen
,
427 PIPE_BIND_CONSTANT_BUFFER
,
431 st_no_flush_pipe_buffer_write(ctx
, *cbuf
,
432 0, param_bytes
, vs_consts
);
434 ctx
->pipe
->set_constant_buffer(ctx
->pipe
, PIPE_SHADER_VERTEX
, 0, *cbuf
);
436 if ((ctx
->state
.dirty
& VS_DIRTY
)) {
437 cso_set_vertex_shader_handle(ctx
->cso_context
,
441 /* must be last because it renders to the depth buffer*/
442 if ((ctx
->state
.dirty
& DEPTH_STENCIL_DIRTY
)) {
443 update_clip_state(ctx
);
444 cso_set_depth_stencil_alpha(ctx
->cso_context
, &ctx
->state
.g3d
.dsa
);
447 shader_set_masking(ctx
->shader
, ctx
->state
.vg
.masking
);
448 shader_set_image_mode(ctx
->shader
, ctx
->state
.vg
.image_mode
);
450 ctx
->state
.dirty
= NONE_DIRTY
;
453 VGboolean
vg_object_is_valid(void *ptr
, enum vg_object_type type
)
455 struct vg_object
*obj
= ptr
;
456 if (ptr
&& is_aligned(obj
) && obj
->type
== type
)
462 void vg_set_error(struct vg_context
*ctx
,
465 /*vgGetError returns the oldest error code provided by
466 * an API call on the current context since the previous
467 * call to vgGetError on that context (or since the creation
469 if (ctx
->_error
== VG_NO_ERROR
)
473 void vg_prepare_blend_surface(struct vg_context
*ctx
)
475 struct pipe_surface
*dest_surface
= NULL
;
476 struct pipe_context
*pipe
= ctx
->pipe
;
477 struct pipe_sampler_view
*view
;
478 struct pipe_sampler_view view_templ
;
479 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
480 struct st_renderbuffer
*strb
= stfb
->strb
;
482 /* first finish all pending rendering */
485 u_sampler_view_default_template(&view_templ
, strb
->texture
, strb
->texture
->format
);
486 view
= pipe
->create_sampler_view(pipe
, strb
->texture
, &view_templ
);
488 dest_surface
= pipe
->screen
->get_tex_surface(pipe
->screen
,
489 stfb
->blend_texture_view
->texture
,
491 PIPE_BIND_RENDER_TARGET
);
492 /* flip it, because we want to use it as a sampler */
493 util_blit_pixels_tex(ctx
->blit
,
499 strb
->width
, strb
->height
,
500 0.0, PIPE_TEX_MIPFILTER_NEAREST
);
503 pipe_surface_reference(&dest_surface
, NULL
);
505 /* make sure it's complete */
508 pipe_sampler_view_reference(&view
, NULL
);
512 void vg_prepare_blend_surface_from_mask(struct vg_context
*ctx
)
514 struct pipe_surface
*dest_surface
= NULL
;
515 struct pipe_context
*pipe
= ctx
->pipe
;
516 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
517 struct st_renderbuffer
*strb
= stfb
->strb
;
519 vg_validate_state(ctx
);
521 /* first finish all pending rendering */
524 dest_surface
= pipe
->screen
->get_tex_surface(pipe
->screen
,
525 stfb
->blend_texture_view
->texture
,
527 PIPE_BIND_RENDER_TARGET
);
529 /* flip it, because we want to use it as a sampler */
530 util_blit_pixels_tex(ctx
->blit
,
531 stfb
->alpha_mask_view
,
536 strb
->width
, strb
->height
,
537 0.0, PIPE_TEX_MIPFILTER_NEAREST
);
539 /* make sure it's complete */
543 pipe_surface_reference(&dest_surface
, NULL
);
546 void * vg_plain_vs(struct vg_context
*ctx
)
548 if (!ctx
->plain_vs
) {
549 ctx
->plain_vs
= shader_create_from_text(ctx
->pipe
,
555 return ctx
->plain_vs
->driver
;
559 void * vg_clear_vs(struct vg_context
*ctx
)
561 if (!ctx
->clear_vs
) {
562 ctx
->clear_vs
= shader_create_from_text(ctx
->pipe
,
568 return ctx
->clear_vs
->driver
;
571 void * vg_texture_vs(struct vg_context
*ctx
)
573 if (!ctx
->texture_vs
) {
574 ctx
->texture_vs
= shader_create_from_text(ctx
->pipe
,
580 return ctx
->texture_vs
->driver
;
583 void vg_set_viewport(struct vg_context
*ctx
, VegaOrientation orientation
)
585 struct pipe_viewport_state viewport
;
586 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
587 VGfloat y_scale
= (orientation
== VEGA_Y0_BOTTOM
) ? -2.f
: 2.f
;
589 viewport
.scale
[0] = fb
->width
/ 2.f
;
590 viewport
.scale
[1] = fb
->height
/ y_scale
;
591 viewport
.scale
[2] = 1.0;
592 viewport
.scale
[3] = 1.0;
593 viewport
.translate
[0] = fb
->width
/ 2.f
;
594 viewport
.translate
[1] = fb
->height
/ 2.f
;
595 viewport
.translate
[2] = 0.0;
596 viewport
.translate
[3] = 0.0;
598 cso_set_viewport(ctx
->cso_context
, &viewport
);