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