summaryrefslogtreecommitdiff
path: root/src/glitz_geometry.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glitz_geometry.c')
-rw-r--r--src/glitz_geometry.c820
1 files changed, 612 insertions, 208 deletions
diff --git a/src/glitz_geometry.c b/src/glitz_geometry.c
index 733ccb6..1ac1108 100644
--- a/src/glitz_geometry.c
+++ b/src/glitz_geometry.c
@@ -1,11 +1,11 @@
/*
- * Copyright © 2004 David Reveman
+ * Copyright © 2004 David Reveman
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
- * appear in supporting documentation, and that the names of
+ * appear in supporting documentation, and that the name of
* David Reveman not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* David Reveman makes no representations about the suitability of this
@@ -20,7 +20,7 @@
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * Author: David Reveman <c99drn@cs.umu.se>
+ * Author: David Reveman <davidr@novell.com>
*/
#ifdef HAVE_CONFIG_H
@@ -29,209 +29,289 @@
#include "glitzint.h"
-/* This is supposed to be 8x, 4x and 2x rotated grid multi-sample
- patterns. I'm not sure they're actually correct. */
-static glitz_sample_offset_t _8x_multi_sample_offsets[] = {
- { -0.375f, -0.375f },
- { -0.125f, -0.125f },
- { 0.375f, -0.375f },
- { 0.125f, -0.125f },
- { 0.375f, 0.375f },
- { 0.125f, 0.125f },
- { -0.375f, 0.375f },
- { -0.125f, 0.125f }
-};
-
-static unsigned short _8x_multi_sample_weights[] = {
- 0x2000, 0x4000, 0x6000, 0x8000, 0xa000, 0xbfff, 0xdfff, 0xffff
-};
-
-static glitz_sample_info_t _8x_multi_sample = {
- _8x_multi_sample_offsets,
- _8x_multi_sample_weights,
- 8
-};
-
-static glitz_sample_offset_t _4x_multi_sample_offsets[] = {
- { -0.125f, -0.375f },
- { 0.375f, -0.125f },
- { 0.125f, 0.375f },
- { -0.375f, 0.125f }
-};
-
-static unsigned short _4x_multi_sample_weights[] = {
- 0x4000, 0x8000, 0xbfff, 0xffff
-};
-
-static glitz_sample_info_t _4x_multi_sample = {
- _4x_multi_sample_offsets,
- _4x_multi_sample_weights,
- 4
-};
-
-static glitz_sample_offset_t _2x_multi_sample_offsets[] = {
- { -0.24f, -0.24f },
- { 0.24f, 0.24f }
-};
-
-static unsigned short _2x_multi_sample_weights[] = {
- 0x8000, 0xffff
-};
-
-static glitz_sample_info_t _2x_multi_sample = {
- _2x_multi_sample_offsets,
- _2x_multi_sample_weights,
- 2
-};
-
-static glitz_sample_offset_t _1x_sample_offsets[] = {
- { 0.0f, 0.0f }
-};
-
-static unsigned short _1x_sample_weights[] = {
- 0xffff
-};
-
-static glitz_sample_info_t _1x_sample = {
- _1x_sample_offsets,
- _1x_sample_weights,
- 1
-};
-void
-glitz_set_geometry (glitz_surface_t *dst,
- glitz_fixed16_16_t x_dst,
- glitz_fixed16_16_t y_dst,
- glitz_geometry_format_t *format,
- glitz_buffer_t *buffer)
+static glitz_gl_enum_t
+_glitz_data_type (glitz_data_type_t type)
{
- glitz_drawable_t *drawable = (dst->attached)? dst->attached: dst->drawable;
-
- if (buffer) {
- glitz_buffer_reference (buffer);
-
- if (dst->geometry.buffer)
- glitz_buffer_destroy (dst->geometry.buffer);
-
- dst->geometry.buffer = buffer;
-
- dst->geometry.x_offset = FIXED_TO_FLOAT (x_dst);
- dst->geometry.y_offset = FIXED_TO_FLOAT (y_dst);
-
- switch (format->primitive) {
- case GLITZ_GEOMETRY_PRIMITIVE_POINTS:
- dst->geometry.primitive = GLITZ_GL_POINTS;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_LINES:
- dst->geometry.primitive = GLITZ_GL_LINES;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_LINE_STRIP:
- dst->geometry.primitive = GLITZ_GL_LINE_STRIP;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_LINE_LOOP:
- dst->geometry.primitive = GLITZ_GL_LINE_LOOP;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_TRIANGLES:
- dst->geometry.primitive = GLITZ_GL_TRIANGLES;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_TRIANGLE_STRIP:
- dst->geometry.primitive = GLITZ_GL_TRIANGLE_STRIP;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_TRIANGLE_FAN:
- dst->geometry.primitive = GLITZ_GL_TRIANGLE_FAN;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_QUADS:
- dst->geometry.primitive = GLITZ_GL_QUADS;
- break;
- case GLITZ_GEOMETRY_PRIMITIVE_QUAD_STRIP:
- dst->geometry.primitive = GLITZ_GL_QUAD_STRIP;
- break;
- default:
- dst->geometry.primitive = GLITZ_GL_POLYGON;
- break;
- }
-
- switch (format->type) {
+ switch (type) {
case GLITZ_DATA_TYPE_SHORT:
- dst->geometry.type = GLITZ_GL_SHORT;
- break;
+ return GLITZ_GL_SHORT;
case GLITZ_DATA_TYPE_INT:
- dst->geometry.type = GLITZ_GL_INT;
- break;
+ return GLITZ_GL_INT;
case GLITZ_DATA_TYPE_DOUBLE:
- dst->geometry.type = GLITZ_GL_DOUBLE;
- break;
+ return GLITZ_GL_DOUBLE;
default:
- dst->geometry.type = GLITZ_GL_FLOAT;
- break;
+ return GLITZ_GL_FLOAT;
}
+}
- dst->geometry.first = format->first;
- dst->geometry.count = format->count;
+void
+glitz_set_geometry (glitz_surface_t *dst,
+ glitz_geometry_type_t type,
+ glitz_geometry_format_t *format,
+ glitz_buffer_t *buffer)
+{
+ switch (type) {
+ case GLITZ_GEOMETRY_TYPE_VERTEX:
+ {
+ glitz_buffer_reference (buffer);
+ if (dst->geometry.buffer)
+ glitz_buffer_destroy (dst->geometry.buffer);
+ dst->geometry.buffer = buffer;
+
+ dst->geometry.type = GLITZ_GEOMETRY_TYPE_VERTEX;
+
+ switch (format->vertex.primitive) {
+ case GLITZ_PRIMITIVE_POINTS:
+ dst->geometry.u.v.prim = GLITZ_GL_POINTS;
+ break;
+ case GLITZ_PRIMITIVE_LINES:
+ dst->geometry.u.v.prim = GLITZ_GL_LINES;
+ break;
+ case GLITZ_PRIMITIVE_LINE_STRIP:
+ dst->geometry.u.v.prim = GLITZ_GL_LINE_STRIP;
+ break;
+ case GLITZ_PRIMITIVE_LINE_LOOP:
+ dst->geometry.u.v.prim = GLITZ_GL_LINE_LOOP;
+ break;
+ case GLITZ_PRIMITIVE_TRIANGLES:
+ dst->geometry.u.v.prim = GLITZ_GL_TRIANGLES;
+ break;
+ case GLITZ_PRIMITIVE_TRIANGLE_STRIP:
+ dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_STRIP;
+ break;
+ case GLITZ_PRIMITIVE_TRIANGLE_FAN:
+ dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_FAN;
+ break;
+ case GLITZ_PRIMITIVE_QUADS:
+ dst->geometry.u.v.prim = GLITZ_GL_QUADS;
+ break;
+ case GLITZ_PRIMITIVE_QUAD_STRIP:
+ dst->geometry.u.v.prim = GLITZ_GL_QUAD_STRIP;
+ break;
+ default:
+ dst->geometry.u.v.prim = GLITZ_GL_POLYGON;
+ break;
+ }
+
+ dst->geometry.u.v.type = _glitz_data_type (format->vertex.type);
+ dst->geometry.stride = format->vertex.bytes_per_vertex;
+ dst->geometry.attributes = format->vertex.attributes;
- if (drawable->format->samples > 1) {
- if (format->edge_hint != GLITZ_GEOMETRY_EDGE_HINT_SHARP) {
- dst->flags |= GLITZ_SURFACE_FLAG_MULTISAMPLE_MASK;
+ if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK)
+ {
+ dst->geometry.u.v.src.type =
+ _glitz_data_type (format->vertex.src.type);
+ dst->geometry.u.v.src.offset = format->vertex.src.offset;
+
+ if (format->vertex.src.size == GLITZ_COORDINATE_SIZE_XY)
+ dst->geometry.u.v.src.size = 2;
+ else
+ dst->geometry.u.v.src.size = 1;
+ }
+
+ if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK)
+ {
+ dst->geometry.u.v.mask.type =
+ _glitz_data_type (format->vertex.mask.type);
+ dst->geometry.u.v.mask.offset = format->vertex.mask.offset;
+
+ if (format->vertex.mask.size == GLITZ_COORDINATE_SIZE_XY)
+ dst->geometry.u.v.mask.size = 2;
+ else
+ dst->geometry.u.v.mask.size = 1;
+ }
+ } break;
+ case GLITZ_GEOMETRY_TYPE_BITMAP:
+ glitz_buffer_reference (buffer);
+ if (dst->geometry.buffer)
+ glitz_buffer_destroy (dst->geometry.buffer);
+ dst->geometry.buffer = buffer;
+
+ dst->geometry.type = GLITZ_GEOMETRY_TYPE_BITMAP;
- if (format->edge_hint != GLITZ_GEOMETRY_EDGE_HINT_FAST_SMOOTH)
- dst->flags |= GLITZ_SURFACE_FLAG_NICEST_MULTISAMPLE_MASK;
+ if (format->bitmap.scanline_order ==
+ GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
+ dst->geometry.u.b.top_down = 1;
else
- dst->flags &= ~GLITZ_SURFACE_FLAG_NICEST_MULTISAMPLE_MASK;
- } else
- dst->flags &= ~GLITZ_SURFACE_FLAG_MULTISAMPLE_MASK;
- } else {
- if (format->mode == GLITZ_GEOMETRY_MODE_INDIRECT) {
- switch (format->edge_hint) {
- case GLITZ_GEOMETRY_EDGE_HINT_BEST_SMOOTH:
- if (drawable->format->stencil_size >= 4) {
- dst->indirect = &_8x_multi_sample;
+ dst->geometry.u.b.top_down = 0;
+
+ switch (format->bitmap.pad) {
+ case 2:
+ dst->geometry.u.b.pad = 2;
break;
- }
- /* fall-through */
- case GLITZ_GEOMETRY_EDGE_HINT_GOOD_SMOOTH:
- if (drawable->format->stencil_size >= 3) {
- dst->indirect = &_4x_multi_sample;
+ case 4:
+ dst->geometry.u.b.pad = 4;
break;
- }
- /* fall-through */
- case GLITZ_GEOMETRY_EDGE_HINT_FAST_SMOOTH:
- if (drawable->format->stencil_size >= 2) {
- dst->indirect = &_2x_multi_sample;
+ case 8:
+ dst->geometry.u.b.pad = 8;
break;
- }
- /* fall-through */
- case GLITZ_GEOMETRY_EDGE_HINT_SHARP:
default:
- dst->indirect = &_1x_sample;
- break;
+ dst->geometry.u.b.pad = 1;
+ break;
}
- } else
- dst->indirect = NULL;
- }
- } else {
- if (dst->geometry.buffer)
- glitz_buffer_destroy (dst->geometry.buffer);
+
+ dst->geometry.stride = format->bitmap.bytes_per_line;
+ dst->geometry.attributes = 0;
+ break;
+ default:
+ dst->geometry.type = GLITZ_GEOMETRY_TYPE_NONE;
+ if (dst->geometry.buffer)
+ glitz_buffer_destroy (dst->geometry.buffer);
- dst->geometry.buffer = NULL;
- dst->flags &= ~GLITZ_SURFACE_FLAG_MULTISAMPLE_MASK;
- dst->indirect = NULL;
- }
+ dst->geometry.buffer = NULL;
+ dst->geometry.attributes = 0;
+ break;
+ }
}
slim_hidden_def(glitz_set_geometry);
void
-glitz_geometry_enable_default (glitz_gl_proc_address_list_t *gl,
- glitz_surface_t *dst,
- glitz_box_t *box)
+glitz_set_array (glitz_surface_t *dst,
+ int first,
+ int size,
+ unsigned int count,
+ glitz_fixed16_16_t x_off,
+ glitz_fixed16_16_t y_off)
{
- dst->geometry.data[0] = box->x1;
- dst->geometry.data[1] = box->y1;
- dst->geometry.data[2] = box->x2;
- dst->geometry.data[3] = box->y1;
- dst->geometry.data[4] = box->x2;
- dst->geometry.data[5] = box->y2;
- dst->geometry.data[6] = box->x1;
- dst->geometry.data[7] = box->y2;
+ if (dst->geometry.array)
+ {
+ glitz_multi_array_destroy (dst->geometry.array);
+ dst->geometry.array = NULL;
+ }
+
+ dst->geometry.first = first;
+ dst->geometry.size = size;
+ dst->geometry.count = count;
+ dst->geometry.off.v[0] = FIXED_TO_FLOAT (x_off);
+ dst->geometry.off.v[1] = FIXED_TO_FLOAT (y_off);
+}
+slim_hidden_def(glitz_set_array);
+
+glitz_multi_array_t *
+glitz_multi_array_create (unsigned int size)
+{
+ glitz_multi_array_t *array;
+ int alloc_size;
+
+ if (!size)
+ return NULL;
+
+ alloc_size = sizeof (glitz_multi_array_t) + (sizeof (int) +
+ sizeof (int) +
+ sizeof (unsigned int) +
+ sizeof (glitz_vec2_t) +
+ sizeof (int)) * (size);
+
+ array = (glitz_multi_array_t *) malloc (alloc_size);
+ if (array == NULL)
+ return NULL;
+
+ array->ref_count = 1;
+ array->size = size;
+ array->first = (int *) (array + 1);
+ array->sizes = (int *) (array->first + size);
+ array->count = (int *) (array->sizes + size);
+ array->off = (glitz_vec2_t *) (array->count + size);
+ array->span = (int *) (array->off + size);
+
+ array->n_arrays = 0;
+
+ return array;
+}
+slim_hidden_def(glitz_multi_array_create);
+
+void
+glitz_multi_array_destroy (glitz_multi_array_t *array)
+{
+ if (!array)
+ return;
+
+ array->ref_count--;
+ if (array->ref_count)
+ return;
+
+ free (array);
+}
+
+void
+glitz_multi_array_reference (glitz_multi_array_t *array)
+{
+ if (array == NULL)
+ return;
+
+ array->ref_count++;
+}
+
+void
+glitz_multi_array_add (glitz_multi_array_t *array,
+ int first,
+ int size,
+ unsigned int count,
+ glitz_fixed16_16_t x_off,
+ glitz_fixed16_16_t y_off)
+{
+ int i;
+
+ if (array->size == array->n_arrays)
+ return;
+
+ i = array->n_arrays++;
+
+ array->first[i] = first;
+ array->sizes[i] = size;
+ array->count[i] = count;
+ array->span[i] = 0;
+
+ if (i == 0 || x_off || y_off)
+ {
+ array->off[i].v[0] = FIXED_TO_FLOAT (x_off);
+ array->off[i].v[1] = FIXED_TO_FLOAT (y_off);
+ array->current_span = &array->span[i];
+ }
+
+ (*array->current_span)++;
+}
+slim_hidden_def(glitz_multi_array_add);
+
+void
+glitz_multi_array_reset (glitz_multi_array_t *array)
+{
+ array->n_arrays = 0;
+}
+slim_hidden_def(glitz_multi_array_reset);
+
+void
+glitz_set_multi_array (glitz_surface_t *dst,
+ glitz_multi_array_t *array,
+ glitz_fixed16_16_t x_off,
+ glitz_fixed16_16_t y_off)
+{
+ glitz_multi_array_reference (array);
+
+ if (dst->geometry.array)
+ glitz_multi_array_destroy (dst->geometry.array);
+
+ dst->geometry.array = array;
+ dst->geometry.count = array->n_arrays;
+ dst->geometry.off.v[0] = FIXED_TO_FLOAT (x_off);
+ dst->geometry.off.v[1] = FIXED_TO_FLOAT (y_off);
+}
+slim_hidden_def(glitz_set_multi_array);
+
+void
+glitz_geometry_enable_none (glitz_gl_proc_address_list_t *gl,
+ glitz_surface_t *dst,
+ glitz_box_t *box)
+{
+ dst->geometry.data[0] = (glitz_float_t) box->x1;
+ dst->geometry.data[1] = (glitz_float_t) box->y1;
+ dst->geometry.data[2] = (glitz_float_t) box->x2;
+ dst->geometry.data[3] = (glitz_float_t) box->y1;
+ dst->geometry.data[4] = (glitz_float_t) box->x2;
+ dst->geometry.data[5] = (glitz_float_t) box->y2;
+ dst->geometry.data[6] = (glitz_float_t) box->x1;
+ dst->geometry.data[7] = (glitz_float_t) box->y2;
gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, dst->geometry.data);
}
@@ -239,38 +319,362 @@ glitz_geometry_enable_default (glitz_gl_proc_address_list_t *gl,
void
glitz_geometry_enable (glitz_gl_proc_address_list_t *gl,
glitz_surface_t *dst,
- glitz_gl_enum_t *primitive,
- glitz_gl_int_t *first,
- glitz_gl_sizei_t *count,
glitz_box_t *box)
{
- if (dst->geometry.buffer) {
- void *ptr;
+ switch (dst->geometry.type) {
+ case GLITZ_GEOMETRY_TYPE_VERTEX:
+ gl->vertex_pointer (2, dst->geometry.u.v.type, dst->geometry.stride,
+ glitz_buffer_bind (dst->geometry.buffer,
+ GLITZ_GL_ARRAY_BUFFER));
+ break;
+ case GLITZ_GEOMETRY_TYPE_BITMAP:
+ dst->geometry.u.b.base =
+ glitz_buffer_bind (dst->geometry.buffer,
+ GLITZ_GL_PIXEL_UNPACK_BUFFER);
- ptr = glitz_buffer_bind (dst->geometry.buffer, GLITZ_GL_ARRAY_BUFFER);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0);
- gl->vertex_pointer (2, dst->geometry.type, 0, ptr);
+#if BITMAP_BIT_ORDER == MSBFirst
+ gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_FALSE);
+#else
+ gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_TRUE);
+#endif
+
+ break;
+ case GLITZ_GEOMETRY_TYPE_NONE:
+ glitz_geometry_enable_none (gl, dst, box);
+ }
+}
+
+void
+glitz_geometry_disable (glitz_surface_t *dst)
+{
+ if (dst->geometry.buffer)
+ glitz_buffer_unbind (dst->geometry.buffer);
+}
+
+static void
+_glitz_draw_rectangle (glitz_gl_proc_address_list_t *gl,
+ glitz_surface_t *dst,
+ glitz_box_t *bounds,
+ int damage)
+{
+ glitz_box_t *clip = dst->clip;
+ int n_clip = dst->n_clip;
+ glitz_box_t box;
- if (dst->geometry.x_offset || dst->geometry.y_offset)
- gl->translate_f (dst->geometry.x_offset, dst->geometry.y_offset, 0.0f);
+ while (n_clip--)
+ {
+ box.x1 = clip->x1 + dst->x_clip;
+ box.y1 = clip->y1 + dst->y_clip;
+ box.x2 = clip->x2 + dst->x_clip;
+ box.y2 = clip->y2 + dst->y_clip;
+ if (bounds->x1 > box.x1)
+ box.x1 = bounds->x1;
+ if (bounds->y1 > box.y1)
+ box.y1 = bounds->y1;
+ if (bounds->x2 < box.x2)
+ box.x2 = bounds->x2;
+ if (bounds->y2 < box.y2)
+ box.y2 = bounds->y2;
+
+ if (box.x1 < box.x2 && box.y1 < box.y2)
+ {
+ gl->scissor (box.x1 + dst->x,
+ dst->attached->height - dst->y - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1);
+
+ gl->draw_arrays (GLITZ_GL_QUADS, 0, 4);
+
+ if (damage)
+ glitz_surface_damage (dst, &box, damage);
+ }
+
+ clip++;
+ }
+}
+
+#define MULTI_DRAW_ARRAYS(surface) \
+ ((surface)->drawable->backend->feature_mask & \
+ GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK)
+
+static void
+_glitz_draw_vertex_arrays (glitz_gl_proc_address_list_t *gl,
+ glitz_surface_t *dst,
+ glitz_box_t *bounds,
+ int damage)
+{
+ glitz_multi_array_t *array = dst->geometry.array;
+ glitz_box_t *clip = dst->clip;
+ int i, n_clip = dst->n_clip;
+ glitz_box_t box;
+
+ while (n_clip--)
+ {
+ box.x1 = clip->x1 + dst->x_clip;
+ box.y1 = clip->y1 + dst->y_clip;
+ box.x2 = clip->x2 + dst->x_clip;
+ box.y2 = clip->y2 + dst->y_clip;
+ if (bounds->x1 > box.x1)
+ box.x1 = bounds->x1;
+ if (bounds->y1 > box.y1)
+ box.y1 = bounds->y1;
+ if (bounds->x2 < box.x2)
+ box.x2 = bounds->x2;
+ if (bounds->y2 < box.y2)
+ box.y2 = bounds->y2;
+
+ if (box.x1 < box.x2 && box.y1 < box.y2)
+ {
+ gl->scissor (box.x1 + dst->x,
+ dst->attached->height - dst->y - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1);
+
+ gl->push_matrix ();
+
+ if (dst->geometry.off.v[0] || dst->geometry.off.v[1])
+ gl->translate_f (dst->geometry.off.v[0],
+ dst->geometry.off.v[1], 0.0f);
+
+ if (array)
+ {
+ for (i = 0; i < array->n_arrays;)
+ {
+ gl->translate_f (array->off[i].v[0],
+ array->off[i].v[1], 0.0f);
+
+ if (MULTI_DRAW_ARRAYS (dst))
+ {
+ gl->multi_draw_arrays (dst->geometry.u.v.prim,
+ &array->first[i],
+ &array->count[i],
+ array->span[i]);
+ i += array->span[i];
+ }
+ else
+ {
+ do {
+ if (array->count[i])
+ gl->draw_arrays (dst->geometry.u.v.prim,
+ array->first[i],
+ array->count[i]);
+
+ } while (array->span[++i] == 0);
+ }
+ }
+ } else
+ gl->draw_arrays (dst->geometry.u.v.prim,
+ dst->geometry.first,
+ dst->geometry.count);
+
+ gl->pop_matrix ();
+
+ if (damage)
+ glitz_surface_damage (dst, &box, damage);
+ }
+
+ clip++;
+ }
+}
+
+#define N_STACK_BITMAP 128
+
+#define BITMAP_PAD 4
+#define BITMAP_STRIDE(x, w, a) \
+ (((((x) & 3) + (w) + (((a) << 3) - 1)) / ((a) << 3)) * (a))
+
+#define BITMAP_SETUP(dst, first, size, count, _w, _h, _b_off, _p_off) \
+ (_w) = (size); \
+ (_h) = (count); \
+ (_b_off) = (first) >> 3; \
+ if ((_p_off) != ((first) & 3)) \
+ { \
+ (_p_off) = (first) & 3; \
+ gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, _p_off); \
+ } \
+ if ((dst)->geometry.u.b.top_down) \
+ { \
+ dst_stride = BITMAP_STRIDE ((first), _w, BITMAP_PAD); \
+ if ((dst)->geometry.stride) \
+ src_stride = (dst)->geometry.stride; \
+ else \
+ src_stride = BITMAP_STRIDE ((first), _w, \
+ (dst)->geometry.u.b.pad); \
+ min_stride = MIN (src_stride, dst_stride); \
+ base = (dst)->geometry.u.b.base + (_b_off); \
+ y = (_h); \
+ while (y--) \
+ memcpy (bitmap + ((_h) - 1 - y) * dst_stride, \
+ base + y * src_stride, \
+ min_stride); \
+ (_b_off) = 0; \
+ }
+
+/* TODO: clipping could be done without glScissor, that might be
+ faster. Other then solid colors can be used if bitmap fits into a
+ stipple pattern. Maybe we should add a repeat parameter to
+ glitz_bitmap_format_t as 2, 4, 8, 16 and 32 sized bitmaps can be tiled.
+ */
+static void
+_glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl,
+ glitz_surface_t *dst,
+ glitz_box_t *bounds,
+ int damage)
+{
+ glitz_multi_array_t *array = dst->geometry.array;
+ glitz_box_t *clip = dst->clip;
+ int n, i, n_clip = dst->n_clip;
+ int x, y, w, h, min_stride, dst_stride, src_stride;
+ glitz_gl_ubyte_t *heap_bitmap = NULL;
+ glitz_gl_ubyte_t stack_bitmap[N_STACK_BITMAP];
+ glitz_gl_ubyte_t *base, *bitmap = dst->geometry.u.b.base;
+ int byte_offset, pixel_offset = 0;
+ glitz_float_t x_off, y_off;
+ glitz_box_t box;
+
+ if (dst->geometry.u.b.top_down)
+ {
+ int max_size = 0;
+
+ if (array)
+ {
+ int size;
+
+ for (i = 0, n = array->n_arrays; n--; i++)
+ {
+ x = array->first[i];
+ w = array->sizes[i];
+ size = BITMAP_STRIDE (x, w, BITMAP_PAD) * array->count[i];
+ if (size > max_size)
+ max_size = size;
+ }
+ }
+ else
+ {
+ x = dst->geometry.first;
+ w = dst->geometry.size;
+ max_size = BITMAP_STRIDE (x, w, BITMAP_PAD) * dst->geometry.count;
+ }
+
+ if (max_size > N_STACK_BITMAP)
+ {
+ heap_bitmap = malloc (max_size);
+ if (!heap_bitmap)
+ {
+ glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK);
+ return;
+ }
+ bitmap = heap_bitmap;
+ } else
+ bitmap = stack_bitmap;
+
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, BITMAP_PAD);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
+ }
+ else
+ {
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, dst->geometry.u.b.pad);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
+ dst->geometry.stride * 8);
+ }
- *primitive = dst->geometry.primitive;
- *first = dst->geometry.first;
- *count = dst->geometry.count;
- } else {
- glitz_geometry_enable_default (gl, dst, box);
- *primitive = GLITZ_GL_QUADS;
- *first = 0;
- *count = 4;
- }
+ while (n_clip--)
+ {
+ box.x1 = clip->x1 + dst->x_clip;
+ box.y1 = clip->y1 + dst->y_clip;
+ box.x2 = clip->x2 + dst->x_clip;
+ box.y2 = clip->y2 + dst->y_clip;
+ if (bounds->x1 > box.x1)
+ box.x1 = bounds->x1;
+ if (bounds->y1 > box.y1)
+ box.y1 = bounds->y1;
+ if (bounds->x2 < box.x2)
+ box.x2 = bounds->x2;
+ if (bounds->y2 < box.y2)
+ box.y2 = bounds->y2;
+
+ if (box.x1 < box.x2 && box.y1 < box.y2)
+ {
+ gl->scissor (box.x1 + dst->x,
+ dst->attached->height - dst->y - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1);
+
+ x_off = dst->x + dst->geometry.off.v[0];
+ y_off = dst->y + dst->geometry.off.v[1];
+
+ if (array)
+ {
+ x_off += array->off->v[0];
+ y_off += array->off->v[1];
+
+ glitz_set_raster_pos (gl, x_off,
+ dst->attached->height - y_off);
+
+ for (i = 0, n = array->n_arrays; n--; i++)
+ {
+ if (n)
+ {
+ x_off = array->off[i + 1].v[0];
+ y_off = array->off[i + 1].v[1];
+ }
+
+ BITMAP_SETUP (dst,
+ array->first[i],
+ array->sizes[i],
+ array->count[i],
+ w, h, byte_offset, pixel_offset);
+
+ gl->bitmap (w, h,
+ 0.0f, (glitz_gl_float_t) array->count[i],
+ x_off, -y_off,
+ bitmap + byte_offset);
+ }
+ }
+ else
+ {
+ glitz_set_raster_pos (gl, x_off,
+ dst->attached->height - y_off);
+
+ BITMAP_SETUP (dst,
+ dst->geometry.first,
+ dst->geometry.size,
+ dst->geometry.count,
+ w, h, byte_offset, pixel_offset);
+
+ gl->bitmap (w, h,
+ 0.0f, (glitz_gl_float_t) dst->geometry.count,
+ 0.0f, 0.0f,
+ bitmap + byte_offset);
+ }
+
+ if (damage)
+ glitz_surface_damage (dst, &box, damage);
+ }
+
+ clip++;
+ }
+
+ if (heap_bitmap)
+ free (heap_bitmap);
}
void
-glitz_geometry_disable (glitz_gl_proc_address_list_t *gl,
- glitz_surface_t *dst)
+glitz_geometry_draw_arrays (glitz_gl_proc_address_list_t *gl,
+ glitz_surface_t *dst,
+ glitz_geometry_type_t type,
+ glitz_box_t *bounds,
+ int damage)
{
- if (dst->geometry.buffer &&
- (dst->drawable->backend->feature_mask &
- GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK))
- gl->bind_buffer (GLITZ_GL_ARRAY_BUFFER, 0);
+ switch (type) {
+ case GLITZ_GEOMETRY_TYPE_VERTEX:
+ _glitz_draw_vertex_arrays (gl, dst, bounds, damage);
+ break;
+ case GLITZ_GEOMETRY_TYPE_BITMAP:
+ _glitz_draw_bitmap_arrays (gl, dst, bounds, damage);
+ break;
+ case GLITZ_GEOMETRY_TYPE_NONE:
+ _glitz_draw_rectangle (gl, dst, bounds, damage);
+ break;
+ }
}