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"
33 #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_memory.h"
44 #include "util/u_blit.h"
45 #include "util/u_sampler.h"
46 #include "util/u_surface.h"
47 #include "util/u_format.h"
49 struct vg_context
*_vg_context
= 0;
51 struct vg_context
* vg_current_context(void)
57 * A depth/stencil rb will be needed regardless of what the visual says.
60 choose_depth_stencil_format(struct vg_context
*ctx
)
62 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
63 enum pipe_format formats
[] = {
64 PIPE_FORMAT_Z24_UNORM_S8_UINT
,
65 PIPE_FORMAT_S8_UINT_Z24_UNORM
,
68 enum pipe_format
*fmt
;
70 for (fmt
= formats
; *fmt
!= PIPE_FORMAT_NONE
; fmt
++) {
71 if (screen
->is_format_supported(screen
, *fmt
,
72 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
))
76 ctx
->ds_format
= *fmt
;
78 return (ctx
->ds_format
!= PIPE_FORMAT_NONE
);
81 void vg_set_current_context(struct vg_context
*ctx
)
84 api_make_dispatch_current((ctx
) ? ctx
->dispatch
: NULL
);
87 struct vg_context
* vg_create_context(struct pipe_context
*pipe
,
89 struct vg_context
*share
)
91 struct vg_context
*ctx
;
93 ctx
= CALLOC_STRUCT(vg_context
);
96 if (!choose_depth_stencil_format(ctx
)) {
101 ctx
->dispatch
= api_create_dispatch();
103 vg_init_state(&ctx
->state
.vg
);
104 ctx
->state
.dirty
= ALL_DIRTY
;
106 ctx
->cso_context
= cso_create_context(pipe
);
108 ctx
->default_paint
= paint_create(ctx
);
109 ctx
->state
.vg
.stroke_paint
= ctx
->default_paint
;
110 ctx
->state
.vg
.fill_paint
= ctx
->default_paint
;
113 ctx
->mask
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
114 ctx
->mask
.sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
115 ctx
->mask
.sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
116 ctx
->mask
.sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
117 ctx
->mask
.sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
118 ctx
->mask
.sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
119 ctx
->mask
.sampler
.normalized_coords
= 0;
121 ctx
->blend_sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
122 ctx
->blend_sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
123 ctx
->blend_sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
124 ctx
->blend_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
125 ctx
->blend_sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
126 ctx
->blend_sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
127 ctx
->blend_sampler
.normalized_coords
= 0;
129 vg_set_error(ctx
, VG_NO_ERROR
);
131 ctx
->owned_objects
[VG_OBJECT_PAINT
] = cso_hash_create();
132 ctx
->owned_objects
[VG_OBJECT_IMAGE
] = cso_hash_create();
133 ctx
->owned_objects
[VG_OBJECT_MASK
] = cso_hash_create();
134 ctx
->owned_objects
[VG_OBJECT_FONT
] = cso_hash_create();
135 ctx
->owned_objects
[VG_OBJECT_PATH
] = cso_hash_create();
137 ctx
->renderer
= renderer_create(ctx
);
138 ctx
->sc
= shaders_cache_create(ctx
);
139 ctx
->shader
= shader_create(ctx
);
141 ctx
->blit
= util_create_blit(ctx
->pipe
, ctx
->cso_context
);
146 void vg_destroy_context(struct vg_context
*ctx
)
148 struct pipe_resource
**cbuf
= &ctx
->mask
.cbuf
;
150 util_destroy_blit(ctx
->blit
);
151 renderer_destroy(ctx
->renderer
);
152 shaders_cache_destroy(ctx
->sc
);
153 shader_destroy(ctx
->shader
);
154 paint_destroy(ctx
->default_paint
);
157 pipe_resource_reference(cbuf
, NULL
);
159 if (ctx
->mask
.union_fs
)
160 vg_shader_destroy(ctx
, ctx
->mask
.union_fs
);
161 if (ctx
->mask
.intersect_fs
)
162 vg_shader_destroy(ctx
, ctx
->mask
.intersect_fs
);
163 if (ctx
->mask
.subtract_fs
)
164 vg_shader_destroy(ctx
, ctx
->mask
.subtract_fs
);
165 if (ctx
->mask
.set_fs
)
166 vg_shader_destroy(ctx
, ctx
->mask
.set_fs
);
168 cso_release_all(ctx
->cso_context
);
169 cso_destroy_context(ctx
->cso_context
);
171 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PAINT
]);
172 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_IMAGE
]);
173 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_MASK
]);
174 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_FONT
]);
175 cso_hash_delete(ctx
->owned_objects
[VG_OBJECT_PATH
]);
177 api_destroy_dispatch(ctx
->dispatch
);
182 void vg_init_object(struct vg_object
*obj
, struct vg_context
*ctx
, enum vg_object_type type
)
186 obj
->handle
= create_handle(obj
);
189 /** free object resources, but not the object itself */
190 void vg_free_object(struct vg_object
*obj
)
194 destroy_handle(obj
->handle
);
197 VGboolean
vg_context_is_object_valid(struct vg_context
*ctx
,
198 enum vg_object_type type
,
202 struct cso_hash
*hash
= ctx
->owned_objects
[type
];
205 return cso_hash_contains(hash
, (unsigned) handle
);
210 void vg_context_add_object(struct vg_context
*ctx
,
211 struct vg_object
*obj
)
214 struct cso_hash
*hash
= ctx
->owned_objects
[obj
->type
];
217 cso_hash_insert(hash
, (unsigned) obj
->handle
, obj
);
221 void vg_context_remove_object(struct vg_context
*ctx
,
222 struct vg_object
*obj
)
225 struct cso_hash
*hash
= ctx
->owned_objects
[obj
->type
];
228 cso_hash_take(hash
, (unsigned) obj
->handle
);
232 static struct pipe_resource
*
233 create_texture(struct pipe_context
*pipe
, enum pipe_format format
,
234 VGint width
, VGint height
)
236 struct pipe_resource templ
;
238 memset(&templ
, 0, sizeof(templ
));
240 if (format
!= PIPE_FORMAT_NONE
) {
241 templ
.format
= format
;
244 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
247 templ
.target
= PIPE_TEXTURE_2D
;
248 templ
.width0
= width
;
249 templ
.height0
= height
;
251 templ
.array_size
= 1;
252 templ
.last_level
= 0;
254 if (util_format_get_component_bits(format
, UTIL_FORMAT_COLORSPACE_ZS
, 1)) {
255 templ
.bind
= PIPE_BIND_DEPTH_STENCIL
;
257 templ
.bind
= (PIPE_BIND_DISPLAY_TARGET
|
258 PIPE_BIND_RENDER_TARGET
|
259 PIPE_BIND_SAMPLER_VIEW
);
262 return pipe
->screen
->resource_create(pipe
->screen
, &templ
);
265 static struct pipe_sampler_view
*
266 create_tex_and_view(struct pipe_context
*pipe
, enum pipe_format format
,
267 VGint width
, VGint height
)
269 struct pipe_resource
*texture
;
270 struct pipe_sampler_view view_templ
;
271 struct pipe_sampler_view
*view
;
273 texture
= create_texture(pipe
, format
, width
, height
);
278 u_sampler_view_default_template(&view_templ
, texture
, texture
->format
);
279 view
= pipe
->create_sampler_view(pipe
, texture
, &view_templ
);
280 /* want the texture to go away if the view is freed */
281 pipe_resource_reference(&texture
, NULL
);
287 vg_context_update_surface_mask_view(struct vg_context
*ctx
,
288 uint width
, uint height
)
290 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
291 struct pipe_sampler_view
*old_sampler_view
= stfb
->surface_mask_view
;
292 struct pipe_context
*pipe
= ctx
->pipe
;
294 if (old_sampler_view
&&
295 old_sampler_view
->texture
->width0
== width
&&
296 old_sampler_view
->texture
->height0
== height
)
300 we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
301 this texture and use it as a sampler, so while this wastes some
302 space it makes both of those a lot simpler
304 stfb
->surface_mask_view
= create_tex_and_view(pipe
,
305 PIPE_FORMAT_B8G8R8A8_UNORM
, width
, height
);
307 if (!stfb
->surface_mask_view
) {
308 if (old_sampler_view
)
309 pipe_sampler_view_reference(&old_sampler_view
, NULL
);
313 /* XXX could this call be avoided? */
314 vg_validate_state(ctx
);
316 /* alpha mask starts with 1.f alpha */
317 mask_fill(0, 0, width
, height
, 1.f
);
319 /* if we had an old surface copy it over */
320 if (old_sampler_view
) {
321 struct pipe_box src_box
;
322 u_box_origin_2d(MIN2(old_sampler_view
->texture
->width0
,
323 stfb
->surface_mask_view
->texture
->width0
),
324 MIN2(old_sampler_view
->texture
->height0
,
325 stfb
->surface_mask_view
->texture
->height0
),
328 pipe
->resource_copy_region(pipe
,
329 stfb
->surface_mask_view
->texture
,
331 old_sampler_view
->texture
,
335 /* Free the old texture
337 if (old_sampler_view
)
338 pipe_sampler_view_reference(&old_sampler_view
, NULL
);
342 vg_context_update_blend_texture_view(struct vg_context
*ctx
,
343 uint width
, uint height
)
345 struct pipe_context
*pipe
= ctx
->pipe
;
346 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
347 struct pipe_sampler_view
*old
= stfb
->blend_texture_view
;
350 old
->texture
->width0
== width
&&
351 old
->texture
->height0
== height
)
354 stfb
->blend_texture_view
= create_tex_and_view(pipe
,
355 PIPE_FORMAT_B8G8R8A8_UNORM
, width
, height
);
357 pipe_sampler_view_reference(&old
, NULL
);
361 vg_context_update_depth_stencil_rb(struct vg_context
* ctx
,
362 uint width
, uint height
)
364 struct st_renderbuffer
*dsrb
= ctx
->draw_buffer
->dsrb
;
365 struct pipe_context
*pipe
= ctx
->pipe
;
366 struct pipe_surface surf_tmpl
;
368 if ((dsrb
->width
== width
&& dsrb
->height
== height
) && dsrb
->texture
)
371 /* unreference existing ones */
372 pipe_surface_reference(&dsrb
->surface
, NULL
);
373 pipe_resource_reference(&dsrb
->texture
, NULL
);
374 dsrb
->width
= dsrb
->height
= 0;
376 dsrb
->texture
= create_texture(pipe
, dsrb
->format
, width
, height
);
380 memset(&surf_tmpl
, 0, sizeof(surf_tmpl
));
381 u_surface_default_template(&surf_tmpl
, dsrb
->texture
,
382 PIPE_BIND_DEPTH_STENCIL
);
383 dsrb
->surface
= pipe
->create_surface(pipe
,
386 if (!dsrb
->surface
) {
387 pipe_resource_reference(&dsrb
->texture
, NULL
);
392 dsrb
->height
= height
;
394 assert(dsrb
->surface
->width
== width
);
395 assert(dsrb
->surface
->height
== height
);
400 void vg_validate_state(struct vg_context
*ctx
)
402 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
404 vg_manager_validate_framebuffer(ctx
);
406 if (vg_context_update_depth_stencil_rb(ctx
, stfb
->width
, stfb
->height
))
407 ctx
->state
.dirty
|= DEPTH_STENCIL_DIRTY
;
409 /* blend state depends on fb format and paint color */
410 if ((ctx
->state
.dirty
& FRAMEBUFFER_DIRTY
) ||
411 (ctx
->state
.dirty
& PAINT_DIRTY
))
412 ctx
->state
.dirty
|= BLEND_DIRTY
;
414 renderer_validate(ctx
->renderer
, ctx
->state
.dirty
,
415 ctx
->draw_buffer
, &ctx
->state
.vg
);
417 ctx
->state
.dirty
= 0;
419 shader_set_masking(ctx
->shader
, ctx
->state
.vg
.masking
);
420 shader_set_image_mode(ctx
->shader
, ctx
->state
.vg
.image_mode
);
421 shader_set_color_transform(ctx
->shader
, ctx
->state
.vg
.color_transform
);
424 VGboolean
vg_object_is_valid(VGHandle object
, enum vg_object_type type
)
426 struct vg_object
*obj
= handle_to_object(object
);
427 if (obj
&& is_aligned(obj
) && obj
->type
== type
)
433 void vg_set_error(struct vg_context
*ctx
,
436 /*vgGetError returns the oldest error code provided by
437 * an API call on the current context since the previous
438 * call to vgGetError on that context (or since the creation
440 if (ctx
->_error
== VG_NO_ERROR
)
444 static void vg_prepare_blend_texture(struct vg_context
*ctx
,
445 struct pipe_sampler_view
*src
)
447 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
448 struct pipe_surface
*surf
;
449 struct pipe_surface surf_tmpl
;
451 vg_context_update_blend_texture_view(ctx
, stfb
->width
, stfb
->height
);
453 memset(&surf_tmpl
, 0, sizeof(surf_tmpl
));
454 u_surface_default_template(&surf_tmpl
, stfb
->blend_texture_view
->texture
,
455 PIPE_BIND_RENDER_TARGET
);
456 surf
= ctx
->pipe
->create_surface(ctx
->pipe
,
457 stfb
->blend_texture_view
->texture
,
460 util_blit_pixels_tex(ctx
->blit
,
461 src
, 0, 0, stfb
->width
, stfb
->height
,
462 surf
, 0, 0, stfb
->width
, stfb
->height
,
463 0.0, PIPE_TEX_MIPFILTER_NEAREST
);
465 pipe_surface_reference(&surf
, NULL
);
469 struct pipe_sampler_view
*vg_prepare_blend_surface(struct vg_context
*ctx
)
471 struct pipe_context
*pipe
= ctx
->pipe
;
472 struct pipe_sampler_view
*view
;
473 struct pipe_sampler_view view_templ
;
474 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
475 struct st_renderbuffer
*strb
= stfb
->strb
;
477 vg_validate_state(ctx
);
479 u_sampler_view_default_template(&view_templ
, strb
->texture
, strb
->texture
->format
);
480 view
= pipe
->create_sampler_view(pipe
, strb
->texture
, &view_templ
);
482 vg_prepare_blend_texture(ctx
, view
);
484 pipe_sampler_view_reference(&view
, NULL
);
486 return stfb
->blend_texture_view
;
490 struct pipe_sampler_view
*vg_prepare_blend_surface_from_mask(struct vg_context
*ctx
)
492 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
494 vg_validate_state(ctx
);
496 vg_context_update_surface_mask_view(ctx
, stfb
->width
, stfb
->height
);
497 vg_prepare_blend_texture(ctx
, stfb
->surface_mask_view
);
499 return stfb
->blend_texture_view
;
502 struct pipe_sampler_view
*vg_get_surface_mask(struct vg_context
*ctx
)
504 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
506 vg_context_update_surface_mask_view(ctx
, stfb
->width
, stfb
->height
);
508 return stfb
->surface_mask_view
;
512 * A transformation from window coordinates to paint coordinates.
514 VGboolean
vg_get_paint_matrix(struct vg_context
*ctx
,
515 const struct matrix
*paint_to_user
,
516 const struct matrix
*user_to_surface
,
521 /* get user-to-paint matrix */
522 memcpy(mat
, paint_to_user
, sizeof(*paint_to_user
));
523 if (!matrix_invert(mat
))
526 /* get surface-to-user matrix */
527 memcpy(&tmp
, user_to_surface
, sizeof(*user_to_surface
));
528 if (!matrix_invert(&tmp
))
531 matrix_mult(mat
, &tmp
);