sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / state_trackers / vega / renderer.c
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.  All Rights Reserved.
4  * Copyright 2010 LunarG, Inc.  All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27
28 #include "renderer.h"
29
30 #include "vg_context.h"
31
32 #include "pipe/p_context.h"
33 #include "pipe/p_state.h"
34 #include "util/u_inlines.h"
35 #include "pipe/p_screen.h"
36 #include "pipe/p_shader_tokens.h"
37
38 #include "util/u_draw_quad.h"
39 #include "util/u_simple_shaders.h"
40 #include "util/u_memory.h"
41 #include "util/u_sampler.h"
42 #include "util/u_surface.h"
43 #include "util/u_math.h"
44 #include "util/u_format.h"
45
46 #include "cso_cache/cso_context.h"
47 #include "tgsi/tgsi_ureg.h"
48
49 typedef enum {
50    RENDERER_STATE_INIT,
51    RENDERER_STATE_COPY,
52    RENDERER_STATE_DRAWTEX,
53    RENDERER_STATE_SCISSOR,
54    RENDERER_STATE_CLEAR,
55    RENDERER_STATE_FILTER,
56    RENDERER_STATE_POLYGON_STENCIL,
57    RENDERER_STATE_POLYGON_FILL,
58    NUM_RENDERER_STATES
59 } RendererState;
60
61 typedef enum {
62    RENDERER_VS_PLAIN,
63    RENDERER_VS_COLOR,
64    RENDERER_VS_TEXTURE,
65    NUM_RENDERER_VS
66 } RendererVs;
67
68 typedef enum {
69    RENDERER_FS_COLOR,
70    RENDERER_FS_TEXTURE,
71    RENDERER_FS_SCISSOR,
72    RENDERER_FS_WHITE,
73    NUM_RENDERER_FS
74 } RendererFs;
75
76 struct renderer {
77    struct pipe_context *pipe;
78    struct cso_context *cso;
79
80    VGbitfield dirty;
81    struct {
82       struct pipe_rasterizer_state rasterizer;
83       struct pipe_depth_stencil_alpha_state dsa;
84       struct pipe_framebuffer_state fb;
85    } g3d;
86    struct matrix projection;
87
88    struct matrix mvp;
89    struct pipe_resource *vs_cbuf;
90
91    struct pipe_resource *fs_cbuf;
92    VGfloat fs_cbuf_data[32];
93    VGint fs_cbuf_len;
94
95    struct pipe_vertex_element velems[2];
96    VGfloat vertices[4][2][4];
97
98    void *cached_vs[NUM_RENDERER_VS];
99    void *cached_fs[NUM_RENDERER_FS];
100
101    RendererState state;
102
103    /* state data */
104    union {
105       struct {
106          VGint tex_width;
107          VGint tex_height;
108       } copy;
109
110       struct {
111          VGint tex_width;
112          VGint tex_height;
113       } drawtex;
114
115       struct {
116          VGboolean restore_dsa;
117       } scissor;
118
119       struct {
120          VGboolean use_sampler;
121          VGint tex_width, tex_height;
122       } filter;
123
124       struct {
125          struct pipe_depth_stencil_alpha_state dsa;
126          VGboolean manual_two_sides;
127          VGboolean restore_dsa;
128       } polygon_stencil;
129    } u;
130 };
131
132 /**
133  * Return VG_TRUE if the renderer can use the resource as the asked bindings.
134  */
135 static VGboolean renderer_can_support(struct renderer *renderer,
136                                       struct pipe_resource *res,
137                                       unsigned bindings)
138 {
139    struct pipe_screen *screen = renderer->pipe->screen;
140
141    return screen->is_format_supported(screen,
142          res->format, res->target, 0, bindings);
143 }
144
145 /**
146  * Set the model-view-projection matrix used by vertex shaders.
147  */
148 static void renderer_set_mvp(struct renderer *renderer,
149                              const struct matrix *mvp)
150 {
151    struct matrix *cur = &renderer->mvp;
152    struct pipe_resource *cbuf;
153    VGfloat consts[3][4];
154    VGint i;
155
156    /* projection only */
157    if (!mvp)
158       mvp = &renderer->projection;
159
160    /* re-upload only if necessary */
161    if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
162       return;
163
164    /* 3x3 matrix to 3 constant vectors (no Z) */
165    for (i = 0; i < 3; i++) {
166       consts[i][0] = mvp->m[i + 0];
167       consts[i][1] = mvp->m[i + 3];
168       consts[i][2] = 0.0f;
169       consts[i][3] = mvp->m[i + 6];
170    }
171
172    cbuf = renderer->vs_cbuf;
173    pipe_resource_reference(&cbuf, NULL);
174    cbuf = pipe_buffer_create(renderer->pipe->screen,
175                              PIPE_BIND_CONSTANT_BUFFER,
176                              PIPE_USAGE_STATIC,
177                              sizeof(consts));
178    if (cbuf) {
179       pipe_buffer_write(renderer->pipe, cbuf,
180             0, sizeof(consts), consts);
181    }
182    renderer->pipe->set_constant_buffer(renderer->pipe,
183          PIPE_SHADER_VERTEX, 0, cbuf);
184
185    memcpy(cur, mvp, sizeof(*mvp));
186    renderer->vs_cbuf = cbuf;
187 }
188
189 /**
190  * Create a simple vertex shader that passes through position and the given
191  * attribute.
192  */
193 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
194 {
195    struct ureg_program *ureg;
196    struct ureg_src src[2], constants[3];
197    struct ureg_dst dst[2], tmp;
198    int i;
199
200    ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
201    if (!ureg)
202       return NULL;
203
204    /* position is in user coordinates */
205    src[0] = ureg_DECL_vs_input(ureg, 0);
206    dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
207    tmp = ureg_DECL_temporary(ureg);
208    for (i = 0; i < Elements(constants); i++)
209       constants[i] = ureg_DECL_constant(ureg, i);
210
211    /* transform to clipped coordinates */
212    ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
213    ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
214    ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
215    ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
216    ureg_MOV(ureg, dst[0], ureg_src(tmp));
217
218    if (semantic_name >= 0) {
219       src[1] = ureg_DECL_vs_input(ureg, 1);
220       dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
221       ureg_MOV(ureg, dst[1], src[1]);
222    }
223
224    ureg_END(ureg);
225
226    return ureg_create_shader_and_destroy(ureg, pipe);
227 }
228
229 /**
230  * Set renderer vertex shader.
231  *
232  * This function modifies vertex_shader state.
233  */
234 static void renderer_set_vs(struct renderer *r, RendererVs id)
235 {
236    /* create as needed */
237    if (!r->cached_vs[id]) {
238       int semantic_name = -1;
239
240       switch (id) {
241       case RENDERER_VS_PLAIN:
242          break;
243       case RENDERER_VS_COLOR:
244          semantic_name = TGSI_SEMANTIC_COLOR;
245          break;
246       case RENDERER_VS_TEXTURE:
247          semantic_name = TGSI_SEMANTIC_GENERIC;
248          break;
249       default:
250          assert(!"Unknown renderer vs id");
251          break;
252       }
253
254       r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
255    }
256
257    cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
258 }
259
260 /**
261  * Create a simple fragment shader that sets the depth to 0.0f.
262  */
263 static void *create_scissor_fs(struct pipe_context *pipe)
264 {
265    struct ureg_program *ureg;
266    struct ureg_dst out;
267    struct ureg_src imm;
268
269    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
270    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
271    imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
272
273    ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
274    ureg_END(ureg);
275
276    return ureg_create_shader_and_destroy(ureg, pipe);
277 }
278
279 /**
280  * Create a simple fragment shader that sets the color to white.
281  */
282 static void *create_white_fs(struct pipe_context *pipe)
283 {
284    struct ureg_program *ureg;
285    struct ureg_dst out;
286    struct ureg_src imm;
287
288    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
289    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
290    imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
291
292    ureg_MOV(ureg, out, imm);
293    ureg_END(ureg);
294
295    return ureg_create_shader_and_destroy(ureg, pipe);
296 }
297
298 /**
299  * Set renderer fragment shader.
300  *
301  * This function modifies fragment_shader state.
302  */
303 static void renderer_set_fs(struct renderer *r, RendererFs id)
304 {
305    /* create as needed */
306    if (!r->cached_fs[id]) {
307       void *fs = NULL;
308
309       switch (id) {
310       case RENDERER_FS_COLOR:
311          fs = util_make_fragment_passthrough_shader(r->pipe);
312          break;
313       case RENDERER_FS_TEXTURE:
314          fs = util_make_fragment_tex_shader(r->pipe,
315                TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
316          break;
317       case RENDERER_FS_SCISSOR:
318          fs = create_scissor_fs(r->pipe);
319          break;
320       case RENDERER_FS_WHITE:
321          fs = create_white_fs(r->pipe);
322          break;
323       default:
324          assert(!"Unknown renderer fs id");
325          break;
326       }
327
328       r->cached_fs[id] = fs;
329    }
330
331    cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
332 }
333
334 typedef enum {
335    VEGA_Y0_TOP,
336    VEGA_Y0_BOTTOM
337 } VegaOrientation;
338
339 static void vg_set_viewport(struct renderer *r,
340                             VegaOrientation orientation)
341 {
342    const struct pipe_framebuffer_state *fb = &r->g3d.fb;
343    struct pipe_viewport_state viewport;
344    VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
345
346    viewport.scale[0] =  fb->width / 2.f;
347    viewport.scale[1] =  fb->height / y_scale;
348    viewport.scale[2] =  1.0;
349    viewport.scale[3] =  1.0;
350    viewport.translate[0] = fb->width / 2.f;
351    viewport.translate[1] = fb->height / 2.f;
352    viewport.translate[2] = 0.0;
353    viewport.translate[3] = 0.0;
354
355    cso_set_viewport(r->cso, &viewport);
356 }
357
358 /**
359  * Set renderer target.
360  *
361  * This function modifies framebuffer and viewport states.
362  */
363 static void renderer_set_target(struct renderer *r,
364                                 struct pipe_surface *cbuf,
365                                 struct pipe_surface *zsbuf,
366                                 VGboolean y0_top)
367 {
368    struct pipe_framebuffer_state fb;
369
370    memset(&fb, 0, sizeof(fb));
371    fb.width = cbuf->width;
372    fb.height = cbuf->height;
373    fb.cbufs[0] = cbuf;
374    fb.nr_cbufs = 1;
375    fb.zsbuf = zsbuf;
376    cso_set_framebuffer(r->cso, &fb);
377
378    vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
379 }
380
381 /**
382  * Set renderer blend state.  Blending is disabled.
383  *
384  * This function modifies blend state.
385  */
386 static void renderer_set_blend(struct renderer *r,
387                                VGbitfield channel_mask)
388 {
389    struct pipe_blend_state blend;
390
391    memset(&blend, 0, sizeof(blend));
392
393    blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
394    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
395    blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
396    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
397
398    if (channel_mask & VG_RED)
399       blend.rt[0].colormask |= PIPE_MASK_R;
400    if (channel_mask & VG_GREEN)
401       blend.rt[0].colormask |= PIPE_MASK_G;
402    if (channel_mask & VG_BLUE)
403       blend.rt[0].colormask |= PIPE_MASK_B;
404    if (channel_mask & VG_ALPHA)
405       blend.rt[0].colormask |= PIPE_MASK_A;
406
407    cso_set_blend(r->cso, &blend);
408 }
409
410 /**
411  * Set renderer sampler and view states.
412  *
413  * This function modifies samplers and fragment_sampler_views states.
414  */
415 static void renderer_set_samplers(struct renderer *r,
416                                   uint num_views,
417                                   struct pipe_sampler_view **views)
418 {
419    struct pipe_sampler_state sampler;
420    unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
421    unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
422    uint i;
423
424    memset(&sampler, 0, sizeof(sampler));
425
426    sampler.min_img_filter = tex_filter;
427    sampler.mag_img_filter = tex_filter;
428    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
429
430    sampler.wrap_s = tex_wrap;
431    sampler.wrap_t = tex_wrap;
432    sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
433
434    sampler.normalized_coords = 1;
435
436    /* set samplers */
437    for (i = 0; i < num_views; i++)
438       cso_single_sampler(r->cso, i, &sampler);
439    cso_single_sampler_done(r->cso);
440
441    /* set views */
442    cso_set_fragment_sampler_views(r->cso, num_views, views);
443 }
444
445 /**
446  * Set custom renderer fragment shader, and optionally set samplers and views
447  * and upload the fragment constant buffer.
448  *
449  * This function modifies fragment_shader, samplers and fragment_sampler_views
450  * states.
451  */
452 static void renderer_set_custom_fs(struct renderer *renderer,
453                                    void *fs,
454                                    const struct pipe_sampler_state **samplers,
455                                    struct pipe_sampler_view **views,
456                                    VGint num_samplers,
457                                    const void *const_buffer,
458                                    VGint const_buffer_len)
459 {
460    cso_set_fragment_shader_handle(renderer->cso, fs);
461
462    /* set samplers and views */
463    if (num_samplers) {
464       cso_set_samplers(renderer->cso, num_samplers, samplers);
465       cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
466    }
467
468    /* upload fs constant buffer */
469    if (const_buffer_len) {
470       struct pipe_resource *cbuf = renderer->fs_cbuf;
471
472       if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
473           memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
474          pipe_resource_reference(&cbuf, NULL);
475
476          cbuf = pipe_buffer_create(renderer->pipe->screen,
477                PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
478                const_buffer_len);
479          pipe_buffer_write(renderer->pipe, cbuf, 0,
480                const_buffer_len, const_buffer);
481          renderer->pipe->set_constant_buffer(renderer->pipe,
482                PIPE_SHADER_FRAGMENT, 0, cbuf);
483
484          renderer->fs_cbuf = cbuf;
485          if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
486             memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
487             renderer->fs_cbuf_len = const_buffer_len;
488          }
489          else {
490             renderer->fs_cbuf_len = 0;
491          }
492       }
493    }
494 }
495
496 /**
497  * Setup renderer quad position.
498  */
499 static void renderer_quad_pos(struct renderer *r,
500                               VGfloat x0, VGfloat y0,
501                               VGfloat x1, VGfloat y1,
502                               VGboolean scissor)
503 {
504    VGfloat z;
505
506    /* the depth test is used for scissoring */
507    z = (scissor) ? 0.0f : 1.0f;
508
509    /* positions */
510    r->vertices[0][0][0] = x0;
511    r->vertices[0][0][1] = y0;
512    r->vertices[0][0][2] = z;
513
514    r->vertices[1][0][0] = x1;
515    r->vertices[1][0][1] = y0;
516    r->vertices[1][0][2] = z;
517
518    r->vertices[2][0][0] = x1;
519    r->vertices[2][0][1] = y1;
520    r->vertices[2][0][2] = z;
521
522    r->vertices[3][0][0] = x0;
523    r->vertices[3][0][1] = y1;
524    r->vertices[3][0][2] = z;
525 }
526
527 /**
528  * Setup renderer quad texture coordinates.
529  */
530 static void renderer_quad_texcoord(struct renderer *r,
531                                    VGfloat x0, VGfloat y0,
532                                    VGfloat x1, VGfloat y1,
533                                    VGint tex_width, VGint tex_height)
534 {
535    VGfloat s0, t0, s1, t1, r0, q0;
536    VGint i;
537
538    s0 = x0 / tex_width;
539    s1 = x1 / tex_width;
540    t0 = y0 / tex_height;
541    t1 = y1 / tex_height;
542    r0 = 0.0f;
543    q0 = 1.0f;
544
545    /* texcoords */
546    r->vertices[0][1][0] = s0;
547    r->vertices[0][1][1] = t0;
548
549    r->vertices[1][1][0] = s1;
550    r->vertices[1][1][1] = t0;
551
552    r->vertices[2][1][0] = s1;
553    r->vertices[2][1][1] = t1;
554
555    r->vertices[3][1][0] = s0;
556    r->vertices[3][1][1] = t1;
557
558    for (i = 0; i < 4; i++) {
559       r->vertices[i][1][2] = r0;
560       r->vertices[i][1][3] = q0;
561    }
562 }
563
564 /**
565  * Draw renderer quad.
566  */
567 static void renderer_quad_draw(struct renderer *r)
568 {
569    struct pipe_resource *buf;
570
571    buf = pipe_user_buffer_create(r->pipe->screen,
572                                  r->vertices,
573                                  sizeof(r->vertices),
574                                  PIPE_BIND_VERTEX_BUFFER);
575    if (buf) {
576       util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
577                               PIPE_PRIM_TRIANGLE_FAN,
578                               Elements(r->vertices),     /* verts */
579                               Elements(r->vertices[0])); /* attribs/vert */
580
581       pipe_resource_reference(&buf, NULL);
582    }
583 }
584
585 /**
586  * Prepare the renderer for copying.
587  */
588 VGboolean renderer_copy_begin(struct renderer *renderer,
589                               struct pipe_surface *dst,
590                               VGboolean y0_top,
591                               struct pipe_sampler_view *src)
592 {
593    assert(renderer->state == RENDERER_STATE_INIT);
594
595    /* sanity check */
596    if (!renderer_can_support(renderer,
597             dst->texture, PIPE_BIND_RENDER_TARGET) ||
598        !renderer_can_support(renderer,
599           src->texture, PIPE_BIND_SAMPLER_VIEW))
600       return VG_FALSE;
601
602    cso_save_framebuffer(renderer->cso);
603    cso_save_viewport(renderer->cso);
604    cso_save_blend(renderer->cso);
605    cso_save_samplers(renderer->cso);
606    cso_save_fragment_sampler_views(renderer->cso);
607    cso_save_fragment_shader(renderer->cso);
608    cso_save_vertex_shader(renderer->cso);
609
610    renderer_set_target(renderer, dst, NULL, y0_top);
611
612    renderer_set_blend(renderer, ~0);
613    renderer_set_samplers(renderer, 1, &src);
614
615    renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
616    renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
617
618    renderer_set_mvp(renderer, NULL);
619
620    /* remember the texture size */
621    renderer->u.copy.tex_width = src->texture->width0;
622    renderer->u.copy.tex_height = src->texture->height0;
623    renderer->state = RENDERER_STATE_COPY;
624
625    return VG_TRUE;
626 }
627
628 /**
629  * Draw into the destination rectangle given by (x, y, w, h).  The texture is
630  * sampled from within the rectangle given by (sx, sy, sw, sh).
631  *
632  * The coordinates are in surface coordinates.
633  */
634 void renderer_copy(struct renderer *renderer,
635                    VGint x, VGint y, VGint w, VGint h,
636                    VGint sx, VGint sy, VGint sw, VGint sh)
637 {
638    assert(renderer->state == RENDERER_STATE_COPY);
639
640    /* there is no depth buffer for scissoring anyway */
641    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
642    renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
643          renderer->u.copy.tex_width,
644          renderer->u.copy.tex_height);
645
646    renderer_quad_draw(renderer);
647 }
648
649 /**
650  * End copying and restore the states.
651  */
652 void renderer_copy_end(struct renderer *renderer)
653 {
654    assert(renderer->state == RENDERER_STATE_COPY);
655
656    cso_restore_framebuffer(renderer->cso);
657    cso_restore_viewport(renderer->cso);
658    cso_restore_blend(renderer->cso);
659    cso_restore_samplers(renderer->cso);
660    cso_restore_fragment_sampler_views(renderer->cso);
661    cso_restore_fragment_shader(renderer->cso);
662    cso_restore_vertex_shader(renderer->cso);
663
664    renderer->state = RENDERER_STATE_INIT;
665 }
666
667 /**
668  * Prepare the renderer for textured drawing.
669  */
670 VGboolean renderer_drawtex_begin(struct renderer *renderer,
671                                  struct pipe_sampler_view *src)
672 {
673    assert(renderer->state == RENDERER_STATE_INIT);
674
675    if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
676       return VG_FALSE;
677
678    cso_save_blend(renderer->cso);
679    cso_save_samplers(renderer->cso);
680    cso_save_fragment_sampler_views(renderer->cso);
681    cso_save_fragment_shader(renderer->cso);
682    cso_save_vertex_shader(renderer->cso);
683
684    renderer_set_blend(renderer, ~0);
685
686    renderer_set_samplers(renderer, 1, &src);
687
688    renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
689    renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
690
691    renderer_set_mvp(renderer, NULL);
692
693    /* remember the texture size */
694    renderer->u.drawtex.tex_width = src->texture->width0;
695    renderer->u.drawtex.tex_height = src->texture->height0;
696    renderer->state = RENDERER_STATE_DRAWTEX;
697
698    return VG_TRUE;
699 }
700
701 /**
702  * Draw into the destination rectangle given by (x, y, w, h).  The texture is
703  * sampled from within the rectangle given by (sx, sy, sw, sh).
704  *
705  * The coordinates are in surface coordinates.
706  */
707 void renderer_drawtex(struct renderer *renderer,
708                       VGint x, VGint y, VGint w, VGint h,
709                       VGint sx, VGint sy, VGint sw, VGint sh)
710 {
711    assert(renderer->state == RENDERER_STATE_DRAWTEX);
712
713    /* with scissoring */
714    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
715    renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
716          renderer->u.drawtex.tex_width,
717          renderer->u.drawtex.tex_height);
718
719    renderer_quad_draw(renderer);
720 }
721
722 /**
723  * End textured drawing and restore the states.
724  */
725 void renderer_drawtex_end(struct renderer *renderer)
726 {
727    assert(renderer->state == RENDERER_STATE_DRAWTEX);
728
729    cso_restore_blend(renderer->cso);
730    cso_restore_samplers(renderer->cso);
731    cso_restore_fragment_sampler_views(renderer->cso);
732    cso_restore_fragment_shader(renderer->cso);
733    cso_restore_vertex_shader(renderer->cso);
734
735    renderer->state = RENDERER_STATE_INIT;
736 }
737
738 /**
739  * Prepare the renderer for scissor update.  This will reset the depth buffer
740  * to 1.0f.
741  */
742 VGboolean renderer_scissor_begin(struct renderer *renderer,
743                                  VGboolean restore_dsa)
744 {
745    struct pipe_depth_stencil_alpha_state dsa;
746
747    assert(renderer->state == RENDERER_STATE_INIT);
748
749    if (restore_dsa)
750       cso_save_depth_stencil_alpha(renderer->cso);
751    cso_save_blend(renderer->cso);
752    cso_save_fragment_shader(renderer->cso);
753
754    /* enable depth writes */
755    memset(&dsa, 0, sizeof(dsa));
756    dsa.depth.enabled = 1;
757    dsa.depth.writemask = 1;
758    dsa.depth.func = PIPE_FUNC_ALWAYS;
759    cso_set_depth_stencil_alpha(renderer->cso, &dsa);
760
761    /* disable color writes */
762    renderer_set_blend(renderer, 0);
763    renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
764
765    renderer_set_mvp(renderer, NULL);
766
767    renderer->u.scissor.restore_dsa = restore_dsa;
768    renderer->state = RENDERER_STATE_SCISSOR;
769
770    /* clear the depth buffer to 1.0f */
771    renderer->pipe->clear(renderer->pipe,
772          PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
773
774    return VG_TRUE;
775 }
776
777 /**
778  * Add a scissor rectangle.  Depth values inside the rectangle will be set to
779  * 0.0f.
780  */
781 void renderer_scissor(struct renderer *renderer,
782                       VGint x, VGint y, VGint width, VGint height)
783 {
784    assert(renderer->state == RENDERER_STATE_SCISSOR);
785
786    renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
787    renderer_quad_draw(renderer);
788 }
789
790 /**
791  * End scissor update and restore the states.
792  */
793 void renderer_scissor_end(struct renderer *renderer)
794 {
795    assert(renderer->state == RENDERER_STATE_SCISSOR);
796
797    if (renderer->u.scissor.restore_dsa)
798       cso_restore_depth_stencil_alpha(renderer->cso);
799    cso_restore_blend(renderer->cso);
800    cso_restore_fragment_shader(renderer->cso);
801
802    renderer->state = RENDERER_STATE_INIT;
803 }
804
805 /**
806  * Prepare the renderer for clearing.
807  */
808 VGboolean renderer_clear_begin(struct renderer *renderer)
809 {
810    assert(renderer->state == RENDERER_STATE_INIT);
811
812    cso_save_blend(renderer->cso);
813    cso_save_fragment_shader(renderer->cso);
814    cso_save_vertex_shader(renderer->cso);
815
816    renderer_set_blend(renderer, ~0);
817    renderer_set_fs(renderer, RENDERER_FS_COLOR);
818    renderer_set_vs(renderer, RENDERER_VS_COLOR);
819
820    renderer_set_mvp(renderer, NULL);
821
822    renderer->state = RENDERER_STATE_CLEAR;
823
824    return VG_TRUE;
825 }
826
827 /**
828  * Clear the framebuffer with the specified region and color.
829  *
830  * The coordinates are in surface coordinates.
831  */
832 void renderer_clear(struct renderer *renderer,
833                     VGint x, VGint y, VGint width, VGint height,
834                     const VGfloat color[4])
835 {
836    VGuint i;
837
838    assert(renderer->state == RENDERER_STATE_CLEAR);
839
840    renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
841    for (i = 0; i < 4; i++)
842       memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
843
844    renderer_quad_draw(renderer);
845 }
846
847 /**
848  * End clearing and retore the states.
849  */
850 void renderer_clear_end(struct renderer *renderer)
851 {
852    assert(renderer->state == RENDERER_STATE_CLEAR);
853
854    cso_restore_blend(renderer->cso);
855    cso_restore_fragment_shader(renderer->cso);
856    cso_restore_vertex_shader(renderer->cso);
857
858    renderer->state = RENDERER_STATE_INIT;
859 }
860
861 /**
862  * Prepare the renderer for image filtering.
863  */
864 VGboolean renderer_filter_begin(struct renderer *renderer,
865                                 struct pipe_resource *dst,
866                                 VGboolean y0_top,
867                                 VGbitfield channel_mask,
868                                 const struct pipe_sampler_state **samplers,
869                                 struct pipe_sampler_view **views,
870                                 VGint num_samplers,
871                                 void *fs,
872                                 const void *const_buffer,
873                                 VGint const_buffer_len)
874 {
875    struct pipe_surface *surf, surf_tmpl;
876
877    assert(renderer->state == RENDERER_STATE_INIT);
878
879    if (!fs)
880       return VG_FALSE;
881    if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
882       return VG_FALSE;
883
884    u_surface_default_template(&surf_tmpl, dst,
885                               PIPE_BIND_RENDER_TARGET);
886    surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
887    if (!surf)
888       return VG_FALSE;
889
890    cso_save_framebuffer(renderer->cso);
891    cso_save_viewport(renderer->cso);
892    cso_save_blend(renderer->cso);
893
894    /* set the image as the target */
895    renderer_set_target(renderer, surf, NULL, y0_top);
896    pipe_surface_reference(&surf, NULL);
897
898    renderer_set_blend(renderer, channel_mask);
899
900    if (num_samplers) {
901       struct pipe_resource *tex;
902
903       cso_save_samplers(renderer->cso);
904       cso_save_fragment_sampler_views(renderer->cso);
905       cso_save_fragment_shader(renderer->cso);
906       cso_save_vertex_shader(renderer->cso);
907
908       renderer_set_custom_fs(renderer, fs,
909                              samplers, views, num_samplers,
910                              const_buffer, const_buffer_len);
911       renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
912
913       tex = views[0]->texture;
914       renderer->u.filter.tex_width = tex->width0;
915       renderer->u.filter.tex_height = tex->height0;
916       renderer->u.filter.use_sampler = VG_TRUE;
917    }
918    else {
919       cso_save_fragment_shader(renderer->cso);
920
921       renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
922                              const_buffer, const_buffer_len);
923
924       renderer->u.filter.use_sampler = VG_FALSE;
925    }
926
927    renderer_set_mvp(renderer, NULL);
928
929    renderer->state = RENDERER_STATE_FILTER;
930
931    return VG_TRUE;
932 }
933
934 /**
935  * Draw into a rectangle of the destination with the specified region of the
936  * texture(s).
937  *
938  * The coordinates are in surface coordinates.
939  */
940 void renderer_filter(struct renderer *renderer,
941                     VGint x, VGint y, VGint w, VGint h,
942                     VGint sx, VGint sy, VGint sw, VGint sh)
943 {
944    assert(renderer->state == RENDERER_STATE_FILTER);
945
946    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
947    if (renderer->u.filter.use_sampler) {
948       renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
949             renderer->u.filter.tex_width,
950             renderer->u.filter.tex_height);
951    }
952
953    renderer_quad_draw(renderer);
954 }
955
956 /**
957  * End image filtering and restore the states.
958  */
959 void renderer_filter_end(struct renderer *renderer)
960 {
961    assert(renderer->state == RENDERER_STATE_FILTER);
962
963    if (renderer->u.filter.use_sampler) {
964       cso_restore_samplers(renderer->cso);
965       cso_restore_fragment_sampler_views(renderer->cso);
966       cso_restore_vertex_shader(renderer->cso);
967    }
968
969    cso_restore_framebuffer(renderer->cso);
970    cso_restore_viewport(renderer->cso);
971    cso_restore_blend(renderer->cso);
972    cso_restore_fragment_shader(renderer->cso);
973
974    renderer->state = RENDERER_STATE_INIT;
975 }
976
977 /**
978  * Prepare the renderer for polygon silhouette rendering.
979  */
980 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
981                                          struct pipe_vertex_element *velem,
982                                          VGFillRule rule,
983                                          VGboolean restore_dsa)
984 {
985    struct pipe_depth_stencil_alpha_state *dsa;
986    VGboolean manual_two_sides;
987
988    assert(renderer->state == RENDERER_STATE_INIT);
989
990    cso_save_vertex_elements(renderer->cso);
991    cso_save_blend(renderer->cso);
992    cso_save_depth_stencil_alpha(renderer->cso);
993
994    cso_set_vertex_elements(renderer->cso, 1, velem);
995
996    /* disable color writes */
997    renderer_set_blend(renderer, 0);
998
999    manual_two_sides = VG_FALSE;
1000    dsa = &renderer->u.polygon_stencil.dsa;
1001    memset(dsa, 0, sizeof(*dsa));
1002    if (rule == VG_EVEN_ODD) {
1003       dsa->stencil[0].enabled = 1;
1004       dsa->stencil[0].writemask = 1;
1005       dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1006       dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1007       dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1008       dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1009       dsa->stencil[0].valuemask = ~0;
1010    }
1011    else {
1012       assert(rule == VG_NON_ZERO);
1013
1014       /* front face */
1015       dsa->stencil[0].enabled = 1;
1016       dsa->stencil[0].writemask = ~0;
1017       dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1018       dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1019       dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1020       dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1021       dsa->stencil[0].valuemask = ~0;
1022
1023       if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1024                                             PIPE_CAP_TWO_SIDED_STENCIL)) {
1025          /* back face */
1026          dsa->stencil[1] = dsa->stencil[0];
1027          dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1028       }
1029       else {
1030          manual_two_sides = VG_TRUE;
1031       }
1032    }
1033    cso_set_depth_stencil_alpha(renderer->cso, dsa);
1034
1035    if (manual_two_sides)
1036       cso_save_rasterizer(renderer->cso);
1037
1038    renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1039    renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1040    renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1041
1042    return VG_TRUE;
1043 }
1044
1045 /**
1046  * Render a polygon silhouette to stencil buffer.
1047  */
1048 void renderer_polygon_stencil(struct renderer *renderer,
1049                               struct pipe_vertex_buffer *vbuf,
1050                               VGuint mode, VGuint start, VGuint count)
1051 {
1052    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1053
1054    cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1055
1056    if (!renderer->u.polygon_stencil.manual_two_sides) {
1057       util_draw_arrays(renderer->pipe, mode, start, count);
1058    }
1059    else {
1060       struct pipe_rasterizer_state raster;
1061       struct pipe_depth_stencil_alpha_state dsa;
1062
1063       raster = renderer->g3d.rasterizer;
1064       dsa = renderer->u.polygon_stencil.dsa;
1065
1066       /* front */
1067       raster.cull_face = PIPE_FACE_BACK;
1068       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1069
1070       cso_set_rasterizer(renderer->cso, &raster);
1071       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1072       util_draw_arrays(renderer->pipe, mode, start, count);
1073
1074       /* back */
1075       raster.cull_face = PIPE_FACE_FRONT;
1076       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1077
1078       cso_set_rasterizer(renderer->cso, &raster);
1079       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1080       util_draw_arrays(renderer->pipe, mode, start, count);
1081    }
1082 }
1083
1084 /**
1085  * End polygon silhouette rendering.
1086  */
1087 void renderer_polygon_stencil_end(struct renderer *renderer)
1088 {
1089    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1090
1091    if (renderer->u.polygon_stencil.manual_two_sides)
1092       cso_restore_rasterizer(renderer->cso);
1093
1094    cso_restore_vertex_elements(renderer->cso);
1095
1096    /* restore color writes */
1097    cso_restore_blend(renderer->cso);
1098
1099    if (renderer->u.polygon_stencil.restore_dsa)
1100       cso_restore_depth_stencil_alpha(renderer->cso);
1101
1102    renderer->state = RENDERER_STATE_INIT;
1103 }
1104
1105 /**
1106  * Prepare the renderer for polygon filling.
1107  */
1108 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1109                                       VGboolean save_dsa)
1110 {
1111    struct pipe_depth_stencil_alpha_state dsa;
1112
1113    assert(renderer->state == RENDERER_STATE_INIT);
1114
1115    if (save_dsa)
1116       cso_save_depth_stencil_alpha(renderer->cso);
1117
1118    /* setup stencil ops */
1119    memset(&dsa, 0, sizeof(dsa));
1120    dsa.stencil[0].enabled = 1;
1121    dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1122    dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1123    dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1124    dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1125    dsa.stencil[0].valuemask = ~0;
1126    dsa.stencil[0].writemask = ~0;
1127    dsa.depth = renderer->g3d.dsa.depth;
1128    cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1129
1130    renderer->state = RENDERER_STATE_POLYGON_FILL;
1131
1132    return VG_TRUE;
1133 }
1134
1135 /**
1136  * Fill a polygon.
1137  */
1138 void renderer_polygon_fill(struct renderer *renderer,
1139                            VGfloat min_x, VGfloat min_y,
1140                            VGfloat max_x, VGfloat max_y)
1141 {
1142    assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1143
1144    renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1145    renderer_quad_draw(renderer);
1146 }
1147
1148 /**
1149  * End polygon filling.
1150  */
1151 void renderer_polygon_fill_end(struct renderer *renderer)
1152 {
1153    assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1154
1155    cso_restore_depth_stencil_alpha(renderer->cso);
1156
1157    renderer->state = RENDERER_STATE_INIT;
1158 }
1159
1160 struct renderer * renderer_create(struct vg_context *owner)
1161 {
1162    struct renderer *renderer;
1163    struct pipe_rasterizer_state *raster;
1164    struct pipe_stencil_ref sr;
1165    VGint i;
1166
1167    renderer = CALLOC_STRUCT(renderer);
1168    if (!renderer)
1169       return NULL;
1170
1171    renderer->pipe = owner->pipe;
1172    renderer->cso = owner->cso_context;
1173
1174    /* init vertex data that doesn't change */
1175    for (i = 0; i < 4; i++)
1176       renderer->vertices[i][0][3] = 1.0f; /* w */
1177
1178    for (i = 0; i < 2; i++) {
1179       renderer->velems[i].src_offset = i * 4 * sizeof(float);
1180       renderer->velems[i].instance_divisor = 0;
1181       renderer->velems[i].vertex_buffer_index = 0;
1182       renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1183    }
1184    cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1185
1186    /* GL rasterization rules */
1187    raster = &renderer->g3d.rasterizer;
1188    memset(raster, 0, sizeof(*raster));
1189    raster->gl_rasterization_rules = 1;
1190    raster->depth_clip = 1;
1191    cso_set_rasterizer(renderer->cso, raster);
1192
1193    /* fixed at 0 */
1194    memset(&sr, 0, sizeof(sr));
1195    cso_set_stencil_ref(renderer->cso, &sr);
1196
1197    renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1198
1199    renderer->state = RENDERER_STATE_INIT;
1200
1201    return renderer;
1202 }
1203
1204 void renderer_destroy(struct renderer *ctx)
1205 {
1206    int i;
1207
1208    for (i = 0; i < NUM_RENDERER_VS; i++) {
1209       if (ctx->cached_vs[i])
1210          cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1211    }
1212    for (i = 0; i < NUM_RENDERER_FS; i++) {
1213       if (ctx->cached_fs[i])
1214          cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1215    }
1216
1217    pipe_resource_reference(&ctx->vs_cbuf, NULL);
1218    pipe_resource_reference(&ctx->fs_cbuf, NULL);
1219
1220    FREE(ctx);
1221 }
1222
1223 static void update_clip_state(struct renderer *renderer,
1224                               const struct vg_state *state)
1225 {
1226    struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1227
1228    memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1229
1230    if (state->scissoring) {
1231       struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1232       int i;
1233
1234       renderer_scissor_begin(renderer, VG_FALSE);
1235
1236       for (i = 0; i < state->scissor_rects_num; ++i) {
1237          const float x      = state->scissor_rects[i * 4 + 0].f;
1238          const float y      = state->scissor_rects[i * 4 + 1].f;
1239          const float width  = state->scissor_rects[i * 4 + 2].f;
1240          const float height = state->scissor_rects[i * 4 + 3].f;
1241          VGint x0, y0, x1, y1, iw, ih;
1242
1243          x0 = (VGint) x;
1244          y0 = (VGint) y;
1245          if (x0 < 0)
1246             x0 = 0;
1247          if (y0 < 0)
1248             y0 = 0;
1249
1250          /* note that x1 and y1 are exclusive */
1251          x1 = (VGint) ceilf(x + width);
1252          y1 = (VGint) ceilf(y + height);
1253          if (x1 > fb->width)
1254             x1 = fb->width;
1255          if (y1 > fb->height)
1256             y1 = fb->height;
1257
1258          iw = x1 - x0;
1259          ih = y1 - y0;
1260          if (iw > 0 && ih> 0 )
1261             renderer_scissor(renderer, x0, y0, iw, ih);
1262       }
1263
1264       renderer_scissor_end(renderer);
1265
1266       dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1267       dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1268       dsa->depth.func = PIPE_FUNC_GEQUAL;
1269    }
1270 }
1271
1272 static void renderer_validate_blend(struct renderer *renderer,
1273                                      const struct vg_state *state,
1274                                      enum pipe_format fb_format)
1275 {
1276    struct pipe_blend_state blend;
1277
1278    memset(&blend, 0, sizeof(blend));
1279    blend.rt[0].colormask = PIPE_MASK_RGBA;
1280    blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1281    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1282    blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1283    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1284
1285    /* TODO alpha masking happens after blending? */
1286
1287    switch (state->blend_mode) {
1288    case VG_BLEND_SRC:
1289       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1290       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1291       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1292       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1293       break;
1294    case VG_BLEND_SRC_OVER:
1295       /* use the blend state only when there is no alpha channel */
1296       if (!util_format_has_alpha(fb_format)) {
1297          blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1298          blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1299          blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1300          blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1301          blend.rt[0].blend_enable = 1;
1302       }
1303       break;
1304    case VG_BLEND_SRC_IN:
1305       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1306       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1307       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1308       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1309       blend.rt[0].blend_enable = 1;
1310       break;
1311    case VG_BLEND_DST_IN:
1312       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
1313       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1314       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
1315       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1316       blend.rt[0].blend_enable = 1;
1317       break;
1318    case VG_BLEND_DST_OVER:
1319    case VG_BLEND_MULTIPLY:
1320    case VG_BLEND_SCREEN:
1321    case VG_BLEND_DARKEN:
1322    case VG_BLEND_LIGHTEN:
1323    case VG_BLEND_ADDITIVE:
1324       /* need a shader */
1325       break;
1326    default:
1327       assert(!"not implemented blend mode");
1328       break;
1329    }
1330
1331    cso_set_blend(renderer->cso, &blend);
1332 }
1333
1334 /**
1335  * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
1336  * and scissoring states are relevant here.
1337  */
1338 void renderer_validate(struct renderer *renderer,
1339                        VGbitfield dirty,
1340                        const struct st_framebuffer *stfb,
1341                        const struct vg_state *state)
1342 {
1343    assert(renderer->state == RENDERER_STATE_INIT);
1344
1345    dirty |= renderer->dirty;
1346    renderer->dirty = 0;
1347
1348    if (dirty & FRAMEBUFFER_DIRTY) {
1349       struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1350       struct matrix *proj = &renderer->projection;
1351
1352       memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1353       fb->width  = stfb->width;
1354       fb->height = stfb->height;
1355       fb->nr_cbufs = 1;
1356       fb->cbufs[0] = stfb->strb->surface;
1357       fb->zsbuf = stfb->dsrb->surface;
1358
1359       cso_set_framebuffer(renderer->cso, fb);
1360       vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1361
1362       matrix_load_identity(proj);
1363       matrix_translate(proj, -1.0f, -1.0f);
1364       matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1365
1366       /* we also got a new depth buffer */
1367       if (dirty & DEPTH_STENCIL_DIRTY) {
1368          renderer->pipe->clear(renderer->pipe,
1369                PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1370       }
1371    }
1372
1373    /* must be last because it renders to the depth buffer*/
1374    if (dirty & DEPTH_STENCIL_DIRTY) {
1375       update_clip_state(renderer, state);
1376       cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1377    }
1378
1379    if (dirty & BLEND_DIRTY)
1380       renderer_validate_blend(renderer, state, stfb->strb->format);
1381 }
1382
1383 /**
1384  * Prepare the renderer for OpenVG pipeline.
1385  */
1386 void renderer_validate_for_shader(struct renderer *renderer,
1387                                   const struct pipe_sampler_state **samplers,
1388                                   struct pipe_sampler_view **views,
1389                                   VGint num_samplers,
1390                                   const struct matrix *modelview,
1391                                   void *fs,
1392                                   const void *const_buffer,
1393                                   VGint const_buffer_len)
1394 {
1395    struct matrix mvp = renderer->projection;
1396
1397    /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1398    matrix_mult(&mvp, modelview);
1399    renderer_set_mvp(renderer, &mvp);
1400
1401    renderer_set_custom_fs(renderer, fs,
1402                           samplers, views, num_samplers,
1403                           const_buffer, const_buffer_len);
1404 }
1405
1406 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1407                                           struct pipe_surface *dst,
1408                                           const struct matrix *modelview)
1409 {
1410    struct matrix mvp = renderer->projection;
1411
1412    /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1413    matrix_mult(&mvp, modelview);
1414    renderer_set_mvp(renderer, &mvp);
1415
1416    renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1417    renderer_set_blend(renderer, ~0);
1418    renderer_set_fs(renderer, RENDERER_FS_WHITE);
1419
1420    /* set internal dirty flags (hacky!) */
1421    renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1422 }
1423
1424 void renderer_copy_surface(struct renderer *ctx,
1425                            struct pipe_surface *src,
1426                            int srcX0, int srcY0,
1427                            int srcX1, int srcY1,
1428                            struct pipe_surface *dst,
1429                            int dstX0, int dstY0,
1430                            int dstX1, int dstY1,
1431                            float z, unsigned filter)
1432 {
1433    struct pipe_context *pipe = ctx->pipe;
1434    struct pipe_screen *screen = pipe->screen;
1435    struct pipe_sampler_view view_templ;
1436    struct pipe_sampler_view *view;
1437    struct pipe_box src_box;
1438    struct pipe_resource texTemp, *tex;
1439    const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1440    const int srcW = abs(srcX1 - srcX0);
1441    const int srcH = abs(srcY1 - srcY0);
1442    const int srcLeft = MIN2(srcX0, srcX1);
1443    const int srcTop = MIN2(srcY0, srcY1);
1444
1445    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1446           filter == PIPE_TEX_MIPFILTER_LINEAR);
1447
1448    if (srcLeft != srcX0) {
1449       /* left-right flip */
1450       int tmp = dstX0;
1451       dstX0 = dstX1;
1452       dstX1 = tmp;
1453    }
1454
1455    if (srcTop != srcY0) {
1456       /* up-down flip */
1457       int tmp = dstY0;
1458       dstY0 = dstY1;
1459       dstY1 = tmp;
1460    }
1461
1462    assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1463                                       0, PIPE_BIND_SAMPLER_VIEW));
1464    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1465                                       0, PIPE_BIND_SAMPLER_VIEW));
1466    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1467                                       0, PIPE_BIND_RENDER_TARGET));
1468
1469    /*
1470     * XXX for now we're always creating a temporary texture.
1471     * Strictly speaking that's not always needed.
1472     */
1473
1474    /* create temp texture */
1475    memset(&texTemp, 0, sizeof(texTemp));
1476    texTemp.target = PIPE_TEXTURE_2D;
1477    texTemp.format = src->format;
1478    texTemp.last_level = 0;
1479    texTemp.width0 = srcW;
1480    texTemp.height0 = srcH;
1481    texTemp.depth0 = 1;
1482    texTemp.array_size = 1;
1483    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1484
1485    tex = screen->resource_create(screen, &texTemp);
1486    if (!tex)
1487       return;
1488
1489    u_sampler_view_default_template(&view_templ, tex, tex->format);
1490    view = pipe->create_sampler_view(pipe, tex, &view_templ);
1491
1492    if (!view)
1493       return;
1494
1495    u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1496
1497    pipe->resource_copy_region(pipe,
1498                               tex, 0, 0, 0, 0,  /* dest */
1499                               src->texture, 0, &src_box);
1500
1501    assert(floatsEqual(z, 0.0f));
1502
1503    /* draw */
1504    if (fb->cbufs[0] == dst) {
1505       /* transform back to surface coordinates */
1506       dstY0 = dst->height - dstY0;
1507       dstY1 = dst->height - dstY1;
1508
1509       if (renderer_drawtex_begin(ctx, view)) {
1510          renderer_drawtex(ctx,
1511                dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1512                0, 0, view->texture->width0, view->texture->height0);
1513          renderer_drawtex_end(ctx);
1514       }
1515    }
1516    else {
1517       if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1518          renderer_copy(ctx,
1519                dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1520                0, 0, view->texture->width0, view->texture->height0);
1521          renderer_copy_end(ctx);
1522       }
1523    }
1524 }
1525
1526 void renderer_texture_quad(struct renderer *r,
1527                            struct pipe_resource *tex,
1528                            VGfloat x1offset, VGfloat y1offset,
1529                            VGfloat x2offset, VGfloat y2offset,
1530                            VGfloat x1, VGfloat y1,
1531                            VGfloat x2, VGfloat y2,
1532                            VGfloat x3, VGfloat y3,
1533                            VGfloat x4, VGfloat y4)
1534 {
1535    const VGfloat z = 0.0f;
1536
1537    assert(r->state == RENDERER_STATE_INIT);
1538    assert(tex->width0 != 0);
1539    assert(tex->height0 != 0);
1540
1541    cso_save_vertex_shader(r->cso);
1542
1543    renderer_set_vs(r, RENDERER_VS_TEXTURE);
1544
1545    /* manually set up positions */
1546    r->vertices[0][0][0] = x1;
1547    r->vertices[0][0][1] = y1;
1548    r->vertices[0][0][2] = z;
1549
1550    r->vertices[1][0][0] = x2;
1551    r->vertices[1][0][1] = y2;
1552    r->vertices[1][0][2] = z;
1553
1554    r->vertices[2][0][0] = x3;
1555    r->vertices[2][0][1] = y3;
1556    r->vertices[2][0][2] = z;
1557
1558    r->vertices[3][0][0] = x4;
1559    r->vertices[3][0][1] = y4;
1560    r->vertices[3][0][2] = z;
1561
1562    /* texcoords */
1563    renderer_quad_texcoord(r, x1offset, y1offset,
1564          x2offset, y2offset, tex->width0, tex->height0);
1565
1566    renderer_quad_draw(r);
1567
1568    cso_restore_vertex_shader(r->cso);
1569 }