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"
39 #include "pipe/p_context.h"
40 #include "util/u_inlines.h"
42 #include "cso_cache/cso_context.h"
44 #include "util/u_simple_shaders.h"
45 #include "util/u_memory.h"
46 #include "util/u_blit.h"
47 #include "util/u_sampler.h"
48 #include "util/u_format.h"
50 struct vg_context
*_vg_context
= 0;
52 struct vg_context
* vg_current_context(void)
58 * A depth/stencil rb will be needed regardless of what the visual says.
61 choose_depth_stencil_format(struct vg_context
*ctx
)
63 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
64 enum pipe_format formats
[] = {
65 PIPE_FORMAT_Z24_UNORM_S8_USCALED
,
66 PIPE_FORMAT_S8_USCALED_Z24_UNORM
,
69 enum pipe_format
*fmt
;
71 for (fmt
= formats
; *fmt
!= PIPE_FORMAT_NONE
; fmt
++) {
72 if (screen
->is_format_supported(screen
, *fmt
,
73 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
, 0))
77 ctx
->ds_format
= *fmt
;
79 return (ctx
->ds_format
!= PIPE_FORMAT_NONE
);
82 void vg_set_current_context(struct vg_context
*ctx
)
85 api_make_dispatch_current((ctx
) ? ctx
->dispatch
: NULL
);
88 struct vg_context
* vg_create_context(struct pipe_context
*pipe
,
90 struct vg_context
*share
)
92 struct vg_context
*ctx
;
94 ctx
= CALLOC_STRUCT(vg_context
);
97 if (!choose_depth_stencil_format(ctx
)) {
102 ctx
->dispatch
= api_create_dispatch();
104 vg_init_state(&ctx
->state
.vg
);
105 ctx
->state
.dirty
= ALL_DIRTY
;
107 ctx
->cso_context
= cso_create_context(pipe
);
109 ctx
->default_paint
= paint_create(ctx
);
110 ctx
->state
.vg
.stroke_paint
= ctx
->default_paint
;
111 ctx
->state
.vg
.fill_paint
= ctx
->default_paint
;
114 ctx
->mask
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
115 ctx
->mask
.sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
116 ctx
->mask
.sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
117 ctx
->mask
.sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
118 ctx
->mask
.sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
119 ctx
->mask
.sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
120 ctx
->mask
.sampler
.normalized_coords
= 0;
122 ctx
->blend_sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
123 ctx
->blend_sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
124 ctx
->blend_sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
125 ctx
->blend_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
126 ctx
->blend_sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
127 ctx
->blend_sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
128 ctx
->blend_sampler
.normalized_coords
= 0;
130 vg_set_error(ctx
, VG_NO_ERROR
);
132 ctx
->owned_objects
[VG_OBJECT_PAINT
] = cso_hash_create();
133 ctx
->owned_objects
[VG_OBJECT_IMAGE
] = cso_hash_create();
134 ctx
->owned_objects
[VG_OBJECT_MASK
] = cso_hash_create();
135 ctx
->owned_objects
[VG_OBJECT_FONT
] = cso_hash_create();
136 ctx
->owned_objects
[VG_OBJECT_PATH
] = cso_hash_create();
138 ctx
->renderer
= renderer_create(ctx
);
139 ctx
->sc
= shaders_cache_create(ctx
);
140 ctx
->shader
= shader_create(ctx
);
142 ctx
->blit
= util_create_blit(ctx
->pipe
, ctx
->cso_context
);
147 void vg_destroy_context(struct vg_context
*ctx
)
149 struct pipe_resource
**cbuf
= &ctx
->mask
.cbuf
;
151 util_destroy_blit(ctx
->blit
);
152 renderer_destroy(ctx
->renderer
);
153 shaders_cache_destroy(ctx
->sc
);
154 shader_destroy(ctx
->shader
);
155 paint_destroy(ctx
->default_paint
);
158 pipe_resource_reference(cbuf
, NULL
);
160 if (ctx
->mask
.union_fs
)
161 vg_shader_destroy(ctx
, ctx
->mask
.union_fs
);
162 if (ctx
->mask
.intersect_fs
)
163 vg_shader_destroy(ctx
, ctx
->mask
.intersect_fs
);
164 if (ctx
->mask
.subtract_fs
)
165 vg_shader_destroy(ctx
, ctx
->mask
.subtract_fs
);
166 if (ctx
->mask
.set_fs
)
167 vg_shader_destroy(ctx
, ctx
->mask
.set_fs
);
169 cso_release_all(ctx
->cso_context
);
170 cso_destroy_context(ctx
->cso_context
);
172 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PAINT
]);
173 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_IMAGE
]);
174 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_MASK
]);
175 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_FONT
]);
176 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PATH
]);
178 api_destroy_dispatch(ctx
->dispatch
);
183 void vg_init_object(struct vg_object
*obj
, struct vg_context
*ctx
, enum vg_object_type type
)
189 VGboolean
vg_context_is_object_valid(struct vg_context
*ctx
,
190 enum vg_object_type type
,
194 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
197 return cso_hash_contains(hash
, (unsigned)(long)ptr
);
202 void vg_context_add_object(struct vg_context
*ctx
,
203 enum vg_object_type type
,
207 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
210 cso_hash_insert(hash
, (unsigned)(long)ptr
, ptr
);
214 void vg_context_remove_object(struct vg_context
*ctx
,
215 enum vg_object_type type
,
219 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
222 cso_hash_take(hash
, (unsigned)(long)ptr
);
226 static struct pipe_resource
*
227 create_texture(struct pipe_context
*pipe
, enum pipe_format format
,
228 VGint width
, VGint height
)
230 struct pipe_resource templ
;
232 memset(&templ
, 0, sizeof(templ
));
234 if (format
!= PIPE_FORMAT_NONE
) {
235 templ
.format
= format
;
238 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
241 templ
.target
= PIPE_TEXTURE_2D
;
242 templ
.width0
= width
;
243 templ
.height0
= height
;
245 templ
.last_level
= 0;
247 if (util_format_get_component_bits(format
, UTIL_FORMAT_COLORSPACE_ZS
, 1)) {
248 templ
.bind
= PIPE_BIND_DEPTH_STENCIL
;
250 templ
.bind
= (PIPE_BIND_DISPLAY_TARGET
|
251 PIPE_BIND_RENDER_TARGET
|
252 PIPE_BIND_SAMPLER_VIEW
);
255 return pipe
->screen
->resource_create(pipe
->screen
, &templ
);
258 static struct pipe_sampler_view
*
259 create_tex_and_view(struct pipe_context
*pipe
, enum pipe_format format
,
260 VGint width
, VGint height
)
262 struct pipe_resource
*texture
;
263 struct pipe_sampler_view view_templ
;
264 struct pipe_sampler_view
*view
;
266 texture
= create_texture(pipe
, format
, width
, height
);
271 u_sampler_view_default_template(&view_templ
, texture
, texture
->format
);
272 view
= pipe
->create_sampler_view(pipe
, texture
, &view_templ
);
273 /* want the texture to go away if the view is freed */
274 pipe_resource_reference(&texture
, NULL
);
280 vg_context_update_alpha_mask_view(struct vg_context
*ctx
,
281 uint width
, uint height
)
283 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
284 struct pipe_sampler_view
*old_sampler_view
= stfb
->alpha_mask_view
;
285 struct pipe_context
*pipe
= ctx
->pipe
;
287 if (old_sampler_view
&&
288 old_sampler_view
->texture
->width0
== width
&&
289 old_sampler_view
->texture
->height0
== height
)
293 we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
294 this texture and use it as a sampler, so while this wastes some
295 space it makes both of those a lot simpler
297 stfb
->alpha_mask_view
= create_tex_and_view(pipe
,
298 PIPE_FORMAT_B8G8R8A8_UNORM
, width
, height
);
300 if (!stfb
->alpha_mask_view
) {
301 if (old_sampler_view
)
302 pipe_sampler_view_reference(&old_sampler_view
, NULL
);
306 /* XXX could this call be avoided? */
307 vg_validate_state(ctx
);
309 /* alpha mask starts with 1.f alpha */
310 mask_fill(0, 0, width
, height
, 1.f
);
312 /* if we had an old surface copy it over */
313 if (old_sampler_view
) {
314 struct pipe_subresource subsurf
, subold_surf
;
317 subold_surf
.face
= 0;
318 subold_surf
.level
= 0;
319 pipe
->resource_copy_region(pipe
,
320 stfb
->alpha_mask_view
->texture
,
323 old_sampler_view
->texture
,
326 MIN2(old_sampler_view
->texture
->width0
,
327 stfb
->alpha_mask_view
->texture
->width0
),
328 MIN2(old_sampler_view
->texture
->height0
,
329 stfb
->alpha_mask_view
->texture
->height0
));
332 /* Free the old texture
334 if (old_sampler_view
)
335 pipe_sampler_view_reference(&old_sampler_view
, NULL
);
339 vg_context_update_blend_texture_view(struct vg_context
*ctx
,
340 uint width
, uint height
)
342 struct pipe_context
*pipe
= ctx
->pipe
;
343 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
344 struct pipe_sampler_view
*old
= stfb
->blend_texture_view
;
347 old
->texture
->width0
== width
&&
348 old
->texture
->height0
== height
)
351 stfb
->blend_texture_view
= create_tex_and_view(pipe
,
352 PIPE_FORMAT_B8G8R8A8_UNORM
, width
, height
);
354 pipe_sampler_view_reference(&old
, NULL
);
358 vg_context_update_depth_stencil_rb(struct vg_context
* ctx
,
359 uint width
, uint height
)
361 struct st_renderbuffer
*dsrb
= ctx
->draw_buffer
->dsrb
;
362 struct pipe_context
*pipe
= ctx
->pipe
;
363 unsigned surface_usage
;
365 if ((dsrb
->width
== width
&& dsrb
->height
== height
) && dsrb
->texture
)
368 /* unreference existing ones */
369 pipe_surface_reference(&dsrb
->surface
, NULL
);
370 pipe_resource_reference(&dsrb
->texture
, NULL
);
371 dsrb
->width
= dsrb
->height
= 0;
373 /* Probably need dedicated flags for surface usage too:
375 surface_usage
= PIPE_BIND_DEPTH_STENCIL
; /* XXX: was: RENDER_TARGET */
377 dsrb
->texture
= create_texture(pipe
, dsrb
->format
, width
, height
);
381 dsrb
->surface
= pipe
->screen
->get_tex_surface(pipe
->screen
,
385 if (!dsrb
->surface
) {
386 pipe_resource_reference(&dsrb
->texture
, NULL
);
391 dsrb
->height
= height
;
393 assert(dsrb
->surface
->width
== width
);
394 assert(dsrb
->surface
->height
== height
);
399 void vg_validate_state(struct vg_context
*ctx
)
401 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
403 vg_manager_validate_framebuffer(ctx
);
405 if (vg_context_update_depth_stencil_rb(ctx
, stfb
->width
, stfb
->height
))
406 ctx
->state
.dirty
|= DEPTH_STENCIL_DIRTY
;
408 /* TODO create as needed */
409 vg_context_update_alpha_mask_view(ctx
, stfb
->width
, stfb
->height
);
410 vg_context_update_blend_texture_view(ctx
, stfb
->width
, stfb
->height
);
412 renderer_validate(ctx
->renderer
, ctx
->state
.dirty
,
413 ctx
->draw_buffer
, &ctx
->state
.vg
);
415 ctx
->state
.dirty
= NONE_DIRTY
;
417 shader_set_masking(ctx
->shader
, ctx
->state
.vg
.masking
);
418 shader_set_image_mode(ctx
->shader
, ctx
->state
.vg
.image_mode
);
419 shader_set_color_transform(ctx
->shader
, ctx
->state
.vg
.color_transform
);
422 VGboolean
vg_object_is_valid(void *ptr
, enum vg_object_type type
)
424 struct vg_object
*obj
= ptr
;
425 if (ptr
&& is_aligned(obj
) && obj
->type
== type
)
431 void vg_set_error(struct vg_context
*ctx
,
434 /*vgGetError returns the oldest error code provided by
435 * an API call on the current context since the previous
436 * call to vgGetError on that context (or since the creation
438 if (ctx
->_error
== VG_NO_ERROR
)
442 void vg_prepare_blend_surface(struct vg_context
*ctx
)
444 struct pipe_surface
*dest_surface
= NULL
;
445 struct pipe_context
*pipe
= ctx
->pipe
;
446 struct pipe_sampler_view
*view
;
447 struct pipe_sampler_view view_templ
;
448 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
449 struct st_renderbuffer
*strb
= stfb
->strb
;
451 /* first finish all pending rendering */
454 u_sampler_view_default_template(&view_templ
, strb
->texture
, strb
->texture
->format
);
455 view
= pipe
->create_sampler_view(pipe
, strb
->texture
, &view_templ
);
457 dest_surface
= pipe
->screen
->get_tex_surface(pipe
->screen
,
458 stfb
->blend_texture_view
->texture
,
460 PIPE_BIND_RENDER_TARGET
);
461 util_blit_pixels_tex(ctx
->blit
,
464 strb
->width
, strb
->height
,
467 strb
->width
, strb
->height
,
468 0.0, PIPE_TEX_MIPFILTER_NEAREST
);
471 pipe_surface_reference(&dest_surface
, NULL
);
473 /* make sure it's complete */
476 pipe_sampler_view_reference(&view
, NULL
);
480 void vg_prepare_blend_surface_from_mask(struct vg_context
*ctx
)
482 struct pipe_surface
*dest_surface
= NULL
;
483 struct pipe_context
*pipe
= ctx
->pipe
;
484 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
485 struct st_renderbuffer
*strb
= stfb
->strb
;
487 vg_validate_state(ctx
);
489 /* first finish all pending rendering */
492 dest_surface
= pipe
->screen
->get_tex_surface(pipe
->screen
,
493 stfb
->blend_texture_view
->texture
,
495 PIPE_BIND_RENDER_TARGET
);
497 util_blit_pixels_tex(ctx
->blit
,
498 stfb
->alpha_mask_view
,
500 strb
->width
, strb
->height
,
503 strb
->width
, strb
->height
,
504 0.0, PIPE_TEX_MIPFILTER_NEAREST
);
506 /* make sure it's complete */
510 pipe_surface_reference(&dest_surface
, NULL
);
514 * A transformation from window coordinates to paint coordinates.
516 VGboolean
vg_get_paint_matrix(struct vg_context
*ctx
,
517 const struct matrix
*paint_to_user
,
518 const struct matrix
*user_to_surface
,
523 /* get user-to-paint matrix */
524 memcpy(mat
, paint_to_user
, sizeof(*paint_to_user
));
525 if (!matrix_invert(mat
))
528 /* get surface-to-user matrix */
529 memcpy(&tmp
, user_to_surface
, sizeof(*user_to_surface
));
530 if (!matrix_invert(&tmp
))
533 matrix_mult(mat
, &tmp
);