• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
renderer_can_support(struct renderer * renderer,struct pipe_resource * res,unsigned bindings)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  */
renderer_set_mvp(struct renderer * renderer,const struct matrix * mvp)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    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  */
create_passthrough_vs(struct pipe_context * pipe,int semantic_name)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  */
renderer_set_vs(struct renderer * r,RendererVs id)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  */
create_scissor_fs(struct pipe_context * pipe)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  */
create_white_fs(struct pipe_context * pipe)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  */
renderer_set_fs(struct renderer * r,RendererFs id)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 
vg_set_viewport(struct renderer * r,VegaOrientation orientation)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  */
renderer_set_target(struct renderer * r,struct pipe_surface * cbuf,struct pipe_surface * zsbuf,VGboolean y0_top)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  */
renderer_set_blend(struct renderer * r,VGbitfield channel_mask)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  */
renderer_set_samplers(struct renderer * r,uint num_views,struct pipe_sampler_view ** views)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, PIPE_SHADER_FRAGMENT, i, &sampler);
439    cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
440 
441    /* set views */
442    cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 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  */
renderer_set_custom_fs(struct renderer * renderer,void * fs,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,const void * const_buffer,VGint const_buffer_len)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, PIPE_SHADER_FRAGMENT, num_samplers, samplers);
465       cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, 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          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  */
renderer_quad_pos(struct renderer * r,VGfloat x0,VGfloat y0,VGfloat x1,VGfloat y1,VGboolean scissor)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  */
renderer_quad_texcoord(struct renderer * r,VGfloat x0,VGfloat y0,VGfloat x1,VGfloat y1,VGint tex_width,VGint tex_height)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  */
renderer_quad_draw(struct renderer * r)567 static void renderer_quad_draw(struct renderer *r)
568 {
569    util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN,
570                                 Elements(r->vertices),     /* verts */
571                                 Elements(r->vertices[0])); /* attribs/vert */
572 }
573 
574 /**
575  * Prepare the renderer for copying.
576  */
renderer_copy_begin(struct renderer * renderer,struct pipe_surface * dst,VGboolean y0_top,struct pipe_sampler_view * src)577 VGboolean renderer_copy_begin(struct renderer *renderer,
578                               struct pipe_surface *dst,
579                               VGboolean y0_top,
580                               struct pipe_sampler_view *src)
581 {
582    assert(renderer->state == RENDERER_STATE_INIT);
583 
584    /* sanity check */
585    if (!renderer_can_support(renderer,
586             dst->texture, PIPE_BIND_RENDER_TARGET) ||
587        !renderer_can_support(renderer,
588           src->texture, PIPE_BIND_SAMPLER_VIEW))
589       return VG_FALSE;
590 
591    cso_save_framebuffer(renderer->cso);
592    cso_save_viewport(renderer->cso);
593    cso_save_blend(renderer->cso);
594    cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
595    cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
596    cso_save_fragment_shader(renderer->cso);
597    cso_save_vertex_shader(renderer->cso);
598 
599    renderer_set_target(renderer, dst, NULL, y0_top);
600 
601    renderer_set_blend(renderer, ~0);
602    renderer_set_samplers(renderer, 1, &src);
603 
604    renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
605    renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
606 
607    renderer_set_mvp(renderer, NULL);
608 
609    /* remember the texture size */
610    renderer->u.copy.tex_width = src->texture->width0;
611    renderer->u.copy.tex_height = src->texture->height0;
612    renderer->state = RENDERER_STATE_COPY;
613 
614    return VG_TRUE;
615 }
616 
617 /**
618  * Draw into the destination rectangle given by (x, y, w, h).  The texture is
619  * sampled from within the rectangle given by (sx, sy, sw, sh).
620  *
621  * The coordinates are in surface coordinates.
622  */
renderer_copy(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)623 void renderer_copy(struct renderer *renderer,
624                    VGint x, VGint y, VGint w, VGint h,
625                    VGint sx, VGint sy, VGint sw, VGint sh)
626 {
627    assert(renderer->state == RENDERER_STATE_COPY);
628 
629    /* there is no depth buffer for scissoring anyway */
630    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
631    renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
632          renderer->u.copy.tex_width,
633          renderer->u.copy.tex_height);
634 
635    renderer_quad_draw(renderer);
636 }
637 
638 /**
639  * End copying and restore the states.
640  */
renderer_copy_end(struct renderer * renderer)641 void renderer_copy_end(struct renderer *renderer)
642 {
643    assert(renderer->state == RENDERER_STATE_COPY);
644 
645    cso_restore_framebuffer(renderer->cso);
646    cso_restore_viewport(renderer->cso);
647    cso_restore_blend(renderer->cso);
648    cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
649    cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
650    cso_restore_fragment_shader(renderer->cso);
651    cso_restore_vertex_shader(renderer->cso);
652 
653    renderer->state = RENDERER_STATE_INIT;
654 }
655 
656 /**
657  * Prepare the renderer for textured drawing.
658  */
renderer_drawtex_begin(struct renderer * renderer,struct pipe_sampler_view * src)659 VGboolean renderer_drawtex_begin(struct renderer *renderer,
660                                  struct pipe_sampler_view *src)
661 {
662    assert(renderer->state == RENDERER_STATE_INIT);
663 
664    if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
665       return VG_FALSE;
666 
667    cso_save_blend(renderer->cso);
668    cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
669    cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
670    cso_save_fragment_shader(renderer->cso);
671    cso_save_vertex_shader(renderer->cso);
672 
673    renderer_set_blend(renderer, ~0);
674 
675    renderer_set_samplers(renderer, 1, &src);
676 
677    renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
678    renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
679 
680    renderer_set_mvp(renderer, NULL);
681 
682    /* remember the texture size */
683    renderer->u.drawtex.tex_width = src->texture->width0;
684    renderer->u.drawtex.tex_height = src->texture->height0;
685    renderer->state = RENDERER_STATE_DRAWTEX;
686 
687    return VG_TRUE;
688 }
689 
690 /**
691  * Draw into the destination rectangle given by (x, y, w, h).  The texture is
692  * sampled from within the rectangle given by (sx, sy, sw, sh).
693  *
694  * The coordinates are in surface coordinates.
695  */
renderer_drawtex(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)696 void renderer_drawtex(struct renderer *renderer,
697                       VGint x, VGint y, VGint w, VGint h,
698                       VGint sx, VGint sy, VGint sw, VGint sh)
699 {
700    assert(renderer->state == RENDERER_STATE_DRAWTEX);
701 
702    /* with scissoring */
703    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
704    renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
705          renderer->u.drawtex.tex_width,
706          renderer->u.drawtex.tex_height);
707 
708    renderer_quad_draw(renderer);
709 }
710 
711 /**
712  * End textured drawing and restore the states.
713  */
renderer_drawtex_end(struct renderer * renderer)714 void renderer_drawtex_end(struct renderer *renderer)
715 {
716    assert(renderer->state == RENDERER_STATE_DRAWTEX);
717 
718    cso_restore_blend(renderer->cso);
719    cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
720    cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
721    cso_restore_fragment_shader(renderer->cso);
722    cso_restore_vertex_shader(renderer->cso);
723 
724    renderer->state = RENDERER_STATE_INIT;
725 }
726 
727 /**
728  * Prepare the renderer for scissor update.  This will reset the depth buffer
729  * to 1.0f.
730  */
renderer_scissor_begin(struct renderer * renderer,VGboolean restore_dsa)731 VGboolean renderer_scissor_begin(struct renderer *renderer,
732                                  VGboolean restore_dsa)
733 {
734    struct pipe_depth_stencil_alpha_state dsa;
735 
736    assert(renderer->state == RENDERER_STATE_INIT);
737 
738    if (restore_dsa)
739       cso_save_depth_stencil_alpha(renderer->cso);
740    cso_save_blend(renderer->cso);
741    cso_save_fragment_shader(renderer->cso);
742 
743    /* enable depth writes */
744    memset(&dsa, 0, sizeof(dsa));
745    dsa.depth.enabled = 1;
746    dsa.depth.writemask = 1;
747    dsa.depth.func = PIPE_FUNC_ALWAYS;
748    cso_set_depth_stencil_alpha(renderer->cso, &dsa);
749 
750    /* disable color writes */
751    renderer_set_blend(renderer, 0);
752    renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
753 
754    renderer_set_mvp(renderer, NULL);
755 
756    renderer->u.scissor.restore_dsa = restore_dsa;
757    renderer->state = RENDERER_STATE_SCISSOR;
758 
759    /* clear the depth buffer to 1.0f */
760    renderer->pipe->clear(renderer->pipe,
761          PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
762 
763    return VG_TRUE;
764 }
765 
766 /**
767  * Add a scissor rectangle.  Depth values inside the rectangle will be set to
768  * 0.0f.
769  */
renderer_scissor(struct renderer * renderer,VGint x,VGint y,VGint width,VGint height)770 void renderer_scissor(struct renderer *renderer,
771                       VGint x, VGint y, VGint width, VGint height)
772 {
773    assert(renderer->state == RENDERER_STATE_SCISSOR);
774 
775    renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
776    renderer_quad_draw(renderer);
777 }
778 
779 /**
780  * End scissor update and restore the states.
781  */
renderer_scissor_end(struct renderer * renderer)782 void renderer_scissor_end(struct renderer *renderer)
783 {
784    assert(renderer->state == RENDERER_STATE_SCISSOR);
785 
786    if (renderer->u.scissor.restore_dsa)
787       cso_restore_depth_stencil_alpha(renderer->cso);
788    cso_restore_blend(renderer->cso);
789    cso_restore_fragment_shader(renderer->cso);
790 
791    renderer->state = RENDERER_STATE_INIT;
792 }
793 
794 /**
795  * Prepare the renderer for clearing.
796  */
renderer_clear_begin(struct renderer * renderer)797 VGboolean renderer_clear_begin(struct renderer *renderer)
798 {
799    assert(renderer->state == RENDERER_STATE_INIT);
800 
801    cso_save_blend(renderer->cso);
802    cso_save_fragment_shader(renderer->cso);
803    cso_save_vertex_shader(renderer->cso);
804 
805    renderer_set_blend(renderer, ~0);
806    renderer_set_fs(renderer, RENDERER_FS_COLOR);
807    renderer_set_vs(renderer, RENDERER_VS_COLOR);
808 
809    renderer_set_mvp(renderer, NULL);
810 
811    renderer->state = RENDERER_STATE_CLEAR;
812 
813    return VG_TRUE;
814 }
815 
816 /**
817  * Clear the framebuffer with the specified region and color.
818  *
819  * The coordinates are in surface coordinates.
820  */
renderer_clear(struct renderer * renderer,VGint x,VGint y,VGint width,VGint height,const VGfloat color[4])821 void renderer_clear(struct renderer *renderer,
822                     VGint x, VGint y, VGint width, VGint height,
823                     const VGfloat color[4])
824 {
825    VGuint i;
826 
827    assert(renderer->state == RENDERER_STATE_CLEAR);
828 
829    renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
830    for (i = 0; i < 4; i++)
831       memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
832 
833    renderer_quad_draw(renderer);
834 }
835 
836 /**
837  * End clearing and retore the states.
838  */
renderer_clear_end(struct renderer * renderer)839 void renderer_clear_end(struct renderer *renderer)
840 {
841    assert(renderer->state == RENDERER_STATE_CLEAR);
842 
843    cso_restore_blend(renderer->cso);
844    cso_restore_fragment_shader(renderer->cso);
845    cso_restore_vertex_shader(renderer->cso);
846 
847    renderer->state = RENDERER_STATE_INIT;
848 }
849 
850 /**
851  * Prepare the renderer for image filtering.
852  */
renderer_filter_begin(struct renderer * renderer,struct pipe_resource * dst,VGboolean y0_top,VGbitfield channel_mask,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,void * fs,const void * const_buffer,VGint const_buffer_len)853 VGboolean renderer_filter_begin(struct renderer *renderer,
854                                 struct pipe_resource *dst,
855                                 VGboolean y0_top,
856                                 VGbitfield channel_mask,
857                                 const struct pipe_sampler_state **samplers,
858                                 struct pipe_sampler_view **views,
859                                 VGint num_samplers,
860                                 void *fs,
861                                 const void *const_buffer,
862                                 VGint const_buffer_len)
863 {
864    struct pipe_surface *surf, surf_tmpl;
865 
866    assert(renderer->state == RENDERER_STATE_INIT);
867 
868    if (!fs)
869       return VG_FALSE;
870    if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
871       return VG_FALSE;
872 
873    u_surface_default_template(&surf_tmpl, dst,
874                               PIPE_BIND_RENDER_TARGET);
875    surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
876    if (!surf)
877       return VG_FALSE;
878 
879    cso_save_framebuffer(renderer->cso);
880    cso_save_viewport(renderer->cso);
881    cso_save_blend(renderer->cso);
882 
883    /* set the image as the target */
884    renderer_set_target(renderer, surf, NULL, y0_top);
885    pipe_surface_reference(&surf, NULL);
886 
887    renderer_set_blend(renderer, channel_mask);
888 
889    if (num_samplers) {
890       struct pipe_resource *tex;
891 
892       cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
893       cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
894       cso_save_fragment_shader(renderer->cso);
895       cso_save_vertex_shader(renderer->cso);
896 
897       renderer_set_custom_fs(renderer, fs,
898                              samplers, views, num_samplers,
899                              const_buffer, const_buffer_len);
900       renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
901 
902       tex = views[0]->texture;
903       renderer->u.filter.tex_width = tex->width0;
904       renderer->u.filter.tex_height = tex->height0;
905       renderer->u.filter.use_sampler = VG_TRUE;
906    }
907    else {
908       cso_save_fragment_shader(renderer->cso);
909 
910       renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
911                              const_buffer, const_buffer_len);
912 
913       renderer->u.filter.use_sampler = VG_FALSE;
914    }
915 
916    renderer_set_mvp(renderer, NULL);
917 
918    renderer->state = RENDERER_STATE_FILTER;
919 
920    return VG_TRUE;
921 }
922 
923 /**
924  * Draw into a rectangle of the destination with the specified region of the
925  * texture(s).
926  *
927  * The coordinates are in surface coordinates.
928  */
renderer_filter(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)929 void renderer_filter(struct renderer *renderer,
930                     VGint x, VGint y, VGint w, VGint h,
931                     VGint sx, VGint sy, VGint sw, VGint sh)
932 {
933    assert(renderer->state == RENDERER_STATE_FILTER);
934 
935    renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
936    if (renderer->u.filter.use_sampler) {
937       renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
938             renderer->u.filter.tex_width,
939             renderer->u.filter.tex_height);
940    }
941 
942    renderer_quad_draw(renderer);
943 }
944 
945 /**
946  * End image filtering and restore the states.
947  */
renderer_filter_end(struct renderer * renderer)948 void renderer_filter_end(struct renderer *renderer)
949 {
950    assert(renderer->state == RENDERER_STATE_FILTER);
951 
952    if (renderer->u.filter.use_sampler) {
953       cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
954       cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
955       cso_restore_vertex_shader(renderer->cso);
956    }
957 
958    cso_restore_framebuffer(renderer->cso);
959    cso_restore_viewport(renderer->cso);
960    cso_restore_blend(renderer->cso);
961    cso_restore_fragment_shader(renderer->cso);
962 
963    renderer->state = RENDERER_STATE_INIT;
964 }
965 
966 /**
967  * Prepare the renderer for polygon silhouette rendering.
968  */
renderer_polygon_stencil_begin(struct renderer * renderer,struct pipe_vertex_element * velem,VGFillRule rule,VGboolean restore_dsa)969 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
970                                          struct pipe_vertex_element *velem,
971                                          VGFillRule rule,
972                                          VGboolean restore_dsa)
973 {
974    struct pipe_depth_stencil_alpha_state *dsa;
975    VGboolean manual_two_sides;
976 
977    assert(renderer->state == RENDERER_STATE_INIT);
978 
979    cso_save_vertex_elements(renderer->cso);
980    cso_save_blend(renderer->cso);
981    cso_save_depth_stencil_alpha(renderer->cso);
982 
983    cso_set_vertex_elements(renderer->cso, 1, velem);
984 
985    /* disable color writes */
986    renderer_set_blend(renderer, 0);
987 
988    manual_two_sides = VG_FALSE;
989    dsa = &renderer->u.polygon_stencil.dsa;
990    memset(dsa, 0, sizeof(*dsa));
991    if (rule == VG_EVEN_ODD) {
992       dsa->stencil[0].enabled = 1;
993       dsa->stencil[0].writemask = 1;
994       dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
995       dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
996       dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
997       dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
998       dsa->stencil[0].valuemask = ~0;
999    }
1000    else {
1001       assert(rule == VG_NON_ZERO);
1002 
1003       /* front face */
1004       dsa->stencil[0].enabled = 1;
1005       dsa->stencil[0].writemask = ~0;
1006       dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1007       dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1008       dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1009       dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1010       dsa->stencil[0].valuemask = ~0;
1011 
1012       if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1013                                             PIPE_CAP_TWO_SIDED_STENCIL)) {
1014          /* back face */
1015          dsa->stencil[1] = dsa->stencil[0];
1016          dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1017       }
1018       else {
1019          manual_two_sides = VG_TRUE;
1020       }
1021    }
1022    cso_set_depth_stencil_alpha(renderer->cso, dsa);
1023 
1024    if (manual_two_sides)
1025       cso_save_rasterizer(renderer->cso);
1026 
1027    renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1028    renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1029    renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1030 
1031    return VG_TRUE;
1032 }
1033 
1034 /**
1035  * Render a polygon silhouette to stencil buffer.
1036  */
renderer_polygon_stencil(struct renderer * renderer,struct pipe_vertex_buffer * vbuf,VGuint mode,VGuint start,VGuint count)1037 void renderer_polygon_stencil(struct renderer *renderer,
1038                               struct pipe_vertex_buffer *vbuf,
1039                               VGuint mode, VGuint start, VGuint count)
1040 {
1041    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1042 
1043    cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1044 
1045    if (!renderer->u.polygon_stencil.manual_two_sides) {
1046       cso_draw_arrays(renderer->cso, mode, start, count);
1047    }
1048    else {
1049       struct pipe_rasterizer_state raster;
1050       struct pipe_depth_stencil_alpha_state dsa;
1051 
1052       raster = renderer->g3d.rasterizer;
1053       dsa = renderer->u.polygon_stencil.dsa;
1054 
1055       /* front */
1056       raster.cull_face = PIPE_FACE_BACK;
1057       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1058 
1059       cso_set_rasterizer(renderer->cso, &raster);
1060       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1061       cso_draw_arrays(renderer->cso, mode, start, count);
1062 
1063       /* back */
1064       raster.cull_face = PIPE_FACE_FRONT;
1065       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1066 
1067       cso_set_rasterizer(renderer->cso, &raster);
1068       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1069       cso_draw_arrays(renderer->cso, mode, start, count);
1070    }
1071 }
1072 
1073 /**
1074  * End polygon silhouette rendering.
1075  */
renderer_polygon_stencil_end(struct renderer * renderer)1076 void renderer_polygon_stencil_end(struct renderer *renderer)
1077 {
1078    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1079 
1080    if (renderer->u.polygon_stencil.manual_two_sides)
1081       cso_restore_rasterizer(renderer->cso);
1082 
1083    cso_restore_vertex_elements(renderer->cso);
1084 
1085    /* restore color writes */
1086    cso_restore_blend(renderer->cso);
1087 
1088    if (renderer->u.polygon_stencil.restore_dsa)
1089       cso_restore_depth_stencil_alpha(renderer->cso);
1090 
1091    renderer->state = RENDERER_STATE_INIT;
1092 }
1093 
1094 /**
1095  * Prepare the renderer for polygon filling.
1096  */
renderer_polygon_fill_begin(struct renderer * renderer,VGboolean save_dsa)1097 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1098                                       VGboolean save_dsa)
1099 {
1100    struct pipe_depth_stencil_alpha_state dsa;
1101 
1102    assert(renderer->state == RENDERER_STATE_INIT);
1103 
1104    if (save_dsa)
1105       cso_save_depth_stencil_alpha(renderer->cso);
1106 
1107    /* setup stencil ops */
1108    memset(&dsa, 0, sizeof(dsa));
1109    dsa.stencil[0].enabled = 1;
1110    dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1111    dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1112    dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1113    dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1114    dsa.stencil[0].valuemask = ~0;
1115    dsa.stencil[0].writemask = ~0;
1116    dsa.depth = renderer->g3d.dsa.depth;
1117    cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1118 
1119    renderer->state = RENDERER_STATE_POLYGON_FILL;
1120 
1121    return VG_TRUE;
1122 }
1123 
1124 /**
1125  * Fill a polygon.
1126  */
renderer_polygon_fill(struct renderer * renderer,VGfloat min_x,VGfloat min_y,VGfloat max_x,VGfloat max_y)1127 void renderer_polygon_fill(struct renderer *renderer,
1128                            VGfloat min_x, VGfloat min_y,
1129                            VGfloat max_x, VGfloat max_y)
1130 {
1131    assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1132 
1133    renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1134    renderer_quad_draw(renderer);
1135 }
1136 
1137 /**
1138  * End polygon filling.
1139  */
renderer_polygon_fill_end(struct renderer * renderer)1140 void renderer_polygon_fill_end(struct renderer *renderer)
1141 {
1142    assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1143 
1144    cso_restore_depth_stencil_alpha(renderer->cso);
1145 
1146    renderer->state = RENDERER_STATE_INIT;
1147 }
1148 
renderer_create(struct vg_context * owner)1149 struct renderer * renderer_create(struct vg_context *owner)
1150 {
1151    struct renderer *renderer;
1152    struct pipe_rasterizer_state *raster;
1153    struct pipe_stencil_ref sr;
1154    VGint i;
1155 
1156    renderer = CALLOC_STRUCT(renderer);
1157    if (!renderer)
1158       return NULL;
1159 
1160    renderer->pipe = owner->pipe;
1161    renderer->cso = owner->cso_context;
1162 
1163    /* init vertex data that doesn't change */
1164    for (i = 0; i < 4; i++)
1165       renderer->vertices[i][0][3] = 1.0f; /* w */
1166 
1167    for (i = 0; i < 2; i++) {
1168       renderer->velems[i].src_offset = i * 4 * sizeof(float);
1169       renderer->velems[i].instance_divisor = 0;
1170       renderer->velems[i].vertex_buffer_index = 0;
1171       renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1172    }
1173    cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1174 
1175    /* GL rasterization rules */
1176    raster = &renderer->g3d.rasterizer;
1177    memset(raster, 0, sizeof(*raster));
1178    raster->gl_rasterization_rules = 1;
1179    raster->depth_clip = 1;
1180    cso_set_rasterizer(renderer->cso, raster);
1181 
1182    /* fixed at 0 */
1183    memset(&sr, 0, sizeof(sr));
1184    cso_set_stencil_ref(renderer->cso, &sr);
1185 
1186    renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1187 
1188    renderer->state = RENDERER_STATE_INIT;
1189 
1190    return renderer;
1191 }
1192 
renderer_destroy(struct renderer * ctx)1193 void renderer_destroy(struct renderer *ctx)
1194 {
1195    int i;
1196 
1197    for (i = 0; i < NUM_RENDERER_VS; i++) {
1198       if (ctx->cached_vs[i])
1199          cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1200    }
1201    for (i = 0; i < NUM_RENDERER_FS; i++) {
1202       if (ctx->cached_fs[i])
1203          cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1204    }
1205 
1206    pipe_resource_reference(&ctx->vs_cbuf, NULL);
1207    pipe_resource_reference(&ctx->fs_cbuf, NULL);
1208 
1209    FREE(ctx);
1210 }
1211 
update_clip_state(struct renderer * renderer,const struct vg_state * state)1212 static void update_clip_state(struct renderer *renderer,
1213                               const struct vg_state *state)
1214 {
1215    struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1216 
1217    memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1218 
1219    if (state->scissoring) {
1220       struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1221       int i;
1222 
1223       renderer_scissor_begin(renderer, VG_FALSE);
1224 
1225       for (i = 0; i < state->scissor_rects_num; ++i) {
1226          const float x      = state->scissor_rects[i * 4 + 0].f;
1227          const float y      = state->scissor_rects[i * 4 + 1].f;
1228          const float width  = state->scissor_rects[i * 4 + 2].f;
1229          const float height = state->scissor_rects[i * 4 + 3].f;
1230          VGint x0, y0, x1, y1, iw, ih;
1231 
1232          x0 = (VGint) x;
1233          y0 = (VGint) y;
1234          if (x0 < 0)
1235             x0 = 0;
1236          if (y0 < 0)
1237             y0 = 0;
1238 
1239          /* note that x1 and y1 are exclusive */
1240          x1 = (VGint) ceilf(x + width);
1241          y1 = (VGint) ceilf(y + height);
1242          if (x1 > fb->width)
1243             x1 = fb->width;
1244          if (y1 > fb->height)
1245             y1 = fb->height;
1246 
1247          iw = x1 - x0;
1248          ih = y1 - y0;
1249          if (iw > 0 && ih> 0 )
1250             renderer_scissor(renderer, x0, y0, iw, ih);
1251       }
1252 
1253       renderer_scissor_end(renderer);
1254 
1255       dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1256       dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1257       dsa->depth.func = PIPE_FUNC_GEQUAL;
1258    }
1259 }
1260 
renderer_validate_blend(struct renderer * renderer,const struct vg_state * state,enum pipe_format fb_format)1261 static void renderer_validate_blend(struct renderer *renderer,
1262                                      const struct vg_state *state,
1263                                      enum pipe_format fb_format)
1264 {
1265    struct pipe_blend_state blend;
1266 
1267    memset(&blend, 0, sizeof(blend));
1268    blend.rt[0].colormask = PIPE_MASK_RGBA;
1269    blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1270    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1271    blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1272    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1273 
1274    /* TODO alpha masking happens after blending? */
1275 
1276    switch (state->blend_mode) {
1277    case VG_BLEND_SRC:
1278       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1279       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1280       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1281       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1282       break;
1283    case VG_BLEND_SRC_OVER:
1284       /* use the blend state only when there is no alpha channel */
1285       if (!util_format_has_alpha(fb_format)) {
1286          blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1287          blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1288          blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1289          blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1290          blend.rt[0].blend_enable = 1;
1291       }
1292       break;
1293    case VG_BLEND_SRC_IN:
1294       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1295       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1296       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1297       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1298       blend.rt[0].blend_enable = 1;
1299       break;
1300    case VG_BLEND_DST_IN:
1301       blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
1302       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1303       blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
1304       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1305       blend.rt[0].blend_enable = 1;
1306       break;
1307    case VG_BLEND_DST_OVER:
1308    case VG_BLEND_MULTIPLY:
1309    case VG_BLEND_SCREEN:
1310    case VG_BLEND_DARKEN:
1311    case VG_BLEND_LIGHTEN:
1312    case VG_BLEND_ADDITIVE:
1313       /* need a shader */
1314       break;
1315    default:
1316       assert(!"not implemented blend mode");
1317       break;
1318    }
1319 
1320    cso_set_blend(renderer->cso, &blend);
1321 }
1322 
1323 /**
1324  * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
1325  * and scissoring states are relevant here.
1326  */
renderer_validate(struct renderer * renderer,VGbitfield dirty,const struct st_framebuffer * stfb,const struct vg_state * state)1327 void renderer_validate(struct renderer *renderer,
1328                        VGbitfield dirty,
1329                        const struct st_framebuffer *stfb,
1330                        const struct vg_state *state)
1331 {
1332    assert(renderer->state == RENDERER_STATE_INIT);
1333 
1334    dirty |= renderer->dirty;
1335    renderer->dirty = 0;
1336 
1337    if (dirty & FRAMEBUFFER_DIRTY) {
1338       struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1339       struct matrix *proj = &renderer->projection;
1340 
1341       memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1342       fb->width  = stfb->width;
1343       fb->height = stfb->height;
1344       fb->nr_cbufs = 1;
1345       fb->cbufs[0] = stfb->strb->surface;
1346       fb->zsbuf = stfb->dsrb->surface;
1347 
1348       cso_set_framebuffer(renderer->cso, fb);
1349       vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1350 
1351       matrix_load_identity(proj);
1352       matrix_translate(proj, -1.0f, -1.0f);
1353       matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1354 
1355       /* we also got a new depth buffer */
1356       if (dirty & DEPTH_STENCIL_DIRTY) {
1357          renderer->pipe->clear(renderer->pipe,
1358                PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1359       }
1360    }
1361 
1362    /* must be last because it renders to the depth buffer*/
1363    if (dirty & DEPTH_STENCIL_DIRTY) {
1364       update_clip_state(renderer, state);
1365       cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1366    }
1367 
1368    if (dirty & BLEND_DIRTY)
1369       renderer_validate_blend(renderer, state, stfb->strb->format);
1370 }
1371 
1372 /**
1373  * Prepare the renderer for OpenVG pipeline.
1374  */
renderer_validate_for_shader(struct renderer * renderer,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,const struct matrix * modelview,void * fs,const void * const_buffer,VGint const_buffer_len)1375 void renderer_validate_for_shader(struct renderer *renderer,
1376                                   const struct pipe_sampler_state **samplers,
1377                                   struct pipe_sampler_view **views,
1378                                   VGint num_samplers,
1379                                   const struct matrix *modelview,
1380                                   void *fs,
1381                                   const void *const_buffer,
1382                                   VGint const_buffer_len)
1383 {
1384    struct matrix mvp = renderer->projection;
1385 
1386    /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1387    matrix_mult(&mvp, modelview);
1388    renderer_set_mvp(renderer, &mvp);
1389 
1390    renderer_set_custom_fs(renderer, fs,
1391                           samplers, views, num_samplers,
1392                           const_buffer, const_buffer_len);
1393 }
1394 
renderer_validate_for_mask_rendering(struct renderer * renderer,struct pipe_surface * dst,const struct matrix * modelview)1395 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1396                                           struct pipe_surface *dst,
1397                                           const struct matrix *modelview)
1398 {
1399    struct matrix mvp = renderer->projection;
1400 
1401    /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1402    matrix_mult(&mvp, modelview);
1403    renderer_set_mvp(renderer, &mvp);
1404 
1405    renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1406    renderer_set_blend(renderer, ~0);
1407    renderer_set_fs(renderer, RENDERER_FS_WHITE);
1408 
1409    /* set internal dirty flags (hacky!) */
1410    renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1411 }
1412 
renderer_copy_surface(struct renderer * ctx,struct pipe_surface * src,int srcX0,int srcY0,int srcX1,int srcY1,struct pipe_surface * dst,int dstX0,int dstY0,int dstX1,int dstY1,float z,unsigned filter)1413 void renderer_copy_surface(struct renderer *ctx,
1414                            struct pipe_surface *src,
1415                            int srcX0, int srcY0,
1416                            int srcX1, int srcY1,
1417                            struct pipe_surface *dst,
1418                            int dstX0, int dstY0,
1419                            int dstX1, int dstY1,
1420                            float z, unsigned filter)
1421 {
1422    struct pipe_context *pipe = ctx->pipe;
1423    struct pipe_screen *screen = pipe->screen;
1424    struct pipe_sampler_view view_templ;
1425    struct pipe_sampler_view *view;
1426    struct pipe_box src_box;
1427    struct pipe_resource texTemp, *tex;
1428    const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1429    const int srcW = abs(srcX1 - srcX0);
1430    const int srcH = abs(srcY1 - srcY0);
1431    const int srcLeft = MIN2(srcX0, srcX1);
1432    const int srcTop = MIN2(srcY0, srcY1);
1433 
1434    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1435           filter == PIPE_TEX_MIPFILTER_LINEAR);
1436 
1437    if (srcLeft != srcX0) {
1438       /* left-right flip */
1439       int tmp = dstX0;
1440       dstX0 = dstX1;
1441       dstX1 = tmp;
1442    }
1443 
1444    if (srcTop != srcY0) {
1445       /* up-down flip */
1446       int tmp = dstY0;
1447       dstY0 = dstY1;
1448       dstY1 = tmp;
1449    }
1450 
1451    assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1452                                       0, PIPE_BIND_SAMPLER_VIEW));
1453    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1454                                       0, PIPE_BIND_SAMPLER_VIEW));
1455    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1456                                       0, PIPE_BIND_RENDER_TARGET));
1457 
1458    /*
1459     * XXX for now we're always creating a temporary texture.
1460     * Strictly speaking that's not always needed.
1461     */
1462 
1463    /* create temp texture */
1464    memset(&texTemp, 0, sizeof(texTemp));
1465    texTemp.target = PIPE_TEXTURE_2D;
1466    texTemp.format = src->format;
1467    texTemp.last_level = 0;
1468    texTemp.width0 = srcW;
1469    texTemp.height0 = srcH;
1470    texTemp.depth0 = 1;
1471    texTemp.array_size = 1;
1472    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1473 
1474    tex = screen->resource_create(screen, &texTemp);
1475    if (!tex)
1476       return;
1477 
1478    u_sampler_view_default_template(&view_templ, tex, tex->format);
1479    view = pipe->create_sampler_view(pipe, tex, &view_templ);
1480 
1481    if (!view)
1482       return;
1483 
1484    u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1485 
1486    pipe->resource_copy_region(pipe,
1487                               tex, 0, 0, 0, 0,  /* dest */
1488                               src->texture, 0, &src_box);
1489 
1490    assert(floatsEqual(z, 0.0f));
1491 
1492    /* draw */
1493    if (fb->cbufs[0] == dst) {
1494       /* transform back to surface coordinates */
1495       dstY0 = dst->height - dstY0;
1496       dstY1 = dst->height - dstY1;
1497 
1498       if (renderer_drawtex_begin(ctx, view)) {
1499          renderer_drawtex(ctx,
1500                dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1501                0, 0, view->texture->width0, view->texture->height0);
1502          renderer_drawtex_end(ctx);
1503       }
1504    }
1505    else {
1506       if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1507          renderer_copy(ctx,
1508                dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1509                0, 0, view->texture->width0, view->texture->height0);
1510          renderer_copy_end(ctx);
1511       }
1512    }
1513 }
1514 
renderer_texture_quad(struct renderer * r,struct pipe_resource * tex,VGfloat x1offset,VGfloat y1offset,VGfloat x2offset,VGfloat y2offset,VGfloat x1,VGfloat y1,VGfloat x2,VGfloat y2,VGfloat x3,VGfloat y3,VGfloat x4,VGfloat y4)1515 void renderer_texture_quad(struct renderer *r,
1516                            struct pipe_resource *tex,
1517                            VGfloat x1offset, VGfloat y1offset,
1518                            VGfloat x2offset, VGfloat y2offset,
1519                            VGfloat x1, VGfloat y1,
1520                            VGfloat x2, VGfloat y2,
1521                            VGfloat x3, VGfloat y3,
1522                            VGfloat x4, VGfloat y4)
1523 {
1524    const VGfloat z = 0.0f;
1525 
1526    assert(r->state == RENDERER_STATE_INIT);
1527    assert(tex->width0 != 0);
1528    assert(tex->height0 != 0);
1529 
1530    cso_save_vertex_shader(r->cso);
1531 
1532    renderer_set_vs(r, RENDERER_VS_TEXTURE);
1533 
1534    /* manually set up positions */
1535    r->vertices[0][0][0] = x1;
1536    r->vertices[0][0][1] = y1;
1537    r->vertices[0][0][2] = z;
1538 
1539    r->vertices[1][0][0] = x2;
1540    r->vertices[1][0][1] = y2;
1541    r->vertices[1][0][2] = z;
1542 
1543    r->vertices[2][0][0] = x3;
1544    r->vertices[2][0][1] = y3;
1545    r->vertices[2][0][2] = z;
1546 
1547    r->vertices[3][0][0] = x4;
1548    r->vertices[3][0][1] = y4;
1549    r->vertices[3][0][2] = z;
1550 
1551    /* texcoords */
1552    renderer_quad_texcoord(r, x1offset, y1offset,
1553          x2offset, y2offset, tex->width0, tex->height0);
1554 
1555    renderer_quad_draw(r);
1556 
1557    cso_restore_vertex_shader(r->cso);
1558 }
1559