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