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 52struct 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 64static float *ptr_to_vertex(float *data, int idx) 65{ 66 return data + (idx * COMPONENTS); 67} 68 69#if 0 70static 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 84struct 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 97struct 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 109void polygon_destroy(struct polygon *poly) 110{ 111 free(poly->data); 112 free(poly); 113} 114 115void 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 127int polygon_size(struct polygon *poly) 128{ 129 return poly->size; 130} 131 132int polygon_vertex_count(struct polygon *poly) 133{ 134 return poly->num_verts; 135} 136 137float * polygon_data(struct polygon *poly) 138{ 139 return poly->data; 140} 141 142void 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 160void 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 176void 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 191void 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 217int polygon_contains_point(struct polygon *p, 218 float x, float y) 219{ 220 return 0; 221} 222 223void 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 234VGboolean 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 244static 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 260void 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 304void 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