Home | History | Annotate | Download | only in vega
      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    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, 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  */
    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  */
    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    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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 
   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 
   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  */
   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  */
   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 
   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 
   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 
   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