revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / state_trackers / vega / vg_context.c
blobc2ab56455b1c412828056af1593265ded0c1f01b
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
15 * of the Software.
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"
29 #include "paint.h"
30 #include "renderer.h"
31 #include "shaders_cache.h"
32 #include "shader.h"
33 #include "vg_manager.h"
34 #include "api.h"
35 #include "mask.h"
36 #include "handle.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)
53 return _vg_context;
56 /**
57 * A depth/stencil rb will be needed regardless of what the visual says.
59 static boolean
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_USCALED,
65 PIPE_FORMAT_S8_USCALED_Z24_UNORM,
66 PIPE_FORMAT_NONE
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))
73 break;
76 ctx->ds_format = *fmt;
78 return (ctx->ds_format != PIPE_FORMAT_NONE);
81 void vg_set_current_context(struct vg_context *ctx)
83 _vg_context = ctx;
84 api_make_dispatch_current((ctx) ? ctx->dispatch : NULL);
87 struct vg_context * vg_create_context(struct pipe_context *pipe,
88 const void *visual,
89 struct vg_context *share)
91 struct vg_context *ctx;
93 ctx = CALLOC_STRUCT(vg_context);
95 ctx->pipe = pipe;
96 if (!choose_depth_stencil_format(ctx)) {
97 FREE(ctx);
98 return NULL;
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);
143 return ctx;
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);
156 if (*cbuf)
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);
179 FREE(ctx);
182 void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
184 obj->type = type;
185 obj->ctx = ctx;
186 obj->handle = create_handle(obj);
189 /** free object resources, but not the object itself */
190 void vg_free_object(struct vg_object *obj)
192 obj->type = 0;
193 obj->ctx = NULL;
194 destroy_handle(obj->handle);
197 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
198 enum vg_object_type type,
199 VGHandle object)
201 if (ctx) {
202 struct cso_hash *hash = ctx->owned_objects[type];
203 if (!hash)
204 return VG_FALSE;
205 return cso_hash_contains(hash, (unsigned)(long)object);
207 return VG_FALSE;
210 void vg_context_add_object(struct vg_context *ctx,
211 enum vg_object_type type,
212 void *ptr)
214 if (ctx) {
215 struct cso_hash *hash = ctx->owned_objects[type];
216 if (!hash)
217 return;
218 cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
222 void vg_context_remove_object(struct vg_context *ctx,
223 enum vg_object_type type,
224 void *ptr)
226 if (ctx) {
227 struct cso_hash *hash = ctx->owned_objects[type];
228 if (!hash)
229 return;
230 cso_hash_take(hash, (unsigned)(long)ptr);
234 static struct pipe_resource *
235 create_texture(struct pipe_context *pipe, enum pipe_format format,
236 VGint width, VGint height)
238 struct pipe_resource templ;
240 memset(&templ, 0, sizeof(templ));
242 if (format != PIPE_FORMAT_NONE) {
243 templ.format = format;
245 else {
246 templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
249 templ.target = PIPE_TEXTURE_2D;
250 templ.width0 = width;
251 templ.height0 = height;
252 templ.depth0 = 1;
253 templ.array_size = 1;
254 templ.last_level = 0;
256 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
257 templ.bind = PIPE_BIND_DEPTH_STENCIL;
258 } else {
259 templ.bind = (PIPE_BIND_DISPLAY_TARGET |
260 PIPE_BIND_RENDER_TARGET |
261 PIPE_BIND_SAMPLER_VIEW);
264 return pipe->screen->resource_create(pipe->screen, &templ);
267 static struct pipe_sampler_view *
268 create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
269 VGint width, VGint height)
271 struct pipe_resource *texture;
272 struct pipe_sampler_view view_templ;
273 struct pipe_sampler_view *view;
275 texture = create_texture(pipe, format, width, height);
277 if (!texture)
278 return NULL;
280 u_sampler_view_default_template(&view_templ, texture, texture->format);
281 view = pipe->create_sampler_view(pipe, texture, &view_templ);
282 /* want the texture to go away if the view is freed */
283 pipe_resource_reference(&texture, NULL);
285 return view;
288 static void
289 vg_context_update_surface_mask_view(struct vg_context *ctx,
290 uint width, uint height)
292 struct st_framebuffer *stfb = ctx->draw_buffer;
293 struct pipe_sampler_view *old_sampler_view = stfb->surface_mask_view;
294 struct pipe_context *pipe = ctx->pipe;
296 if (old_sampler_view &&
297 old_sampler_view->texture->width0 == width &&
298 old_sampler_view->texture->height0 == height)
299 return;
302 we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
303 this texture and use it as a sampler, so while this wastes some
304 space it makes both of those a lot simpler
306 stfb->surface_mask_view = create_tex_and_view(pipe,
307 PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
309 if (!stfb->surface_mask_view) {
310 if (old_sampler_view)
311 pipe_sampler_view_reference(&old_sampler_view, NULL);
312 return;
315 /* XXX could this call be avoided? */
316 vg_validate_state(ctx);
318 /* alpha mask starts with 1.f alpha */
319 mask_fill(0, 0, width, height, 1.f);
321 /* if we had an old surface copy it over */
322 if (old_sampler_view) {
323 struct pipe_box src_box;
324 u_box_origin_2d(MIN2(old_sampler_view->texture->width0,
325 stfb->surface_mask_view->texture->width0),
326 MIN2(old_sampler_view->texture->height0,
327 stfb->surface_mask_view->texture->height0),
328 &src_box);
330 pipe->resource_copy_region(pipe,
331 stfb->surface_mask_view->texture,
332 0, 0, 0, 0,
333 old_sampler_view->texture,
334 0, &src_box);
337 /* Free the old texture
339 if (old_sampler_view)
340 pipe_sampler_view_reference(&old_sampler_view, NULL);
343 static void
344 vg_context_update_blend_texture_view(struct vg_context *ctx,
345 uint width, uint height)
347 struct pipe_context *pipe = ctx->pipe;
348 struct st_framebuffer *stfb = ctx->draw_buffer;
349 struct pipe_sampler_view *old = stfb->blend_texture_view;
351 if (old &&
352 old->texture->width0 == width &&
353 old->texture->height0 == height)
354 return;
356 stfb->blend_texture_view = create_tex_and_view(pipe,
357 PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
359 pipe_sampler_view_reference(&old, NULL);
362 static boolean
363 vg_context_update_depth_stencil_rb(struct vg_context * ctx,
364 uint width, uint height)
366 struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
367 struct pipe_context *pipe = ctx->pipe;
368 struct pipe_surface surf_tmpl;
370 if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
371 return FALSE;
373 /* unreference existing ones */
374 pipe_surface_reference(&dsrb->surface, NULL);
375 pipe_resource_reference(&dsrb->texture, NULL);
376 dsrb->width = dsrb->height = 0;
378 dsrb->texture = create_texture(pipe, dsrb->format, width, height);
379 if (!dsrb->texture)
380 return TRUE;
382 memset(&surf_tmpl, 0, sizeof(surf_tmpl));
383 u_surface_default_template(&surf_tmpl, dsrb->texture,
384 PIPE_BIND_DEPTH_STENCIL);
385 dsrb->surface = pipe->create_surface(pipe,
386 dsrb->texture,
387 &surf_tmpl);
388 if (!dsrb->surface) {
389 pipe_resource_reference(&dsrb->texture, NULL);
390 return TRUE;
393 dsrb->width = width;
394 dsrb->height = height;
396 assert(dsrb->surface->width == width);
397 assert(dsrb->surface->height == height);
399 return TRUE;
402 void vg_validate_state(struct vg_context *ctx)
404 struct st_framebuffer *stfb = ctx->draw_buffer;
406 vg_manager_validate_framebuffer(ctx);
408 if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height))
409 ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
411 /* blend state depends on fb format and paint color */
412 if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) ||
413 (ctx->state.dirty & PAINT_DIRTY))
414 ctx->state.dirty |= BLEND_DIRTY;
416 renderer_validate(ctx->renderer, ctx->state.dirty,
417 ctx->draw_buffer, &ctx->state.vg);
419 ctx->state.dirty = 0;
421 shader_set_masking(ctx->shader, ctx->state.vg.masking);
422 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
423 shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform);
426 VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type)
428 struct vg_object *obj = handle_to_object(object);
429 if (obj && is_aligned(obj) && obj->type == type)
430 return VG_TRUE;
431 else
432 return VG_FALSE;
435 void vg_set_error(struct vg_context *ctx,
436 VGErrorCode code)
438 /*vgGetError returns the oldest error code provided by
439 * an API call on the current context since the previous
440 * call to vgGetError on that context (or since the creation
441 of the context).*/
442 if (ctx->_error == VG_NO_ERROR)
443 ctx->_error = code;
446 static void vg_prepare_blend_texture(struct vg_context *ctx,
447 struct pipe_sampler_view *src)
449 struct st_framebuffer *stfb = ctx->draw_buffer;
450 struct pipe_surface *surf;
451 struct pipe_surface surf_tmpl;
453 vg_context_update_blend_texture_view(ctx, stfb->width, stfb->height);
455 memset(&surf_tmpl, 0, sizeof(surf_tmpl));
456 u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture,
457 PIPE_BIND_RENDER_TARGET);
458 surf = ctx->pipe->create_surface(ctx->pipe,
459 stfb->blend_texture_view->texture,
460 &surf_tmpl);
461 if (surf) {
462 util_blit_pixels_tex(ctx->blit,
463 src, 0, 0, stfb->width, stfb->height,
464 surf, 0, 0, stfb->width, stfb->height,
465 0.0, PIPE_TEX_MIPFILTER_NEAREST);
467 pipe_surface_reference(&surf, NULL);
471 struct pipe_sampler_view *vg_prepare_blend_surface(struct vg_context *ctx)
473 struct pipe_context *pipe = ctx->pipe;
474 struct pipe_sampler_view *view;
475 struct pipe_sampler_view view_templ;
476 struct st_framebuffer *stfb = ctx->draw_buffer;
477 struct st_renderbuffer *strb = stfb->strb;
479 vg_validate_state(ctx);
481 u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
482 view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
484 vg_prepare_blend_texture(ctx, view);
486 pipe_sampler_view_reference(&view, NULL);
488 return stfb->blend_texture_view;
492 struct pipe_sampler_view *vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
494 struct st_framebuffer *stfb = ctx->draw_buffer;
496 vg_validate_state(ctx);
498 vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
499 vg_prepare_blend_texture(ctx, stfb->surface_mask_view);
501 return stfb->blend_texture_view;
504 struct pipe_sampler_view *vg_get_surface_mask(struct vg_context *ctx)
506 struct st_framebuffer *stfb = ctx->draw_buffer;
508 vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
510 return stfb->surface_mask_view;
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,
519 struct matrix *mat)
521 struct matrix tmp;
523 /* get user-to-paint matrix */
524 memcpy(mat, paint_to_user, sizeof(*paint_to_user));
525 if (!matrix_invert(mat))
526 return VG_FALSE;
528 /* get surface-to-user matrix */
529 memcpy(&tmp, user_to_surface, sizeof(*user_to_surface));
530 if (!matrix_invert(&tmp))
531 return VG_FALSE;
533 matrix_mult(mat, &tmp);
535 return VG_TRUE;