11ebbbe54449402528e5f4e6d8cb93db9c41271f
[profile/ivi/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 #include "util/u_sampler.h"
47
48 struct vg_context *_vg_context = 0;
49
50 struct vg_context * vg_current_context(void)
51 {
52    return _vg_context;
53 }
54
55 static void init_clear(struct vg_context *st)
56 {
57    struct pipe_context *pipe = st->pipe;
58
59    /* rasterizer state: bypass clipping */
60    memset(&st->clear.raster, 0, sizeof(st->clear.raster));
61    st->clear.raster.gl_rasterization_rules = 1;
62
63    /* fragment shader state: color pass-through program */
64    st->clear.fs =
65       util_make_fragment_passthrough_shader(pipe);
66 }
67 void vg_set_current_context(struct vg_context *ctx)
68 {
69    _vg_context = ctx;
70 }
71
72 struct vg_context * vg_create_context(struct pipe_context *pipe,
73                                       const void *visual,
74                                       struct vg_context *share)
75 {
76    struct vg_context *ctx;
77    unsigned i;
78
79    ctx = CALLOC_STRUCT(vg_context);
80
81    ctx->pipe = pipe;
82
83    vg_init_state(&ctx->state.vg);
84    ctx->state.dirty = ALL_DIRTY;
85
86    ctx->cso_context = cso_create_context(pipe);
87
88    init_clear(ctx);
89
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;
93
94
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;
101
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;
108
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;
114    }
115
116    vg_set_error(ctx, VG_NO_ERROR);
117
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();
123
124    ctx->renderer = renderer_create(ctx);
125    ctx->sc = shaders_cache_create(ctx);
126    ctx->shader = shader_create(ctx);
127
128    ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
129
130    return ctx;
131 }
132
133 void vg_destroy_context(struct vg_context *ctx)
134 {
135    struct pipe_buffer **cbuf = &ctx->mask.cbuf;
136    struct pipe_buffer **vsbuf = &ctx->vs_const_buffer;
137
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);
143
144    if (*cbuf)
145       pipe_buffer_reference(cbuf, NULL);
146
147    if (*vsbuf)
148       pipe_buffer_reference(vsbuf, NULL);
149
150    if (ctx->clear.fs) {
151       cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
152       ctx->clear.fs = NULL;
153    }
154
155    if (ctx->plain_vs) {
156       vg_shader_destroy(ctx, ctx->plain_vs);
157       ctx->plain_vs = NULL;
158    }
159    if (ctx->clear_vs) {
160       vg_shader_destroy(ctx, ctx->clear_vs);
161       ctx->clear_vs = NULL;
162    }
163    if (ctx->texture_vs) {
164       vg_shader_destroy(ctx, ctx->texture_vs);
165       ctx->texture_vs = NULL;
166    }
167
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);
178
179    cso_release_all(ctx->cso_context);
180    cso_destroy_context(ctx->cso_context);
181
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]);
187
188    free(ctx);
189 }
190
191 void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
192 {
193    obj->type = type;
194    obj->ctx = ctx;
195 }
196
197 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
198                                 enum vg_object_type type,
199                                 void *ptr)
200 {
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)ptr);
206     }
207     return VG_FALSE;
208 }
209
210 void vg_context_add_object(struct vg_context *ctx,
211                            enum vg_object_type type,
212                            void *ptr)
213 {
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);
219     }
220 }
221
222 void vg_context_remove_object(struct vg_context *ctx,
223                               enum vg_object_type type,
224                               void *ptr)
225 {
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);
231    }
232 }
233
234 static void update_clip_state(struct vg_context *ctx)
235 {
236    struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
237    struct vg_state *state =  &ctx->state.vg;
238
239    memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
240
241    if (state->scissoring) {
242       struct pipe_blend_state *blend = &ctx->state.g3d.blend;
243       struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
244       int i;
245
246       dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
247       dsa->depth.func = PIPE_FUNC_ALWAYS;
248       dsa->depth.enabled = 1;
249
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,
256                                                               40,
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);
261
262       ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
263
264       /* disable color writes */
265       blend->rt[0].colormask = 0; /*disable colorwrites*/
266       cso_set_blend(ctx->cso_context, blend);
267
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;
275
276          minx = 0;
277          miny = 0;
278          maxx = fb->width;
279          maxy = fb->height;
280
281          if (x > minx)
282             minx = x;
283          if (y > miny)
284             miny = y;
285
286          if (x + width < maxx)
287             maxx = x + width;
288          if (y + height < maxy)
289             maxy = y + height;
290
291          /* check for null space */
292          if (minx >= maxx || miny >= maxy)
293             minx = miny = maxx = maxy = 0;
294
295          /*glClear(GL_DEPTH_BUFFER_BIT);*/
296          renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
297       }
298
299       cso_restore_blend(ctx->cso_context);
300       cso_restore_fragment_shader(ctx->cso_context);
301
302       dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
303       dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
304       dsa->depth.func = PIPE_FUNC_GEQUAL;
305    }
306 }
307
308 void vg_validate_state(struct vg_context *ctx)
309 {
310    vg_manager_validate_framebuffer(ctx);
311
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;
317
318       switch (ctx->state.vg.blend_mode) {
319       case VG_BLEND_SRC:
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;
325          break;
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;
331          break;
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;
337          break;
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;
343          break;
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;
349          break;
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;
359          break;
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;
365          break;
366       default:
367          assert(!"not implemented blend mode");
368       }
369       cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
370    }
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);
376    }
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,
382          -1, -1, 0, 0
383       };
384       struct pipe_buffer **cbuf = &ctx->vs_const_buffer;
385
386       vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
387
388       pipe_buffer_reference(cbuf, NULL);
389       *cbuf = pipe_buffer_create(ctx->pipe->screen, 16,
390                                         PIPE_BUFFER_USAGE_CONSTANT,
391                                         param_bytes);
392
393       if (*cbuf) {
394          st_no_flush_pipe_buffer_write(ctx, *cbuf,
395                                        0, param_bytes, vs_consts);
396       }
397       ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
398    }
399    if ((ctx->state.dirty & VS_DIRTY)) {
400       cso_set_vertex_shader_handle(ctx->cso_context,
401                                    vg_plain_vs(ctx));
402    }
403
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);
408    }
409
410    shader_set_masking(ctx->shader, ctx->state.vg.masking);
411    shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
412
413    ctx->state.dirty = NONE_DIRTY;
414 }
415
416 VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
417 {
418    struct vg_object *obj = ptr;
419    if (ptr && is_aligned(obj) && obj->type == type)
420       return VG_TRUE;
421    else
422       return VG_FALSE;
423 }
424
425 void vg_set_error(struct vg_context *ctx,
426                   VGErrorCode code)
427 {
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
431     of the context).*/
432    if (ctx->_error == VG_NO_ERROR)
433       ctx->_error = code;
434 }
435
436 void vg_prepare_blend_surface(struct vg_context *ctx)
437 {
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;
444
445    /* first finish all pending rendering */
446    vgFinish();
447
448    u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
449    view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
450
451    dest_surface = pipe->screen->get_tex_surface(pipe->screen,
452                                                 stfb->blend_texture_view->texture,
453                                                 0, 0, 0,
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,
457                         view,
458                         0, strb->height,
459                         strb->width, 0,
460                         dest_surface,
461                         0, 0,
462                         strb->width, strb->height,
463                         0.0, PIPE_TEX_MIPFILTER_NEAREST);
464
465    if (dest_surface)
466       pipe_surface_reference(&dest_surface, NULL);
467
468    /* make sure it's complete */
469    vgFinish();
470
471    pipe_sampler_view_reference(&view, NULL);
472 }
473
474
475 void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
476 {
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;
481
482    vg_validate_state(ctx);
483
484    /* first finish all pending rendering */
485    vgFinish();
486
487    dest_surface = pipe->screen->get_tex_surface(pipe->screen,
488                                                 stfb->blend_texture_view->texture,
489                                                 0, 0, 0,
490                                                 PIPE_BUFFER_USAGE_GPU_WRITE);
491
492    /* flip it, because we want to use it as a sampler */
493    util_blit_pixels_tex(ctx->blit,
494                         stfb->alpha_mask_view,
495                         0, strb->height,
496                         strb->width, 0,
497                         dest_surface,
498                         0, 0,
499                         strb->width, strb->height,
500                         0.0, PIPE_TEX_MIPFILTER_NEAREST);
501
502    /* make sure it's complete */
503    vgFinish();
504
505    if (dest_surface)
506       pipe_surface_reference(&dest_surface, NULL);
507 }
508
509 void * vg_plain_vs(struct vg_context *ctx)
510 {
511    if (!ctx->plain_vs) {
512       ctx->plain_vs = shader_create_from_text(ctx->pipe,
513                                               vs_plain_asm,
514                                               200,
515                                               PIPE_SHADER_VERTEX);
516    }
517
518    return ctx->plain_vs->driver;
519 }
520
521
522 void * vg_clear_vs(struct vg_context *ctx)
523 {
524    if (!ctx->clear_vs) {
525       ctx->clear_vs = shader_create_from_text(ctx->pipe,
526                                               vs_clear_asm,
527                                               200,
528                                               PIPE_SHADER_VERTEX);
529    }
530
531    return ctx->clear_vs->driver;
532 }
533
534 void * vg_texture_vs(struct vg_context *ctx)
535 {
536    if (!ctx->texture_vs) {
537       ctx->texture_vs = shader_create_from_text(ctx->pipe,
538                                                 vs_texture_asm,
539                                                 200,
540                                                 PIPE_SHADER_VERTEX);
541    }
542
543    return ctx->texture_vs->driver;
544 }
545
546 void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
547 {
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;
551
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;
560
561    cso_set_viewport(ctx->cso_context, &viewport);
562 }