Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / vega / vg_context.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 *
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:
12 *
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.
16 *
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.
24 *
25 **************************************************************************/
26
27 #include "vg_context.h"
28
29 #include "paint.h"
30 #include "renderer.h"
31 #include "shaders_cache.h"
32 #include "shader.h"
33 #include "asm_util.h"
34 #include "st_inlines.h"
35 #include "vg_manager.h"
36
37 #include "pipe/p_context.h"
38 #include "util/u_inlines.h"
39 #include "pipe/p_shader_tokens.h"
40
41 #include "cso_cache/cso_context.h"
42
43 #include "util/u_simple_shaders.h"
44 #include "util/u_memory.h"
45 #include "util/u_blit.h"
46
47 struct vg_context *_vg_context = 0;
48
49 struct vg_context * vg_current_context(void)
50 {
51 return _vg_context;
52 }
53
54 static void init_clear(struct vg_context *st)
55 {
56 struct pipe_context *pipe = st->pipe;
57
58 /* rasterizer state: bypass clipping */
59 memset(&st->clear.raster, 0, sizeof(st->clear.raster));
60 st->clear.raster.gl_rasterization_rules = 1;
61
62 /* fragment shader state: color pass-through program */
63 st->clear.fs =
64 util_make_fragment_passthrough_shader(pipe);
65 }
66 void vg_set_current_context(struct vg_context *ctx)
67 {
68 _vg_context = ctx;
69 }
70
71 struct vg_context * vg_create_context(struct pipe_context *pipe,
72 const void *visual,
73 struct vg_context *share)
74 {
75 struct vg_context *ctx;
76 unsigned i;
77
78 ctx = CALLOC_STRUCT(vg_context);
79
80 ctx->pipe = pipe;
81
82 vg_init_state(&ctx->state.vg);
83 ctx->state.dirty = ALL_DIRTY;
84
85 ctx->cso_context = cso_create_context(pipe);
86
87 init_clear(ctx);
88
89 ctx->default_paint = paint_create(ctx);
90 ctx->state.vg.stroke_paint = ctx->default_paint;
91 ctx->state.vg.fill_paint = ctx->default_paint;
92
93
94 ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
95 ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
96 ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
97 ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
98 ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
99 ctx->mask.sampler.normalized_coords = 0;
100
101 ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
102 ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
103 ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
104 ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
105 ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
106 ctx->blend_sampler.normalized_coords = 0;
107
108 for (i = 0; i < 2; i++) {
109 ctx->velems[i].src_offset = i * 4 * sizeof(float);
110 ctx->velems[i].instance_divisor = 0;
111 ctx->velems[i].vertex_buffer_index = 0;
112 ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
113 }
114
115 vg_set_error(ctx, VG_NO_ERROR);
116
117 ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
118 ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
119 ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
120 ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
121 ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
122
123 ctx->renderer = renderer_create(ctx);
124 ctx->sc = shaders_cache_create(ctx);
125 ctx->shader = shader_create(ctx);
126
127 ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
128
129 return ctx;
130 }
131
132 void vg_destroy_context(struct vg_context *ctx)
133 {
134 struct pipe_buffer **cbuf = &ctx->mask.cbuf;
135 struct pipe_buffer **vsbuf = &ctx->vs_const_buffer;
136
137 util_destroy_blit(ctx->blit);
138 renderer_destroy(ctx->renderer);
139 shaders_cache_destroy(ctx->sc);
140 shader_destroy(ctx->shader);
141 paint_destroy(ctx->default_paint);
142
143 if (*cbuf)
144 pipe_buffer_reference(cbuf, NULL);
145
146 if (*vsbuf)
147 pipe_buffer_reference(vsbuf, NULL);
148
149 if (ctx->clear.fs) {
150 cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
151 ctx->clear.fs = NULL;
152 }
153
154 if (ctx->plain_vs) {
155 vg_shader_destroy(ctx, ctx->plain_vs);
156 ctx->plain_vs = NULL;
157 }
158 if (ctx->clear_vs) {
159 vg_shader_destroy(ctx, ctx->clear_vs);
160 ctx->clear_vs = NULL;
161 }
162 if (ctx->texture_vs) {
163 vg_shader_destroy(ctx, ctx->texture_vs);
164 ctx->texture_vs = NULL;
165 }
166
167 if (ctx->pass_through_depth_fs)
168 vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
169 if (ctx->mask.union_fs)
170 vg_shader_destroy(ctx, ctx->mask.union_fs);
171 if (ctx->mask.intersect_fs)
172 vg_shader_destroy(ctx, ctx->mask.intersect_fs);
173 if (ctx->mask.subtract_fs)
174 vg_shader_destroy(ctx, ctx->mask.subtract_fs);
175 if (ctx->mask.set_fs)
176 vg_shader_destroy(ctx, ctx->mask.set_fs);
177
178 cso_release_all(ctx->cso_context);
179 cso_destroy_context(ctx->cso_context);
180
181 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
182 cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
183 cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
184 cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
185 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
186
187 free(ctx);
188 }
189
190 void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
191 {
192 obj->type = type;
193 obj->ctx = ctx;
194 }
195
196 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
197 enum vg_object_type type,
198 void *ptr)
199 {
200 if (ctx) {
201 struct cso_hash *hash = ctx->owned_objects[type];
202 if (!hash)
203 return VG_FALSE;
204 return cso_hash_contains(hash, (unsigned)(long)ptr);
205 }
206 return VG_FALSE;
207 }
208
209 void vg_context_add_object(struct vg_context *ctx,
210 enum vg_object_type type,
211 void *ptr)
212 {
213 if (ctx) {
214 struct cso_hash *hash = ctx->owned_objects[type];
215 if (!hash)
216 return;
217 cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
218 }
219 }
220
221 void vg_context_remove_object(struct vg_context *ctx,
222 enum vg_object_type type,
223 void *ptr)
224 {
225 if (ctx) {
226 struct cso_hash *hash = ctx->owned_objects[type];
227 if (!hash)
228 return;
229 cso_hash_take(hash, (unsigned)(long)ptr);
230 }
231 }
232
233 static void update_clip_state(struct vg_context *ctx)
234 {
235 struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
236 struct vg_state *state = &ctx->state.vg;
237
238 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
239
240 if (state->scissoring) {
241 struct pipe_blend_state *blend = &ctx->state.g3d.blend;
242 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
243 int i;
244
245 dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
246 dsa->depth.func = PIPE_FUNC_ALWAYS;
247 dsa->depth.enabled = 1;
248
249 cso_save_blend(ctx->cso_context);
250 cso_save_fragment_shader(ctx->cso_context);
251 /* set a passthrough shader */
252 if (!ctx->pass_through_depth_fs)
253 ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
254 pass_through_depth_asm,
255 40,
256 PIPE_SHADER_FRAGMENT);
257 cso_set_fragment_shader_handle(ctx->cso_context,
258 ctx->pass_through_depth_fs->driver);
259 cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
260
261 ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
262
263 /* disable color writes */
264 blend->rt[0].colormask = 0; /*disable colorwrites*/
265 cso_set_blend(ctx->cso_context, blend);
266
267 /* enable scissoring */
268 for (i = 0; i < state->scissor_rects_num; ++i) {
269 const float x = state->scissor_rects[i * 4 + 0].f;
270 const float y = state->scissor_rects[i * 4 + 1].f;
271 const float width = state->scissor_rects[i * 4 + 2].f;
272 const float height = state->scissor_rects[i * 4 + 3].f;
273 VGfloat minx, miny, maxx, maxy;
274
275 minx = 0;
276 miny = 0;
277 maxx = fb->width;
278 maxy = fb->height;
279
280 if (x > minx)
281 minx = x;
282 if (y > miny)
283 miny = y;
284
285 if (x + width < maxx)
286 maxx = x + width;
287 if (y + height < maxy)
288 maxy = y + height;
289
290 /* check for null space */
291 if (minx >= maxx || miny >= maxy)
292 minx = miny = maxx = maxy = 0;
293
294 /*glClear(GL_DEPTH_BUFFER_BIT);*/
295 renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
296 }
297
298 cso_restore_blend(ctx->cso_context);
299 cso_restore_fragment_shader(ctx->cso_context);
300
301 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
302 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
303 dsa->depth.func = PIPE_FUNC_GEQUAL;
304 }
305 }
306
307 void vg_validate_state(struct vg_context *ctx)
308 {
309 vg_manager_validate_framebuffer(ctx);
310
311 if ((ctx->state.dirty & BLEND_DIRTY)) {
312 struct pipe_blend_state *blend = &ctx->state.g3d.blend;
313 memset(blend, 0, sizeof(struct pipe_blend_state));
314 blend->rt[0].blend_enable = 1;
315 blend->rt[0].colormask = PIPE_MASK_RGBA;
316
317 switch (ctx->state.vg.blend_mode) {
318 case VG_BLEND_SRC:
319 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
320 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
321 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
322 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
323 blend->rt[0].blend_enable = 0;
324 break;
325 case VG_BLEND_SRC_OVER:
326 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
327 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
328 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
329 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
330 break;
331 case VG_BLEND_DST_OVER:
332 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
333 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
334 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
335 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
336 break;
337 case VG_BLEND_SRC_IN:
338 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
339 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
340 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
341 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
342 break;
343 case VG_BLEND_DST_IN:
344 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
345 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
346 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
347 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
348 break;
349 case VG_BLEND_MULTIPLY:
350 case VG_BLEND_SCREEN:
351 case VG_BLEND_DARKEN:
352 case VG_BLEND_LIGHTEN:
353 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
354 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
355 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
356 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
357 blend->rt[0].blend_enable = 0;
358 break;
359 case VG_BLEND_ADDITIVE:
360 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
361 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
362 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
363 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
364 break;
365 default:
366 assert(!"not implemented blend mode");
367 }
368 cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
369 }
370 if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
371 struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
372 memset(raster, 0, sizeof(struct pipe_rasterizer_state));
373 raster->gl_rasterization_rules = 1;
374 cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
375 }
376 if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
377 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
378 const VGint param_bytes = 8 * sizeof(VGfloat);
379 VGfloat vs_consts[8] = {
380 2.f/fb->width, 2.f/fb->height, 1, 1,
381 -1, -1, 0, 0
382 };
383 struct pipe_buffer **cbuf = &ctx->vs_const_buffer;
384
385 vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
386
387 pipe_buffer_reference(cbuf, NULL);
388 *cbuf = pipe_buffer_create(ctx->pipe->screen, 16,
389 PIPE_BUFFER_USAGE_CONSTANT,
390 param_bytes);
391
392 if (*cbuf) {
393 st_no_flush_pipe_buffer_write(ctx, *cbuf,
394 0, param_bytes, vs_consts);
395 }
396 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
397 }
398 if ((ctx->state.dirty & VS_DIRTY)) {
399 cso_set_vertex_shader_handle(ctx->cso_context,
400 vg_plain_vs(ctx));
401 }
402
403 /* must be last because it renders to the depth buffer*/
404 if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
405 update_clip_state(ctx);
406 cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
407 }
408
409 shader_set_masking(ctx->shader, ctx->state.vg.masking);
410 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
411
412 ctx->state.dirty = NONE_DIRTY;
413 }
414
415 VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
416 {
417 struct vg_object *obj = ptr;
418 if (ptr && is_aligned(obj) && obj->type == type)
419 return VG_TRUE;
420 else
421 return VG_FALSE;
422 }
423
424 void vg_set_error(struct vg_context *ctx,
425 VGErrorCode code)
426 {
427 /*vgGetError returns the oldest error code provided by
428 * an API call on the current context since the previous
429 * call to vgGetError on that context (or since the creation
430 of the context).*/
431 if (ctx->_error == VG_NO_ERROR)
432 ctx->_error = code;
433 }
434
435 void vg_prepare_blend_surface(struct vg_context *ctx)
436 {
437 struct pipe_surface *dest_surface = NULL;
438 struct pipe_context *pipe = ctx->pipe;
439 struct st_framebuffer *stfb = ctx->draw_buffer;
440 struct st_renderbuffer *strb = stfb->strb;
441
442 /* first finish all pending rendering */
443 vgFinish();
444
445 dest_surface = pipe->screen->get_tex_surface(pipe->screen,
446 stfb->blend_texture,
447 0, 0, 0,
448 PIPE_BUFFER_USAGE_GPU_WRITE);
449 /* flip it, because we want to use it as a sampler */
450 util_blit_pixels_tex(ctx->blit,
451 strb->texture,
452 0, strb->height,
453 strb->width, 0,
454 dest_surface,
455 0, 0,
456 strb->width, strb->height,
457 0.0, PIPE_TEX_MIPFILTER_NEAREST);
458
459 if (dest_surface)
460 pipe_surface_reference(&dest_surface, NULL);
461
462 /* make sure it's complete */
463 vgFinish();
464 }
465
466
467 void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
468 {
469 struct pipe_surface *dest_surface = NULL;
470 struct pipe_context *pipe = ctx->pipe;
471 struct st_framebuffer *stfb = ctx->draw_buffer;
472 struct st_renderbuffer *strb = stfb->strb;
473
474 vg_validate_state(ctx);
475
476 /* first finish all pending rendering */
477 vgFinish();
478
479 dest_surface = pipe->screen->get_tex_surface(pipe->screen,
480 stfb->blend_texture,
481 0, 0, 0,
482 PIPE_BUFFER_USAGE_GPU_WRITE);
483
484 /* flip it, because we want to use it as a sampler */
485 util_blit_pixels_tex(ctx->blit,
486 stfb->alpha_mask,
487 0, strb->height,
488 strb->width, 0,
489 dest_surface,
490 0, 0,
491 strb->width, strb->height,
492 0.0, PIPE_TEX_MIPFILTER_NEAREST);
493
494 /* make sure it's complete */
495 vgFinish();
496
497 if (dest_surface)
498 pipe_surface_reference(&dest_surface, NULL);
499 }
500
501 void * vg_plain_vs(struct vg_context *ctx)
502 {
503 if (!ctx->plain_vs) {
504 ctx->plain_vs = shader_create_from_text(ctx->pipe,
505 vs_plain_asm,
506 200,
507 PIPE_SHADER_VERTEX);
508 }
509
510 return ctx->plain_vs->driver;
511 }
512
513
514 void * vg_clear_vs(struct vg_context *ctx)
515 {
516 if (!ctx->clear_vs) {
517 ctx->clear_vs = shader_create_from_text(ctx->pipe,
518 vs_clear_asm,
519 200,
520 PIPE_SHADER_VERTEX);
521 }
522
523 return ctx->clear_vs->driver;
524 }
525
526 void * vg_texture_vs(struct vg_context *ctx)
527 {
528 if (!ctx->texture_vs) {
529 ctx->texture_vs = shader_create_from_text(ctx->pipe,
530 vs_texture_asm,
531 200,
532 PIPE_SHADER_VERTEX);
533 }
534
535 return ctx->texture_vs->driver;
536 }
537
538 void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
539 {
540 struct pipe_viewport_state viewport;
541 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
542 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
543
544 viewport.scale[0] = fb->width / 2.f;
545 viewport.scale[1] = fb->height / y_scale;
546 viewport.scale[2] = 1.0;
547 viewport.scale[3] = 1.0;
548 viewport.translate[0] = fb->width / 2.f;
549 viewport.translate[1] = fb->height / 2.f;
550 viewport.translate[2] = 0.0;
551 viewport.translate[3] = 0.0;
552
553 cso_set_viewport(ctx->cso_context, &viewport);
554 }