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"
37 #include "pipe/p_context.h"
38 #include "util/u_inlines.h"
39 #include "pipe/p_shader_tokens.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);
67 void vg_set_current_context(struct vg_context *ctx)
72 struct vg_context * vg_create_context(struct pipe_context *pipe,
74 struct vg_context *share)
76 struct vg_context *ctx;
79 ctx = CALLOC_STRUCT(vg_context);
83 vg_init_state(&ctx->state.vg);
84 ctx->state.dirty = ALL_DIRTY;
86 ctx->cso_context = cso_create_context(pipe);
90 ctx->default_paint = paint_create(ctx);
91 ctx->state.vg.stroke_paint = ctx->default_paint;
92 ctx->state.vg.fill_paint = ctx->default_paint;
95 ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
96 ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
97 ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
98 ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
99 ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
100 ctx->mask.sampler.normalized_coords = 0;
102 ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
103 ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
104 ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
105 ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
106 ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
107 ctx->blend_sampler.normalized_coords = 0;
109 for (i = 0; i < 2; i++) {
110 ctx->velems[i].src_offset = i * 4 * sizeof(float);
111 ctx->velems[i].instance_divisor = 0;
112 ctx->velems[i].vertex_buffer_index = 0;
113 ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
116 vg_set_error(ctx, VG_NO_ERROR);
118 ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
119 ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
120 ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
121 ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
122 ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
124 ctx->renderer = renderer_create(ctx);
125 ctx->sc = shaders_cache_create(ctx);
126 ctx->shader = shader_create(ctx);
128 ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
133 void vg_destroy_context(struct vg_context *ctx)
135 struct pipe_buffer **cbuf = &ctx->mask.cbuf;
136 struct pipe_buffer **vsbuf = &ctx->vs_const_buffer;
138 util_destroy_blit(ctx->blit);
139 renderer_destroy(ctx->renderer);
140 shaders_cache_destroy(ctx->sc);
141 shader_destroy(ctx->shader);
142 paint_destroy(ctx->default_paint);
145 pipe_buffer_reference(cbuf, NULL);
148 pipe_buffer_reference(vsbuf, NULL);
151 cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
152 ctx->clear.fs = NULL;
156 vg_shader_destroy(ctx, ctx->plain_vs);
157 ctx->plain_vs = NULL;
160 vg_shader_destroy(ctx, ctx->clear_vs);
161 ctx->clear_vs = NULL;
163 if (ctx->texture_vs) {
164 vg_shader_destroy(ctx, ctx->texture_vs);
165 ctx->texture_vs = NULL;
168 if (ctx->pass_through_depth_fs)
169 vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
170 if (ctx->mask.union_fs)
171 vg_shader_destroy(ctx, ctx->mask.union_fs);
172 if (ctx->mask.intersect_fs)
173 vg_shader_destroy(ctx, ctx->mask.intersect_fs);
174 if (ctx->mask.subtract_fs)
175 vg_shader_destroy(ctx, ctx->mask.subtract_fs);
176 if (ctx->mask.set_fs)
177 vg_shader_destroy(ctx, ctx->mask.set_fs);
179 cso_release_all(ctx->cso_context);
180 cso_destroy_context(ctx->cso_context);
182 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
183 cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
184 cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
185 cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
186 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
191 void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
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)(long)ptr);
210 void vg_context_add_object(struct vg_context *ctx,
211 enum vg_object_type type,
215 struct cso_hash *hash = ctx->owned_objects[type];
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,
227 struct cso_hash *hash = ctx->owned_objects[type];
230 cso_hash_take(hash, (unsigned)(long)ptr);
234 static void update_clip_state(struct vg_context *ctx)
236 struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
237 struct vg_state *state = &ctx->state.vg;
239 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
241 if (state->scissoring) {
242 struct pipe_blend_state *blend = &ctx->state.g3d.blend;
243 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
246 dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
247 dsa->depth.func = PIPE_FUNC_ALWAYS;
248 dsa->depth.enabled = 1;
250 cso_save_blend(ctx->cso_context);
251 cso_save_fragment_shader(ctx->cso_context);
252 /* set a passthrough shader */
253 if (!ctx->pass_through_depth_fs)
254 ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
255 pass_through_depth_asm,
257 PIPE_SHADER_FRAGMENT);
258 cso_set_fragment_shader_handle(ctx->cso_context,
259 ctx->pass_through_depth_fs->driver);
260 cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
262 ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
264 /* disable color writes */
265 blend->rt[0].colormask = 0; /*disable colorwrites*/
266 cso_set_blend(ctx->cso_context, blend);
268 /* enable scissoring */
269 for (i = 0; i < state->scissor_rects_num; ++i) {
270 const float x = state->scissor_rects[i * 4 + 0].f;
271 const float y = state->scissor_rects[i * 4 + 1].f;
272 const float width = state->scissor_rects[i * 4 + 2].f;
273 const float height = state->scissor_rects[i * 4 + 3].f;
274 VGfloat minx, miny, maxx, maxy;
286 if (x + width < maxx)
288 if (y + height < maxy)
291 /* check for null space */
292 if (minx >= maxx || miny >= maxy)
293 minx = miny = maxx = maxy = 0;
295 /*glClear(GL_DEPTH_BUFFER_BIT);*/
296 renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
299 cso_restore_blend(ctx->cso_context);
300 cso_restore_fragment_shader(ctx->cso_context);
302 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
303 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
304 dsa->depth.func = PIPE_FUNC_GEQUAL;
308 void vg_validate_state(struct vg_context *ctx)
310 vg_manager_validate_framebuffer(ctx);
312 if ((ctx->state.dirty & BLEND_DIRTY)) {
313 struct pipe_blend_state *blend = &ctx->state.g3d.blend;
314 memset(blend, 0, sizeof(struct pipe_blend_state));
315 blend->rt[0].blend_enable = 1;
316 blend->rt[0].colormask = PIPE_MASK_RGBA;
318 switch (ctx->state.vg.blend_mode) {
320 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
321 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
322 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
323 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
324 blend->rt[0].blend_enable = 0;
326 case VG_BLEND_SRC_OVER:
327 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
328 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
329 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
330 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
332 case VG_BLEND_DST_OVER:
333 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
334 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
335 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
336 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
338 case VG_BLEND_SRC_IN:
339 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
340 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
341 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
342 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
344 case VG_BLEND_DST_IN:
345 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
346 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
347 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
348 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
350 case VG_BLEND_MULTIPLY:
351 case VG_BLEND_SCREEN:
352 case VG_BLEND_DARKEN:
353 case VG_BLEND_LIGHTEN:
354 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
355 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
356 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
357 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
358 blend->rt[0].blend_enable = 0;
360 case VG_BLEND_ADDITIVE:
361 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
362 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
363 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
364 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
367 assert(!"not implemented blend mode");
369 cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
371 if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
372 struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
373 memset(raster, 0, sizeof(struct pipe_rasterizer_state));
374 raster->gl_rasterization_rules = 1;
375 cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
377 if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
378 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
379 const VGint param_bytes = 8 * sizeof(VGfloat);
380 VGfloat vs_consts[8] = {
381 2.f/fb->width, 2.f/fb->height, 1, 1,
384 struct pipe_buffer **cbuf = &ctx->vs_const_buffer;
386 vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
388 pipe_buffer_reference(cbuf, NULL);
389 *cbuf = pipe_buffer_create(ctx->pipe->screen, 16,
390 PIPE_BUFFER_USAGE_CONSTANT,
394 st_no_flush_pipe_buffer_write(ctx, *cbuf,
395 0, param_bytes, vs_consts);
397 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
399 if ((ctx->state.dirty & VS_DIRTY)) {
400 cso_set_vertex_shader_handle(ctx->cso_context,
404 /* must be last because it renders to the depth buffer*/
405 if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
406 update_clip_state(ctx);
407 cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
410 shader_set_masking(ctx->shader, ctx->state.vg.masking);
411 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
413 ctx->state.dirty = NONE_DIRTY;
416 VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
418 struct vg_object *obj = ptr;
419 if (ptr && is_aligned(obj) && obj->type == type)
425 void vg_set_error(struct vg_context *ctx,
428 /*vgGetError returns the oldest error code provided by
429 * an API call on the current context since the previous
430 * call to vgGetError on that context (or since the creation
432 if (ctx->_error == VG_NO_ERROR)
436 void vg_prepare_blend_surface(struct vg_context *ctx)
438 struct pipe_surface *dest_surface = NULL;
439 struct pipe_context *pipe = ctx->pipe;
440 struct pipe_sampler_view *view;
441 struct pipe_sampler_view view_templ;
442 struct st_framebuffer *stfb = ctx->draw_buffer;
443 struct st_renderbuffer *strb = stfb->strb;
445 /* first finish all pending rendering */
448 u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
449 view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
451 dest_surface = pipe->screen->get_tex_surface(pipe->screen,
452 stfb->blend_texture_view->texture,
454 PIPE_BUFFER_USAGE_GPU_WRITE);
455 /* flip it, because we want to use it as a sampler */
456 util_blit_pixels_tex(ctx->blit,
462 strb->width, strb->height,
463 0.0, PIPE_TEX_MIPFILTER_NEAREST);
466 pipe_surface_reference(&dest_surface, NULL);
468 /* make sure it's complete */
471 pipe_sampler_view_reference(&view, NULL);
475 void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
477 struct pipe_surface *dest_surface = NULL;
478 struct pipe_context *pipe = ctx->pipe;
479 struct st_framebuffer *stfb = ctx->draw_buffer;
480 struct st_renderbuffer *strb = stfb->strb;
482 vg_validate_state(ctx);
484 /* first finish all pending rendering */
487 dest_surface = pipe->screen->get_tex_surface(pipe->screen,
488 stfb->blend_texture_view->texture,
490 PIPE_BUFFER_USAGE_GPU_WRITE);
492 /* flip it, because we want to use it as a sampler */
493 util_blit_pixels_tex(ctx->blit,
494 stfb->alpha_mask_view,
499 strb->width, strb->height,
500 0.0, PIPE_TEX_MIPFILTER_NEAREST);
502 /* make sure it's complete */
506 pipe_surface_reference(&dest_surface, NULL);
509 void * vg_plain_vs(struct vg_context *ctx)
511 if (!ctx->plain_vs) {
512 ctx->plain_vs = shader_create_from_text(ctx->pipe,
518 return ctx->plain_vs->driver;
522 void * vg_clear_vs(struct vg_context *ctx)
524 if (!ctx->clear_vs) {
525 ctx->clear_vs = shader_create_from_text(ctx->pipe,
531 return ctx->clear_vs->driver;
534 void * vg_texture_vs(struct vg_context *ctx)
536 if (!ctx->texture_vs) {
537 ctx->texture_vs = shader_create_from_text(ctx->pipe,
543 return ctx->texture_vs->driver;
546 void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
548 struct pipe_viewport_state viewport;
549 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
550 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
552 viewport.scale[0] = fb->width / 2.f;
553 viewport.scale[1] = fb->height / y_scale;
554 viewport.scale[2] = 1.0;
555 viewport.scale[3] = 1.0;
556 viewport.translate[0] = fb->width / 2.f;
557 viewport.translate[1] = fb->height / 2.f;
558 viewport.translate[2] = 0.0;
559 viewport.translate[3] = 0.0;
561 cso_set_viewport(ctx->cso_context, &viewport);