0,0 → 1,351 |
/************************************************************************** |
* |
* Copyright 2009 VMware, Inc. All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the |
* "Software"), to deal in the Software without restriction, including |
* without limitation the rights to use, copy, modify, merge, publish, |
* distribute, sub license, and/or sell copies of the Software, and to |
* permit persons to whom the Software is furnished to do so, subject to |
* the following conditions: |
* |
* The above copyright notice and this permission notice (including the |
* next paragraph) shall be included in all copies or substantial portions |
* of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR |
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
**************************************************************************/ |
|
#include "polygon.h" |
|
#include "matrix.h" /*for floatsEqual*/ |
#include "vg_context.h" |
#include "vg_state.h" |
#include "renderer.h" |
#include "util_array.h" |
#include "VG/openvg.h" |
|
#include "pipe/p_context.h" |
#include "pipe/p_defines.h" |
#include "pipe/p_state.h" |
#include "util/u_inlines.h" |
#include "pipe/p_screen.h" |
|
#include "util/u_draw_quad.h" |
#include "util/u_math.h" |
|
#include <string.h> |
#include <stdlib.h> |
|
#define DEBUG_POLYGON 0 |
|
#define COMPONENTS 2 |
|
struct polygon |
{ |
VGfloat *data; |
VGint size; |
|
VGint num_verts; |
|
VGboolean dirty; |
void *user_vbuf; |
struct pipe_screen *screen; |
}; |
|
static float *ptr_to_vertex(float *data, int idx) |
{ |
return data + (idx * COMPONENTS); |
} |
|
#if 0 |
static void polygon_print(struct polygon *poly) |
{ |
int i; |
float *vert; |
debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts); |
for (i = 0; i < poly->num_verts; ++i) { |
vert = ptr_to_vertex(poly->data, i); |
debug_printf("%f, %f, ", vert[0], vert[1]); |
} |
debug_printf("\nend\n"); |
} |
#endif |
|
|
struct polygon * polygon_create(int size) |
{ |
struct polygon *poly = malloc(sizeof(struct polygon)); |
|
poly->data = malloc(sizeof(float) * COMPONENTS * size); |
poly->size = size; |
poly->num_verts = 0; |
poly->dirty = VG_TRUE; |
poly->user_vbuf = NULL; |
|
return poly; |
} |
|
struct polygon * polygon_create_from_data(float *data, int size) |
{ |
struct polygon *poly = polygon_create(size); |
|
memcpy(poly->data, data, sizeof(float) * COMPONENTS * size); |
poly->num_verts = size; |
poly->dirty = VG_TRUE; |
poly->user_vbuf = NULL; |
|
return poly; |
} |
|
void polygon_destroy(struct polygon *poly) |
{ |
free(poly->data); |
free(poly); |
} |
|
void polygon_resize(struct polygon *poly, int new_size) |
{ |
float *data = malloc(sizeof(float) * COMPONENTS * new_size); |
int size = MIN2(sizeof(float) * COMPONENTS * new_size, |
sizeof(float) * COMPONENTS * poly->size); |
memcpy(data, poly->data, size); |
free(poly->data); |
poly->data = data; |
poly->size = new_size; |
poly->dirty = VG_TRUE; |
} |
|
int polygon_size(struct polygon *poly) |
{ |
return poly->size; |
} |
|
int polygon_vertex_count(struct polygon *poly) |
{ |
return poly->num_verts; |
} |
|
float * polygon_data(struct polygon *poly) |
{ |
return poly->data; |
} |
|
void polygon_vertex_append(struct polygon *p, |
float x, float y) |
{ |
float *vert; |
#if DEBUG_POLYGON |
debug_printf("Append vertex [%f, %f]\n", x, y); |
#endif |
if (p->num_verts >= p->size) { |
polygon_resize(p, p->size * 2); |
} |
|
vert = ptr_to_vertex(p->data, p->num_verts); |
vert[0] = x; |
vert[1] = y; |
++p->num_verts; |
p->dirty = VG_TRUE; |
} |
|
void polygon_set_vertex(struct polygon *p, int idx, |
float x, float y) |
{ |
float *vert; |
if (idx >= p->num_verts) { |
/*fixme: error reporting*/ |
abort(); |
return; |
} |
|
vert = ptr_to_vertex(p->data, idx); |
vert[0] = x; |
vert[1] = y; |
p->dirty = VG_TRUE; |
} |
|
void polygon_vertex(struct polygon *p, int idx, |
float *vertex) |
{ |
float *vert; |
if (idx >= p->num_verts) { |
/*fixme: error reporting*/ |
abort(); |
return; |
} |
|
vert = ptr_to_vertex(p->data, idx); |
vertex[0] = vert[0]; |
vertex[1] = vert[1]; |
} |
|
void polygon_bounding_rect(struct polygon *p, |
float *rect) |
{ |
int i; |
float minx, miny, maxx, maxy; |
float *vert = ptr_to_vertex(p->data, 0); |
minx = vert[0]; |
maxx = vert[0]; |
miny = vert[1]; |
maxy = vert[1]; |
|
for (i = 1; i < p->num_verts; ++i) { |
vert = ptr_to_vertex(p->data, i); |
minx = MIN2(vert[0], minx); |
miny = MIN2(vert[1], miny); |
|
maxx = MAX2(vert[0], maxx); |
maxy = MAX2(vert[1], maxy); |
} |
|
rect[0] = minx; |
rect[1] = miny; |
rect[2] = maxx - minx; |
rect[3] = maxy - miny; |
} |
|
int polygon_contains_point(struct polygon *p, |
float x, float y) |
{ |
return 0; |
} |
|
void polygon_append_polygon(struct polygon *dst, |
struct polygon *src) |
{ |
if (dst->num_verts + src->num_verts >= dst->size) { |
polygon_resize(dst, dst->num_verts + src->num_verts * 1.5); |
} |
memcpy(ptr_to_vertex(dst->data, dst->num_verts), |
src->data, src->num_verts * COMPONENTS * sizeof(VGfloat)); |
dst->num_verts += src->num_verts; |
} |
|
VGboolean polygon_is_closed(struct polygon *p) |
{ |
VGfloat start[2], end[2]; |
|
polygon_vertex(p, 0, start); |
polygon_vertex(p, p->num_verts - 1, end); |
|
return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]); |
} |
|
static void polygon_prepare_buffer(struct vg_context *ctx, |
struct polygon *poly) |
{ |
struct pipe_context *pipe; |
|
/*polygon_print(poly);*/ |
|
pipe = ctx->pipe; |
|
if (poly->user_vbuf == NULL || poly->dirty) { |
poly->screen = pipe->screen; |
poly->user_vbuf = poly->data; |
poly->dirty = VG_FALSE; |
} |
} |
|
void polygon_fill(struct polygon *poly, struct vg_context *ctx) |
{ |
struct pipe_vertex_element velement; |
struct pipe_vertex_buffer vbuffer; |
VGfloat bounds[4]; |
VGfloat min_x, min_y, max_x, max_y; |
|
assert(poly); |
polygon_bounding_rect(poly, bounds); |
min_x = bounds[0]; |
min_y = bounds[1]; |
max_x = bounds[0] + bounds[2]; |
max_y = bounds[1] + bounds[3]; |
|
#if DEBUG_POLYGON |
debug_printf("Poly bounds are [%f, %f], [%f, %f]\n", |
min_x, min_y, max_x, max_y); |
#endif |
|
polygon_prepare_buffer(ctx, poly); |
|
/* tell renderer about the vertex attributes */ |
memset(&velement, 0, sizeof(velement)); |
velement.src_offset = 0; |
velement.instance_divisor = 0; |
velement.vertex_buffer_index = 0; |
velement.src_format = PIPE_FORMAT_R32G32_FLOAT; |
|
/* tell renderer about the vertex buffer */ |
memset(&vbuffer, 0, sizeof(vbuffer)); |
vbuffer.user_buffer = poly->user_vbuf; |
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */ |
|
renderer_polygon_stencil_begin(ctx->renderer, |
&velement, ctx->state.vg.fill_rule, VG_FALSE); |
renderer_polygon_stencil(ctx->renderer, &vbuffer, |
PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts); |
renderer_polygon_stencil_end(ctx->renderer); |
|
renderer_polygon_fill_begin(ctx->renderer, VG_FALSE); |
renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y); |
renderer_polygon_fill_end(ctx->renderer); |
} |
|
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx) |
{ |
struct array *polys = polyarray->array; |
VGfloat min_x = polyarray->min_x; |
VGfloat min_y = polyarray->min_y; |
VGfloat max_x = polyarray->max_x; |
VGfloat max_y = polyarray->max_y; |
struct pipe_vertex_element velement; |
struct pipe_vertex_buffer vbuffer; |
VGint i; |
|
|
#if DEBUG_POLYGON |
debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n", |
__FUNCTION__, |
min_x, min_y, max_x, max_y); |
#endif |
|
/* tell renderer about the vertex attributes */ |
memset(&velement, 0, sizeof(velement)); |
velement.src_offset = 0; |
velement.instance_divisor = 0; |
velement.vertex_buffer_index = 0; |
velement.src_format = PIPE_FORMAT_R32G32_FLOAT; |
|
/* tell renderer about the vertex buffer */ |
memset(&vbuffer, 0, sizeof(vbuffer)); |
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */ |
|
/* prepare the stencil buffer */ |
renderer_polygon_stencil_begin(ctx->renderer, |
&velement, ctx->state.vg.fill_rule, VG_FALSE); |
for (i = 0; i < polys->num_elements; ++i) { |
struct polygon *poly = (((struct polygon**)polys->data)[i]); |
|
polygon_prepare_buffer(ctx, poly); |
vbuffer.user_buffer = poly->user_vbuf; |
|
renderer_polygon_stencil(ctx->renderer, &vbuffer, |
PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts); |
} |
renderer_polygon_stencil_end(ctx->renderer); |
|
/* fill it */ |
renderer_polygon_fill_begin(ctx->renderer, VG_FALSE); |
renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y); |
renderer_polygon_fill_end(ctx->renderer); |
} |