Home | History | Annotate | Download | only in vega
      1 /**************************************************************************
      2  *
      3  * Copyright 2009 VMware, Inc.  All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     20  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  **************************************************************************/
     26 
     27 #include "polygon.h"
     28 
     29 #include "matrix.h" /*for floatsEqual*/
     30 #include "vg_context.h"
     31 #include "vg_state.h"
     32 #include "renderer.h"
     33 #include "util_array.h"
     34 #include "VG/openvg.h"
     35 
     36 #include "pipe/p_context.h"
     37 #include "pipe/p_defines.h"
     38 #include "pipe/p_state.h"
     39 #include "util/u_inlines.h"
     40 #include "pipe/p_screen.h"
     41 
     42 #include "util/u_draw_quad.h"
     43 #include "util/u_math.h"
     44 
     45 #include <string.h>
     46 #include <stdlib.h>
     47 
     48 #define DEBUG_POLYGON 0
     49 
     50 #define COMPONENTS 2
     51 
     52 struct polygon
     53 {
     54    VGfloat *data;
     55    VGint    size;
     56 
     57    VGint    num_verts;
     58 
     59    VGboolean dirty;
     60    void *user_vbuf;
     61    struct pipe_screen *screen;
     62 };
     63 
     64 static float *ptr_to_vertex(float *data, int idx)
     65 {
     66    return data + (idx * COMPONENTS);
     67 }
     68 
     69 #if 0
     70 static void polygon_print(struct polygon *poly)
     71 {
     72    int i;
     73    float *vert;
     74    debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts);
     75    for (i = 0; i < poly->num_verts; ++i) {
     76       vert = ptr_to_vertex(poly->data, i);
     77       debug_printf("%f, %f,  ", vert[0], vert[1]);
     78    }
     79    debug_printf("\nend\n");
     80 }
     81 #endif
     82 
     83 
     84 struct polygon * polygon_create(int size)
     85 {
     86    struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon));
     87 
     88    poly->data = malloc(sizeof(float) * COMPONENTS * size);
     89    poly->size = size;
     90    poly->num_verts = 0;
     91    poly->dirty = VG_TRUE;
     92    poly->user_vbuf = NULL;
     93 
     94    return poly;
     95 }
     96 
     97 struct polygon * polygon_create_from_data(float *data, int size)
     98 {
     99    struct polygon *poly = polygon_create(size);
    100 
    101    memcpy(poly->data, data, sizeof(float) * COMPONENTS * size);
    102    poly->num_verts = size;
    103    poly->dirty = VG_TRUE;
    104    poly->user_vbuf = NULL;
    105 
    106    return poly;
    107 }
    108 
    109 void polygon_destroy(struct polygon *poly)
    110 {
    111    free(poly->data);
    112    free(poly);
    113 }
    114 
    115 void polygon_resize(struct polygon *poly, int new_size)
    116 {
    117    float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
    118    int size = MIN2(sizeof(float) * COMPONENTS * new_size,
    119                    sizeof(float) * COMPONENTS * poly->size);
    120    memcpy(data, poly->data, size);
    121    free(poly->data);
    122    poly->data = data;
    123    poly->size = new_size;
    124    poly->dirty = VG_TRUE;
    125 }
    126 
    127 int polygon_size(struct polygon *poly)
    128 {
    129    return poly->size;
    130 }
    131 
    132 int polygon_vertex_count(struct polygon *poly)
    133 {
    134    return poly->num_verts;
    135 }
    136 
    137 float * polygon_data(struct polygon *poly)
    138 {
    139    return poly->data;
    140 }
    141 
    142 void polygon_vertex_append(struct polygon *p,
    143                            float x, float y)
    144 {
    145    float *vert;
    146 #if DEBUG_POLYGON
    147    debug_printf("Append vertex [%f, %f]\n", x, y);
    148 #endif
    149    if (p->num_verts >= p->size) {
    150       polygon_resize(p, p->size * 2);
    151    }
    152 
    153    vert = ptr_to_vertex(p->data, p->num_verts);
    154    vert[0] = x;
    155    vert[1] = y;
    156    ++p->num_verts;
    157    p->dirty = VG_TRUE;
    158 }
    159 
    160 void polygon_set_vertex(struct polygon *p, int idx,
    161                         float x, float y)
    162 {
    163    float *vert;
    164    if (idx >= p->num_verts) {
    165       /*fixme: error reporting*/
    166       abort();
    167       return;
    168    }
    169 
    170    vert = ptr_to_vertex(p->data, idx);
    171    vert[0] = x;
    172    vert[1] = y;
    173    p->dirty = VG_TRUE;
    174 }
    175 
    176 void polygon_vertex(struct polygon *p, int idx,
    177                     float *vertex)
    178 {
    179    float *vert;
    180    if (idx >= p->num_verts) {
    181       /*fixme: error reporting*/
    182       abort();
    183       return;
    184    }
    185 
    186    vert = ptr_to_vertex(p->data, idx);
    187    vertex[0] = vert[0];
    188    vertex[1] = vert[1];
    189 }
    190 
    191 void polygon_bounding_rect(struct polygon *p,
    192                            float *rect)
    193 {
    194    int i;
    195    float minx, miny, maxx, maxy;
    196    float *vert = ptr_to_vertex(p->data, 0);
    197    minx = vert[0];
    198    maxx = vert[0];
    199    miny = vert[1];
    200    maxy = vert[1];
    201 
    202    for (i = 1; i < p->num_verts; ++i) {
    203       vert = ptr_to_vertex(p->data, i);
    204       minx = MIN2(vert[0], minx);
    205       miny = MIN2(vert[1], miny);
    206 
    207       maxx = MAX2(vert[0], maxx);
    208       maxy = MAX2(vert[1], maxy);
    209    }
    210 
    211    rect[0] = minx;
    212    rect[1] = miny;
    213    rect[2] = maxx - minx;
    214    rect[3] = maxy - miny;
    215 }
    216 
    217 int polygon_contains_point(struct polygon *p,
    218                            float x, float y)
    219 {
    220    return 0;
    221 }
    222 
    223 void polygon_append_polygon(struct polygon *dst,
    224                             struct polygon *src)
    225 {
    226    if (dst->num_verts + src->num_verts >= dst->size) {
    227       polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
    228    }
    229    memcpy(ptr_to_vertex(dst->data, dst->num_verts),
    230           src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
    231    dst->num_verts += src->num_verts;
    232 }
    233 
    234 VGboolean polygon_is_closed(struct polygon *p)
    235 {
    236    VGfloat start[2], end[2];
    237 
    238    polygon_vertex(p, 0, start);
    239    polygon_vertex(p, p->num_verts - 1, end);
    240 
    241    return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
    242 }
    243 
    244 static void polygon_prepare_buffer(struct vg_context *ctx,
    245                                    struct polygon *poly)
    246 {
    247    struct pipe_context *pipe;
    248 
    249    /*polygon_print(poly);*/
    250 
    251    pipe = ctx->pipe;
    252 
    253    if (poly->user_vbuf == NULL || poly->dirty) {
    254       poly->screen = pipe->screen;
    255       poly->user_vbuf = poly->data;
    256       poly->dirty = VG_FALSE;
    257    }
    258 }
    259 
    260 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
    261 {
    262    struct pipe_vertex_element velement;
    263    struct pipe_vertex_buffer vbuffer;
    264    VGfloat bounds[4];
    265    VGfloat min_x, min_y, max_x, max_y;
    266 
    267    assert(poly);
    268    polygon_bounding_rect(poly, bounds);
    269    min_x = bounds[0];
    270    min_y = bounds[1];
    271    max_x = bounds[0] + bounds[2];
    272    max_y = bounds[1] + bounds[3];
    273 
    274 #if DEBUG_POLYGON
    275    debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
    276                 min_x, min_y, max_x, max_y);
    277 #endif
    278 
    279    polygon_prepare_buffer(ctx, poly);
    280 
    281    /* tell renderer about the vertex attributes */
    282    memset(&velement, 0, sizeof(velement));
    283    velement.src_offset = 0;
    284    velement.instance_divisor = 0;
    285    velement.vertex_buffer_index = 0;
    286    velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
    287 
    288    /* tell renderer about the vertex buffer */
    289    memset(&vbuffer, 0, sizeof(vbuffer));
    290    vbuffer.user_buffer = poly->user_vbuf;
    291    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
    292 
    293    renderer_polygon_stencil_begin(ctx->renderer,
    294          &velement, ctx->state.vg.fill_rule, VG_FALSE);
    295    renderer_polygon_stencil(ctx->renderer, &vbuffer,
    296          PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
    297    renderer_polygon_stencil_end(ctx->renderer);
    298 
    299    renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
    300    renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
    301    renderer_polygon_fill_end(ctx->renderer);
    302 }
    303 
    304 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
    305 {
    306    struct array *polys = polyarray->array;
    307    VGfloat min_x = polyarray->min_x;
    308    VGfloat min_y = polyarray->min_y;
    309    VGfloat max_x = polyarray->max_x;
    310    VGfloat max_y = polyarray->max_y;
    311    struct pipe_vertex_element velement;
    312    struct pipe_vertex_buffer vbuffer;
    313    VGint i;
    314 
    315 
    316 #if DEBUG_POLYGON
    317    debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
    318                 __FUNCTION__,
    319                 min_x, min_y, max_x, max_y);
    320 #endif
    321 
    322    /* tell renderer about the vertex attributes */
    323    memset(&velement, 0, sizeof(velement));
    324    velement.src_offset = 0;
    325    velement.instance_divisor = 0;
    326    velement.vertex_buffer_index = 0;
    327    velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
    328 
    329    /* tell renderer about the vertex buffer */
    330    memset(&vbuffer, 0, sizeof(vbuffer));
    331    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
    332 
    333    /* prepare the stencil buffer */
    334    renderer_polygon_stencil_begin(ctx->renderer,
    335          &velement, ctx->state.vg.fill_rule, VG_FALSE);
    336    for (i = 0; i < polys->num_elements; ++i) {
    337       struct polygon *poly = (((struct polygon**)polys->data)[i]);
    338 
    339       polygon_prepare_buffer(ctx, poly);
    340       vbuffer.user_buffer = poly->user_vbuf;
    341 
    342       renderer_polygon_stencil(ctx->renderer, &vbuffer,
    343             PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
    344    }
    345    renderer_polygon_stencil_end(ctx->renderer);
    346 
    347    /* fill it */
    348    renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
    349    renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
    350    renderer_polygon_fill_end(ctx->renderer);
    351 }
    352