summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <davidr@novell.com>2005-11-29 22:41:26 +0000
committerDavid Reveman <davidr@novell.com>2005-11-29 22:41:26 +0000
commit60bbdc23f8b64ab4410818f679531909739653b1 (patch)
tree59b2e4319301e14f153f48175ca815d7d5764f84
parent788dd168a74afab77069b3a2aef0a8abca6843e9 (diff)
Add YUV surfaces
-rw-r--r--ChangeLog10
-rw-r--r--configure.in2
-rw-r--r--src/agl/glitz_agl_format.c4
-rw-r--r--src/egl/glitz_egl_config.c6
-rw-r--r--src/egl/glitz_egl_surface.c1
-rw-r--r--src/glitz.h30
-rw-r--r--src/glitz_compose.c9
-rw-r--r--src/glitz_context.c7
-rw-r--r--src/glitz_filter.c213
-rw-r--r--src/glitz_format.c98
-rw-r--r--src/glitz_gl.h37
-rw-r--r--src/glitz_pixel.c662
-rw-r--r--src/glitz_program.c283
-rw-r--r--src/glitz_rect.c1
-rw-r--r--src/glitz_surface.c23
-rw-r--r--src/glitz_texture.c61
-rw-r--r--src/glitz_util.c28
-rw-r--r--src/glitzint.h32
-rw-r--r--src/glx/glitz_glx_drawable.c1
-rw-r--r--src/glx/glitz_glx_format.c11
-rw-r--r--src/wgl/glitz_wgl_format.c3
21 files changed, 1100 insertions, 422 deletions
diff --git a/ChangeLog b/ChangeLog
index 0cc71e9..9450410 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2005-11-29 David Reveman <davidr@novell.com>
+
+ * src/glitz.h (GLITZ_REVISION): Bump version to 0.5.1.
+
+ * configure.in: Bump version to 0.5.1.
+
+ YV12 surface support.
+
+ New radial gradient.
+
2005-11-09 David Reveman <davidr@novell.com>
* Add WGL backend. Thanks to Vladimir Vukicevic and Tor Lillqvist.
diff --git a/configure.in b/configure.in
index 1fbf0de..e7245fa 100644
--- a/configure.in
+++ b/configure.in
@@ -6,7 +6,7 @@ dnl ===========================================================================
# Package version number, (as distinct from shared library version)
# This must be manually synchronized with the version in src/glitz.h
-GLITZ_VERSION=0.5.0
+GLITZ_VERSION=0.5.1
# libtool shared library version
# Increment if the interface has additions, changes, removals.
diff --git a/src/agl/glitz_agl_format.c b/src/agl/glitz_agl_format.c
index 29bd101..5de385a 100644
--- a/src/agl/glitz_agl_format.c
+++ b/src/agl/glitz_agl_format.c
@@ -153,6 +153,9 @@ _glitz_agl_format_compare (const void *elem1,
i = score[0] = score[1] = 0;
for (; i < 2; i++) {
+ if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
+ score[i] -= 1000;
+
if (format[i]->d.color.red_size) {
if (format[i]->d.color.red_size == 8)
score[i] += 5;
@@ -232,6 +235,7 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.d.id = 0
+ format.color.fourcc = GLITZ_FOURCC_RGB;
n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *);
diff --git a/src/egl/glitz_egl_config.c b/src/egl/glitz_egl_config.c
index 729269f..16d924f 100644
--- a/src/egl/glitz_egl_config.c
+++ b/src/egl/glitz_egl_config.c
@@ -45,6 +45,9 @@ _glitz_egl_format_compare (const void *elem1,
for (; i < 2; i++)
{
+ if (format[i]->color.fourcc != GLITZ_FOURCC_RGB)
+ score[i] -= 1000;
+
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
@@ -118,7 +121,8 @@ _glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
if (!egl_configs)
return;
- format.d.id = 0;
+ format.d.id = 0;
+ format.d.color.fourcc = GLITZ_FOURCC_RGB;
format.d.doublebuffer = 1;
eglGetConfigs (egl_display, egl_configs, num_configs, &num_configs);
diff --git a/src/egl/glitz_egl_surface.c b/src/egl/glitz_egl_surface.c
index d98be64..440b3d1 100644
--- a/src/egl/glitz_egl_surface.c
+++ b/src/egl/glitz_egl_surface.c
@@ -215,6 +215,7 @@ glitz_egl_destroy (void *abstract_drawable)
GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (surface->base.backend->gl,
&surface->screen_info->program_map);
+ glitz_program_map_init (&surface->screen_info->program_map);
glitz_egl_pop_current (abstract_drawable);
}
diff --git a/src/glitz.h b/src/glitz.h
index c359bdc..71b9091 100644
--- a/src/glitz.h
+++ b/src/glitz.h
@@ -28,7 +28,7 @@
#define GLITZ_MAJOR 0
#define GLITZ_MINOR 5
-#define GLITZ_REVISION 0
+#define GLITZ_REVISION 1
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
@@ -148,17 +148,29 @@ typedef enum {
typedef unsigned long glitz_format_id_t;
+typedef unsigned int glitz_fourcc_t;
+
+#define GLITZ_FORMAT_FOURCC_MASK (1L << 5)
+
+#define GLITZ_FOURCC(a, b, c, d) \
+ ((a) | (b) << 8 | (c) << 16 | ((glitz_fourcc_t) (d)) << 24)
+
+#define GLITZ_FOURCC_RGB ((glitz_fourcc_t) 0x0)
+#define GLITZ_FOURCC_YV12 GLITZ_FOURCC ('Y', 'V', '1', '2')
+#define GLITZ_FOURCC_YUY2 GLITZ_FOURCC ('Y', 'U', 'Y', '2')
+
typedef struct _glitz_color_format_t {
+ glitz_fourcc_t fourcc;
unsigned short red_size;
unsigned short green_size;
unsigned short blue_size;
unsigned short alpha_size;
} glitz_color_format_t;
-#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5)
-#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6)
-#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7)
-#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8)
+#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 6)
+#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 7)
+#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 8)
+#define GLITZ_FORMAT_SAMPLES_MASK (1L << 9)
typedef struct _glitz_drawable_format_t {
glitz_format_id_t id;
@@ -169,15 +181,8 @@ typedef struct _glitz_drawable_format_t {
glitz_bool_t doublebuffer;
} glitz_drawable_format_t;
-#define GLITZ_FORMAT_TYPE_MASK (1L << 5)
-
-typedef enum {
- GLITZ_FORMAT_TYPE_COLOR
-} glitz_format_type_t;
-
typedef struct _glitz_format_t {
glitz_format_id_t id;
- glitz_format_type_t type;
glitz_color_format_t color;
} glitz_format_t;
@@ -569,6 +574,7 @@ typedef struct _glitz_pixel_masks {
} glitz_pixel_masks_t;
typedef struct _glitz_pixel_format {
+ glitz_fourcc_t fourcc;
glitz_pixel_masks_t masks;
int xoffset;
int skip_lines;
diff --git a/src/glitz_compose.c b/src/glitz_compose.c
index 1dcf70f..62d8599 100644
--- a/src/glitz_compose.c
+++ b/src/glitz_compose.c
@@ -347,7 +347,7 @@ _glitz_combine_solid_solidc (glitz_composite_op_t *op)
if (op->solid->alpha > 0)
op->gl->blend_color ((glitz_gl_clampf_t)
- op->solid->red / op->solid->alpha,
+ op->solid->red / op->solid->alpha,
(glitz_gl_clampf_t)
op->solid->green / op->solid->alpha,
(glitz_gl_clampf_t)
@@ -421,9 +421,10 @@ _glitz_combine_map[GLITZ_SURFACE_TYPES][GLITZ_SURFACE_TYPES] = {
((SURFACE_PAD (surface))? \
(TEXTURE_PADABLE (&(surface)->texture)) \
: \
- ( \
- (!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \
- ((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \
+ (TEXTURE_CLAMPABLE (&(surface)->texture) && \
+ ((!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \
+ ((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \
+ ) \
) \
) \
)
diff --git a/src/glitz_context.c b/src/glitz_context.c
index f0977cb..249d933 100644
--- a/src/glitz_context.c
+++ b/src/glitz_context.c
@@ -110,6 +110,11 @@ void
glitz_context_make_current (glitz_context_t *context,
glitz_drawable_t *drawable)
{
+ glitz_lose_current_function_t lose_current;
+
+ lose_current = context->lose_current;
+ context->lose_current = 0;
+
if (drawable != context->drawable)
{
glitz_drawable_reference (drawable);
@@ -145,6 +150,8 @@ glitz_context_make_current (glitz_context_t *context,
GLITZ_DAMAGE_SOLID_MASK);
}
+ context->lose_current = lose_current;
+
drawable->backend->make_current (drawable, context);
}
slim_hidden_def(glitz_context_make_current);
diff --git a/src/glitz_filter.c b/src/glitz_filter.c
index cfe939d..c36d4eb 100644
--- a/src/glitz_filter.c
+++ b/src/glitz_filter.c
@@ -107,6 +107,10 @@ glitz_filter_set_params (glitz_surface_t *surface,
_glitz_filter_params_set (&dm, 3.0f, &params, &n_params);
_glitz_filter_params_set (&dn, 3.0f, &params, &n_params);
+
+ glitz_clamp_value (&dm, 1.0f, 1024.0f);
+ glitz_clamp_value (&dn, 1.0f, 1024.0f);
+
m = dm;
n = dn;
@@ -130,8 +134,10 @@ glitz_filter_set_params (glitz_surface_t *surface,
_glitz_filter_params_set (&weight, 0.0f, &params, &n_params);
if (weight != 0.0f) {
vec = &vecs[surface->filter_params->id++];
- vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit;
- vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit;
+ vec->v[0] = (i - cx) *
+ surface->texture.texcoord_width_unit;
+ vec->v[1] = (cy - j) *
+ surface->texture.texcoord_height_unit;
vec->v[2] = weight;
vec->v[3] = 0.0f;
}
@@ -211,14 +217,15 @@ glitz_filter_set_params (glitz_surface_t *surface,
if (size < 2)
size = 2;
- if (_glitz_filter_params_ensure (surface, size + 1))
- return GLITZ_STATUS_NO_MEMORY;
+ if (filter == GLITZ_FILTER_LINEAR_GRADIENT)
+ {
+ glitz_float_t length, dh, dv;
+ glitz_float_t start_x, start_y, stop_x, stop_y;
- vecs = surface->filter_params->vectors;
+ if (_glitz_filter_params_ensure (surface, size + 1))
+ return GLITZ_STATUS_NO_MEMORY;
- if (filter == GLITZ_FILTER_LINEAR_GRADIENT) {
- glitz_float_t length, angle, dh, dv;
- glitz_float_t start_x, start_y, stop_x, stop_y;
+ vecs = surface->filter_params->vectors;
_glitz_filter_params_set (&start_x, 0.0f, &params, &n_params);
_glitz_filter_params_set (&start_y, 0.0f, &params, &n_params);
@@ -228,32 +235,48 @@ glitz_filter_set_params (glitz_surface_t *surface,
dh = stop_x - start_x;
dv = stop_y - start_y;
- length = sqrtf (dh * dh + dv * dv);
+ length = dh * dh + dv * dv;
- angle = -atan2f (dv, dh);
-
- vecs->v[2] = cosf (angle);
- vecs->v[3] = -sinf (angle);
+ vecs->v[0] = dh / length;
+ vecs->v[1] = dv / length;
+ vecs->v[2] = -vecs->v[0] * start_x - vecs->v[1] * start_y;
+ vecs->v[3] = 0.0f;
+ }
+ else
+ {
+ glitz_float_t r0, r1, r, x0, y0, x1, y1, dx, dy;
- vecs->v[0] = vecs->v[2] * start_x;
- vecs->v[0] += vecs->v[3] * start_y;
+ if (_glitz_filter_params_ensure (surface, size + 2))
+ return GLITZ_STATUS_NO_MEMORY;
- vecs->v[1] = (length)? 1.0f / length: 2147483647.0f;
- } else {
- glitz_float_t r0, r1;
+ vecs = surface->filter_params->vectors;
- _glitz_filter_params_set (&vecs->v[0], 0.5f, &params, &n_params);
- _glitz_filter_params_set (&vecs->v[1], 0.5f, &params, &n_params);
+ _glitz_filter_params_set (&x0, 0.5f, &params, &n_params);
+ _glitz_filter_params_set (&y0, 0.5f, &params, &n_params);
_glitz_filter_params_set (&r0, 0.0f, &params, &n_params);
- _glitz_filter_params_set (&r1, 0.5f, &params, &n_params);
+
+ _glitz_filter_params_set (&x1, x0, &params, &n_params);
+ _glitz_filter_params_set (&y1, y0, &params, &n_params);
+ _glitz_filter_params_set (&r1, r0 + 0.5f, &params, &n_params);
glitz_clamp_value (&r0, 0.0f, r1);
- vecs->v[2] = r0;
- if (r1 != r0)
- vecs->v[3] = 1.0f / (r1 - r0);
- else
- vecs->v[3] = 2147483647.0f;
+ r = r0 / r1;
+
+ dx = x1 - x0;
+ dy = y1 - y0;
+
+ vecs->v[0] = x0 - r * dx;
+ vecs->v[1] = y0 - r * dy;
+ vecs->v[2] = dx * 2.0f;
+ vecs->v[3] = dy * 2.0f;
+
+ vecs++;
+
+ vecs->v[0] = 1.0f / (1.0f + r);
+ vecs->v[1] = -r * vecs->v[0];
+ vecs->v[2] = (r1 * r1 - dx * dx - dy * dy) * 4.0f;
+ vecs->v[3] = 2.0f / vecs->v[2];
}
vecs++;
@@ -309,10 +332,35 @@ glitz_filter_set_params (glitz_surface_t *surface,
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
- if (surface->filter_params)
+ switch (surface->format->color.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ if (_glitz_filter_params_ensure (surface, 2))
+ return GLITZ_STATUS_NO_MEMORY;
+
+ vecs = surface->filter_params->vectors;
+
+ vecs->v[0] = 0.0f;
+ vecs->v[1] = surface->texture.texcoord_height_unit *
+ ((surface->texture.box.y2 + 1) & ~1);
+ vecs->v[2] = surface->texture.texcoord_width_unit *
+ (surface->texture.width >> 1);
+ vecs->v[3] = 0.0f;
+
+ vecs++;
+
+ vecs->v[0] = surface->texture.texcoord_width_unit;
+ vecs->v[1] = surface->texture.texcoord_height_unit;
+ vecs->v[2] = surface->texture.texcoord_width_unit *
+ surface->texture.box.x2 - vecs->v[0];
+ vecs->v[3] = surface->texture.texcoord_height_unit *
+ surface->texture.box.y2 - vecs->v[1];
+
+ surface->filter_params->id = 1;
+ break;
+ default:
free (surface->filter_params);
-
- surface->filter_params = NULL;
+ surface->filter_params = NULL;
+ }
break;
}
@@ -325,6 +373,9 @@ glitz_gl_uint_t
glitz_filter_get_fragment_program (glitz_surface_t *surface,
glitz_composite_op_t *op)
{
+ if (surface->filter_params->fp_type == GLITZ_FP_UNSUPPORTED)
+ return 0;
+
return glitz_get_fragment_program (op,
surface->filter_params->fp_type,
surface->filter_params->id);
@@ -334,43 +385,56 @@ void
glitz_filter_set_type (glitz_surface_t *surface,
glitz_filter_t filter)
{
- switch (filter) {
- case GLITZ_FILTER_CONVOLUTION:
- case GLITZ_FILTER_GAUSSIAN:
- surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
+ switch (surface->format->color.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ switch (filter) {
+ case GLITZ_FILTER_BILINEAR:
+ case GLITZ_FILTER_NEAREST:
+ surface->filter_params->fp_type = GLITZ_FP_COLORSPACE_YV12;
+ break;
+ default:
+ surface->filter_params->fp_type = GLITZ_FP_UNSUPPORTED;
+ break;
+ }
break;
- case GLITZ_FILTER_LINEAR_GRADIENT:
- if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
- if (SURFACE_MIRRORED (surface))
+ default:
+ switch (filter) {
+ case GLITZ_FILTER_CONVOLUTION:
+ case GLITZ_FILTER_GAUSSIAN:
+ surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
+ break;
+ case GLITZ_FILTER_LINEAR_GRADIENT:
+ if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
+ if (SURFACE_MIRRORED (surface))
+ surface->filter_params->fp_type =
+ GLITZ_FP_LINEAR_GRADIENT_REFLECT;
+ else
+ surface->filter_params->fp_type =
+ GLITZ_FP_LINEAR_GRADIENT_REPEAT;
+ } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type =
- GLITZ_FP_LINEAR_GRADIENT_REFLECT;
- else
+ GLITZ_FP_LINEAR_GRADIENT_NEAREST;
+ } else
surface->filter_params->fp_type =
- GLITZ_FP_LINEAR_GRADIENT_REPEAT;
- } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
- surface->filter_params->fp_type =
- GLITZ_FP_LINEAR_GRADIENT_NEAREST;
- } else
- surface->filter_params->fp_type =
- GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
- break;
- case GLITZ_FILTER_RADIAL_GRADIENT:
- if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
- if (SURFACE_MIRRORED (surface))
+ GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
+ break;
+ case GLITZ_FILTER_RADIAL_GRADIENT:
+ if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
+ if (SURFACE_MIRRORED (surface))
+ surface->filter_params->fp_type =
+ GLITZ_FP_RADIAL_GRADIENT_REFLECT;
+ else
+ surface->filter_params->fp_type =
+ GLITZ_FP_RADIAL_GRADIENT_REPEAT;
+ } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type =
- GLITZ_FP_RADIAL_GRADIENT_REFLECT;
- else
+ GLITZ_FP_RADIAL_GRADIENT_NEAREST;
+ } else
surface->filter_params->fp_type =
- GLITZ_FP_RADIAL_GRADIENT_REPEAT;
- } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
- surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_NEAREST;
- } else
- surface->filter_params->fp_type =
- GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
- break;
- case GLITZ_FILTER_BILINEAR:
- case GLITZ_FILTER_NEAREST:
- break;
+ GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
+ default:
+ break;
+ }
}
}
@@ -402,6 +466,15 @@ glitz_filter_enable (glitz_surface_t *surface,
vec++;
+ j = 1;
+ if (surface->filter == GLITZ_FILTER_RADIAL_GRADIENT)
+ {
+ gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, j++,
+ vec->v);
+
+ vec++;
+ }
+
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
glitz_vec4_t v;
@@ -410,10 +483,8 @@ glitz_filter_enable (glitz_surface_t *surface,
v.v[2] = 0.0f;
v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f;
- gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v);
- j = 2;
- } else
- j = 1;
+ gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, j++, v.v);
+ }
for (i = 0; i < surface->filter_params->id; i++, vec++)
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM,
@@ -432,6 +503,18 @@ glitz_filter_enable (glitz_surface_t *surface,
} break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
+ switch (surface->format->color.fourcc) {
+ case GLITZ_FOURCC_YV12: {
+ glitz_vec4_t *vec;
+
+ vec = surface->filter_params->vectors;
+
+ gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0,
+ vec[0].v);
+ gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1,
+ vec[1].v);
+ } break;
+ }
break;
}
}
diff --git a/src/glitz_format.c b/src/glitz_format.c
index 8e93e3a..3d44e00 100644
--- a/src/glitz_format.c
+++ b/src/glitz_format.c
@@ -31,28 +31,32 @@
#include <stdlib.h>
-struct _texture_format {
+static struct _texture_format {
glitz_gl_int_t texture_format;
glitz_format_t format;
} _texture_formats[] = {
- { GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } },
- { GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } },
- { GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } },
- { GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } },
- { GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } },
- { GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } },
- { GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } },
- { GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } },
- { GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } },
- { GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } },
- { GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } },
- { GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } },
- { GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } },
- { GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } },
- { GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } },
- { GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } },
- { GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } },
- { GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } }
+ { GLITZ_GL_ALPHA4, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 4 } } },
+ { GLITZ_GL_ALPHA8, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 8 } } },
+ { GLITZ_GL_ALPHA12, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 12 } } },
+ { GLITZ_GL_ALPHA16, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 16 } } },
+ { GLITZ_GL_R3_G3_B2, { 0, { GLITZ_FOURCC_RGB, 3, 3, 2, 0 } } },
+ { GLITZ_GL_RGB4, { 0, { GLITZ_FOURCC_RGB, 4, 4, 4, 0 } } },
+ { GLITZ_GL_RGB5, { 0, { GLITZ_FOURCC_RGB, 5, 6, 5, 0 } } },
+ { GLITZ_GL_RGB8, { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 } } },
+ { GLITZ_GL_RGB10, { 0, { GLITZ_FOURCC_RGB, 10, 10, 10, 0 } } },
+ { GLITZ_GL_RGB12, { 0, { GLITZ_FOURCC_RGB, 12, 12, 12, 0 } } },
+ { GLITZ_GL_RGB16, { 0, { GLITZ_FOURCC_RGB, 16, 16, 16, 0 } } },
+ { GLITZ_GL_RGBA2, { 0, { GLITZ_FOURCC_RGB, 2, 2, 2, 2 } } },
+ { GLITZ_GL_RGB5_A1, { 0, { GLITZ_FOURCC_RGB, 5, 5, 5, 1 } } },
+ { GLITZ_GL_RGBA4, { 0, { GLITZ_FOURCC_RGB, 4, 4, 4, 4 } } },
+ { GLITZ_GL_RGBA8, { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 } } },
+ { GLITZ_GL_RGB10_A2, { 0, { GLITZ_FOURCC_RGB, 10, 10, 10, 2 } } },
+ { GLITZ_GL_RGBA12, { 0, { GLITZ_FOURCC_RGB, 12, 12, 12, 12 } } },
+ { GLITZ_GL_RGBA16, { 0, { GLITZ_FOURCC_RGB, 16, 16, 16, 16 } } }
+};
+
+static glitz_format_t _texture_format_yv12 = {
+ 0, { GLITZ_FOURCC_YV12, 0, 0, 0, 0 }
};
static void
@@ -79,7 +83,8 @@ void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
- int *n_formats)
+ int *n_formats,
+ unsigned long features)
{
glitz_gl_int_t value;
int i, n_texture_formats;
@@ -88,12 +93,12 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
sizeof (_texture_formats) / sizeof (struct _texture_format);
for (i = 0; i < n_texture_formats; i++) {
- gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
- _texture_formats[i].texture_format, 1, 1, 0,
- GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
+ switch (_texture_formats[i].format.color.fourcc) {
+ case GLITZ_FOURCC_RGB:
+ gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
+ _texture_formats[i].texture_format, 1, 1, 0,
+ GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
- switch (_texture_formats[i].format.type) {
- case GLITZ_FORMAT_TYPE_COLOR:
if (_texture_formats[i].format.color.red_size) {
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
GLITZ_GL_TEXTURE_RED_SIZE,
@@ -136,6 +141,13 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
_texture_formats[i].texture_format,
&_texture_formats[i].format);
}
+
+ /* formats used for YUV surfaces */
+ if (features & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK)
+ {
+ _glitz_add_texture_format (formats, texture_formats, n_formats,
+ GLITZ_GL_LUMINANCE8, &_texture_format_yv12);
+ }
}
static void
@@ -155,7 +167,7 @@ _glitz_add_drawable_format (glitz_int_drawable_format_t *format,
}
}
-/* TODO: Available drawable formats needs to be validated is a similar way
+/* TODO: Available drawable formats needs to be validated in a similar way
as surface formats. */
void
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
@@ -167,10 +179,10 @@ _glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
{
glitz_int_drawable_format_t format;
glitz_drawable_format_t d[] = {
- { 0, { 8, 8, 8, 0 }, 0, 0, 1, 0 },
- { 0, { 8, 8, 8, 8 }, 0, 0, 1, 0 },
- { 0, { 8, 8, 8, 0 }, 24, 8, 1, 1 },
- { 0, { 8, 8, 8, 8 }, 24, 8, 1, 1 }
+ { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 }, 0, 0, 1, 0 },
+ { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 }, 0, 0, 1, 0 },
+ { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 }, 24, 8, 1, 1 },
+ { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 }, 24, 8, 1, 1 }
};
int i;
@@ -196,6 +208,9 @@ glitz_drawable_format_copy (const glitz_drawable_format_t *src,
if (mask & GLITZ_FORMAT_ID_MASK)
dst->id = src->id;
+ if (mask & GLITZ_FORMAT_FOURCC_MASK)
+ dst->color.fourcc = src->color.fourcc;
+
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
dst->color.red_size = src->color.red_size;
@@ -234,6 +249,10 @@ glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
if (templ->d.id != formats->d.id)
continue;
+ if (mask & GLITZ_FORMAT_FOURCC_MASK)
+ if (templ->d.color.fourcc != formats->d.color.fourcc)
+ continue;
+
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (templ->d.color.red_size != formats->d.color.red_size)
continue;
@@ -300,8 +319,8 @@ _glitz_format_find (glitz_format_t *formats,
if (templ->id != formats->id)
continue;
- if (mask & GLITZ_FORMAT_TYPE_MASK)
- if (templ->type != formats->type)
+ if (mask & GLITZ_FORMAT_FOURCC_MASK)
+ if (templ->color.fourcc != formats->color.fourcc)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
@@ -345,9 +364,13 @@ glitz_find_standard_format (glitz_drawable_t *drawable,
glitz_format_t templ;
unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK |
- GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK;
+ GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_FOURCC_MASK;
- templ.type = GLITZ_FORMAT_TYPE_COLOR;
+ templ.color.fourcc = GLITZ_FOURCC_RGB;
+ templ.color.red_size = 0;
+ templ.color.green_size = 0;
+ templ.color.blue_size = 0;
+ templ.color.alpha_size = 0;
switch (format_name) {
case GLITZ_STANDARD_ARGB32:
@@ -360,18 +383,11 @@ glitz_find_standard_format (glitz_drawable_t *drawable,
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
- templ.color.alpha_size = 0;
break;
case GLITZ_STANDARD_A8:
- templ.color.red_size = 0;
- templ.color.green_size = 0;
- templ.color.blue_size = 0;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_A1:
- templ.color.red_size = 0;
- templ.color.green_size = 0;
- templ.color.blue_size = 0;
templ.color.alpha_size = 1;
break;
}
diff --git a/src/glitz_gl.h b/src/glitz_gl.h
index 7b76a31..9332e55 100644
--- a/src/glitz_gl.h
+++ b/src/glitz_gl.h
@@ -202,24 +202,25 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
#define GLITZ_GL_BGR 0x80E0
#define GLITZ_GL_BGRA 0x80E1
-#define GLITZ_GL_ALPHA4 0x803B
-#define GLITZ_GL_ALPHA8 0x803C
-#define GLITZ_GL_ALPHA12 0x803D
-#define GLITZ_GL_ALPHA16 0x803E
-#define GLITZ_GL_R3_G3_B2 0x2A10
-#define GLITZ_GL_RGB4 0x804F
-#define GLITZ_GL_RGB5 0x8050
-#define GLITZ_GL_RGB8 0x8051
-#define GLITZ_GL_RGB10 0x8052
-#define GLITZ_GL_RGB12 0x8053
-#define GLITZ_GL_RGB16 0x8054
-#define GLITZ_GL_RGBA2 0x8055
-#define GLITZ_GL_RGBA4 0x8056
-#define GLITZ_GL_RGB5_A1 0x8057
-#define GLITZ_GL_RGBA8 0x8058
-#define GLITZ_GL_RGB10_A2 0x8059
-#define GLITZ_GL_RGBA12 0x805A
-#define GLITZ_GL_RGBA16 0x805B
+#define GLITZ_GL_ALPHA4 0x803B
+#define GLITZ_GL_ALPHA8 0x803C
+#define GLITZ_GL_ALPHA12 0x803D
+#define GLITZ_GL_ALPHA16 0x803E
+#define GLITZ_GL_LUMINANCE8 0x8040
+#define GLITZ_GL_R3_G3_B2 0x2A10
+#define GLITZ_GL_RGB4 0x804F
+#define GLITZ_GL_RGB5 0x8050
+#define GLITZ_GL_RGB8 0x8051
+#define GLITZ_GL_RGB10 0x8052
+#define GLITZ_GL_RGB12 0x8053
+#define GLITZ_GL_RGB16 0x8054
+#define GLITZ_GL_RGBA2 0x8055
+#define GLITZ_GL_RGBA4 0x8056
+#define GLITZ_GL_RGB5_A1 0x8057
+#define GLITZ_GL_RGBA8 0x8058
+#define GLITZ_GL_RGB10_A2 0x8059
+#define GLITZ_GL_RGBA12 0x805A
+#define GLITZ_GL_RGBA16 0x805B
#define GLITZ_GL_FRONT_AND_BACK 0x0408
#define GLITZ_GL_FLAT 0x1D00
diff --git a/src/glitz_pixel.c b/src/glitz_pixel.c
index 95c3d75..b0010e6 100644
--- a/src/glitz_pixel.c
+++ b/src/glitz_pixel.c
@@ -37,23 +37,10 @@ typedef struct _glitz_gl_pixel_format {
glitz_gl_enum_t type;
} glitz_gl_pixel_format_t;
-static glitz_gl_pixel_format_t _gl_pixel_formats[] = {
+static glitz_gl_pixel_format_t _gl_rgb_pixel_formats[] = {
{
{
- {
- 8,
- 0x000000ff,
- 0x00000000,
- 0x00000000,
- 0x00000000
- },
- 0, 0, 0,
- GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
- },
- GLITZ_GL_ALPHA,
- GLITZ_GL_UNSIGNED_BYTE
- }, {
- {
+ GLITZ_FOURCC_RGB,
{
32,
0xff000000,
@@ -72,12 +59,31 @@ static glitz_gl_pixel_format_t _gl_pixel_formats[] = {
GLITZ_GL_UNSIGNED_BYTE
#endif
+ }, {
+ {
+ GLITZ_FOURCC_RGB,
+ {
+ 8,
+ 0x000000ff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000
+ },
+ 0, 0, 0,
+ GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
+ },
+ GLITZ_GL_ALPHA,
+ GLITZ_GL_UNSIGNED_BYTE
}
};
-static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
+#define N_RGB_FORMATS \
+ (sizeof (_gl_rgb_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
+
+static glitz_gl_pixel_format_t _gl_packed_rgb_pixel_formats[] = {
{
{
+ GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@@ -99,6 +105,31 @@ static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
}
};
+#define N_PACKED_RGB_FORMATS \
+ (sizeof (_gl_packed_rgb_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
+
+static glitz_gl_pixel_format_t _gl_yuv_pixel_formats[] = {
+ {
+ {
+ GLITZ_FOURCC_YV12,
+ {
+ 12,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000
+ },
+ 0, 0, 0,
+ GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
+ },
+ GLITZ_GL_LUMINANCE,
+ GLITZ_GL_UNSIGNED_BYTE
+ }
+};
+
+#define N_YUV_FORMATS \
+ (sizeof (_gl_yuv_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
+
#define SOLID_ALPHA 0
#define SOLID_RED 1
#define SOLID_GREEN 2
@@ -106,6 +137,7 @@ static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
static glitz_pixel_format_t _solid_format[] = {
{
+ GLITZ_FOURCC_RGB,
{
16,
0x0000ffff,
@@ -116,6 +148,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
+ GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@@ -126,6 +159,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
+ GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@@ -136,6 +170,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
+ GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@@ -153,19 +188,19 @@ typedef struct _glitz_pixel_color {
} glitz_pixel_color_t;
typedef struct _glitz_pixel_transform_op {
- char *line;
- int offset;
+ char *line, *line2, *line3;
+ int offset;
glitz_pixel_format_t *format;
- glitz_pixel_color_t *color;
+ glitz_pixel_color_t *color;
} glitz_pixel_transform_op_t;
-#define FETCH(p, mask) \
- ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
+#define FETCH(p, mask) \
+ ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
0xffffffff) / ((uint64_t) (mask)))): 0x0)
-#define FETCH_A(p, mask) \
- ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
- 0xffffffff) /((uint64_t) (mask)))): 0xffffffff)
+#define FETCH_A(p, mask) \
+ ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
+ 0xffffffff) / ((uint64_t) (mask)))): 0xffffffff)
typedef void (*glitz_pixel_fetch_function_t) (glitz_pixel_transform_op_t *op);
@@ -237,9 +272,59 @@ _fetch_32 (glitz_pixel_transform_op_t *op)
op->color->b = FETCH (p, op->format->masks.blue_mask);
}
+static void
+_fetch_yv12 (glitz_pixel_transform_op_t *op)
+{
+ int16_t y = ((uint8_t *) op->line)[op->offset] - 16;
+ int16_t v = ((uint8_t *) op->line2)[op->offset >> 1] - 128;
+ int16_t u = ((uint8_t *) op->line3)[op->offset >> 1] - 128;
+ int32_t r, g, b;
+
+ /* TODO: use tables, in a tight loop */
+ op->color->a = 0xffffffff;
+ /* all colors multiplied by 0x010101, cropped, shifted */
+ /* R = 1.164(Y - 16) + 1.596(V - 128) */
+ r = 0x012b27 * y + 0x019a2e * v;
+ op->color->r = r >= 0 ? r < 0x1000000 ? (((unsigned) r) << 8) :
+ 0xffffffff : 0;
+ /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
+ g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
+ op->color->g = g >= 0 ? g < 0x1000000 ? (((unsigned) g) << 8) :
+ 0xffffffff : 0;
+ /* B = 1.164(Y - 16) + 2.018(U - 128) */
+ b = 0x012b27 * y + 0x0206a2 * u;
+ op->color->b = b >= 0 ? b < 0x1000000 ? (((unsigned) b) << 8) :
+ 0xffffffff : 0;
+}
+
+static void
+_fetch_yuy2 (glitz_pixel_transform_op_t *op)
+{
+ int16_t y = ((uint8_t *) op->line)[op->offset << 1] - 16;
+ int16_t u = ((uint8_t *) op->line)[((op->offset << 1) & -4) + 1] - 128;
+ int16_t v = ((uint8_t *) op->line)[((op->offset << 1) & -4) + 3] - 128;
+ int32_t r, g, b;
+
+ /* TODO: use tables, in a tight loop */
+ op->color->a = 0xffffffff;
+ /* all colors multiplied by 0x010101, cropped, shifted */
+ /* R = 1.164(Y - 16) + 1.596(V - 128) */
+ r = 0x012b27 * y + 0x019a2e * v;
+ op->color->r = r >= 0 ? r < 0x1000000 ? (((unsigned) r) << 8) :
+ 0xffffffff : 0;
+ /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
+ g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
+ op->color->g = g >= 0 ? g < 0x1000000 ? (((unsigned) g) << 8) :
+ 0xffffffff : 0;
+ /* B = 1.164(Y - 16) + 2.018(U - 128) */
+ b = 0x012b27 * y + 0x0206a2 * u;
+ op->color->b = b >= 0 ? b < 0x1000000 ? (((unsigned) b) << 8) :
+ 0xffffffff : 0;
+}
+
typedef void (*glitz_pixel_store_function_t) (glitz_pixel_transform_op_t *op);
-#define STORE(v, mask) \
+#define STORE(v, mask) \
(((uint32_t) (((v) * (uint64_t) (mask)) / 0xffffffff)) & (mask))
static void
@@ -320,15 +405,76 @@ _store_32 (glitz_pixel_transform_op_t *op)
STORE (op->color->b, op->format->masks.blue_mask);
}
+static void
+_store_yv12 (glitz_pixel_transform_op_t *op)
+{
+ uint8_t *yp = &((uint8_t *) op->line)[op->offset];
+ int16_t y;
+
+ /* Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 */
+ y = op->color->r / 0x03e41be4 + op->color->g / 0x01fbefbf +
+ op->color->b / 0x0a343eb2 + 16;
+
+ *yp = y > 0 ? y < 255 ? y : 255 : 0;
+
+ if (op->line2 && (op->offset & 1) == 0)
+ {
+ uint8_t *vp = &((uint8_t *) op->line2)[op->offset >> 1];
+ uint8_t *up = &((uint8_t *) op->line3)[op->offset >> 1];
+ int16_t v, u;
+
+ /* V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 */
+ v = op->color->r / 0x024724bd - op->color->g / 0x02b7a6f5 -
+ op->color->b / 0x0e15a241 + 128;
+ *vp = v > 0 ? v < 255 ? v : 255 : 0;
+
+ /* U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 */
+ u = op->color->b / 0x024724bd - op->color->r / 0x06c1bad0 -
+ op->color->g / 0x36fb99f + 128;
+
+ *up = u > 0 ? u < 255 ? u : 255 : 0;
+ }
+}
+
+static void
+_store_yuy2 (glitz_pixel_transform_op_t *op)
+{
+ uint8_t *p = (uint8_t *) &op->line[op->offset << 1];
+ int16_t y, v, u;
+
+ /* Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 */
+ y = op->color->r / 0x03e41be4 + op->color->g / 0x01fbefbf +
+ op->color->b / 0x0a343eb2 + 16;
+
+ p[0] = y >= 0 ? y < 255 ? y : 255 : 0;
+
+ if ((op->offset & 1) == 0)
+ {
+ /* U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 */
+ u = op->color->b / 0x024724bd - op->color->r / 0x06c1bad0 -
+ op->color->g / 0x36fb99f + 128;
+
+ p[1] = u >= 0 ? u < 255 ? u : 255 : 0;
+ }
+ else
+ {
+ /* V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 */
+ v = op->color->r / 0x024724bd - op->color->g / 0x02b7a6f5 -
+ op->color->b / 0x0e15a241 + 128;
+
+ p[1] = v >= 0 ? v < 255 ? v : 255 : 0;
+ }
+}
+
#define GLITZ_TRANSFORM_PIXELS_MASK (1L << 0)
#define GLITZ_TRANSFORM_SCANLINE_ORDER_MASK (1L << 1)
#define GLITZ_TRANSFORM_COPY_BOX_MASK (1L << 2)
typedef struct _glitz_image {
- char *data;
+ char *data;
glitz_pixel_format_t *format;
- int width;
- int height;
+ int width;
+ int height;
} glitz_image_t;
static void
@@ -342,62 +488,111 @@ _glitz_pixel_transform (unsigned long transform,
int width,
int height)
{
- int src_stride, dst_stride;
- int x, y, bytes_per_pixel = 0;
+ int src_stride, dst_stride;
+ int src_planeoffset = 0, dst_planeoffset = 0;
+ int x, y, bytes_per_pixel = 0;
glitz_pixel_fetch_function_t fetch;
glitz_pixel_store_function_t store;
- glitz_pixel_color_t color;
- glitz_pixel_transform_op_t src_op, dst_op;
-
- switch (src->format->masks.bpp) {
- case 1:
- fetch = _fetch_1;
- break;
- case 8:
- fetch = _fetch_8;
+ glitz_pixel_color_t color;
+ glitz_pixel_transform_op_t src_op, dst_op;
+
+ switch (src->format->fourcc) {
+ case GLITZ_FOURCC_RGB:
+ switch (src->format->masks.bpp) {
+ case 1:
+ fetch = _fetch_1;
+ break;
+ case 8:
+ fetch = _fetch_8;
+ break;
+ case 16:
+ fetch = _fetch_16;
+ break;
+ case 24:
+ fetch = _fetch_24;
+ break;
+ case 32:
+ default:
+ fetch = _fetch_32;
+ }
break;
- case 16:
- fetch = _fetch_16;
+ case GLITZ_FOURCC_YV12:
+ fetch = _fetch_yv12;
break;
- case 24:
- fetch = _fetch_24;
+ case GLITZ_FOURCC_YUY2:
+ fetch = _fetch_yuy2;
break;
- case 32:
default:
fetch = _fetch_32;
- break;
}
- switch (dst->format->masks.bpp) {
- case 1:
- store = _store_1;
- break;
- case 8:
- store = _store_8;
+ switch (dst->format->fourcc) {
+ case GLITZ_FOURCC_RGB:
+ switch (dst->format->masks.bpp) {
+ case 1:
+ store = _store_1;
+ break;
+ case 8:
+ store = _store_8;
+ break;
+ case 16:
+ store = _store_16;
+ break;
+ case 24:
+ store = _store_24;
+ break;
+ case 32:
+ default:
+ store = _store_32;
+ }
break;
- case 16:
- store = _store_16;
+ case GLITZ_FOURCC_YV12:
+ store = _store_yv12;
break;
- case 24:
- store = _store_24;
+ case GLITZ_FOURCC_YUY2:
+ store = _store_yuy2;
break;
- case 32:
default:
store = _store_32;
+ }
+
+ switch (src->format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ src_stride = (src->format->bytes_per_line) ?
+ src->format->bytes_per_line: (src->width + 3) & -4;
+ src_planeoffset = src_stride * src->height;
+ bytes_per_pixel = 1;
break;
+ default:
+ src_stride = (src->format->bytes_per_line) ?
+ src->format->bytes_per_line:
+ (((src->width * src->format->masks.bpp) / 8) + 3) & -4;
+ /* This only works for bpp % 8 = 0, but it shouldn't be a problem as
+ * it will never be used for bitmaps */
+ bytes_per_pixel = src->format->masks.bpp / 8;
}
- src_stride = (src->format->bytes_per_line)? src->format->bytes_per_line:
- (((src->width * src->format->masks.bpp) / 8) + 3) & -4;
if (src_stride == 0)
src_stride = 1;
+
src_op.format = src->format;
src_op.color = &color;
- dst_stride = (dst->format->bytes_per_line)? dst->format->bytes_per_line:
- (((dst->width * dst->format->masks.bpp) / 8) + 3) & -4;
+ switch (dst->format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ dst_stride = (dst->format->bytes_per_line) ?
+ dst->format->bytes_per_line: (dst->width + 3) & -4;
+ dst_planeoffset = dst_stride * dst->height;
+ break;
+ default:
+ dst_stride = (dst->format->bytes_per_line) ?
+ dst->format->bytes_per_line:
+ (((dst->width * dst->format->masks.bpp) / 8) + 3) & -4;
+ }
+
if (dst_stride == 0)
dst_stride = 1;
+
dst_op.format = dst->format;
dst_op.color = &color;
@@ -408,7 +603,49 @@ _glitz_pixel_transform (unsigned long transform,
else
src_op.line = &src->data[(y + y_src) * src_stride];
- dst_op.line = &dst->data[(y + y_dst) * dst_stride];
+ switch (src->format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ if (src->format->scanline_order != dst->format->scanline_order)
+ {
+ src_op.line2 =
+ &src->data[src_planeoffset +
+ (((src->height - (y + y_src) - 1) >> 1))
+ * (src_stride >> 1)];
+ src_op.line3 =
+ &src->data[src_planeoffset +
+ (src_planeoffset >> 2) +
+ (((src->height - (y + y_src) - 1) >> 1))
+ * (src_stride >> 1)];
+ }
+ else
+ {
+ src_op.line2 =
+ &src->data[src_planeoffset +
+ ((y + y_src) >> 1) * (src_stride >> 1)];
+ src_op.line3 =
+ &src->data[src_planeoffset +
+ (src_planeoffset >> 2) +
+ ((y + y_src) >> 1) * (src_stride >> 1)];
+ }
+ break;
+ }
+
+ dst_op.line = &dst->data[(y + y_dst) * dst_stride];
+ dst_op.line2 = dst_op.line3 = NULL;
+
+ switch (dst->format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ if ((y & 1) == 0)
+ {
+ dst_op.line2 =
+ &dst->data[dst_planeoffset +
+ ((y + y_dst) >> 1) * (dst_stride >> 1)];
+ dst_op.line3 =
+ &dst->data[dst_planeoffset + (dst_planeoffset >> 2) +
+ ((y + y_dst) >> 1) * (dst_stride >> 1)];
+ }
+ break;
+ }
if (transform & GLITZ_TRANSFORM_PIXELS_MASK)
{
@@ -423,41 +660,62 @@ _glitz_pixel_transform (unsigned long transform,
}
else
{
- /* This only works for bpp >= 8, but it shouldn't be a problem as
- it will never be used for bitmaps */
- if (bytes_per_pixel == 0)
- bytes_per_pixel = src->format->masks.bpp / 8;
-
memcpy (&dst_op.line[x_dst * bytes_per_pixel],
&src_op.line[x_src * bytes_per_pixel],
width * bytes_per_pixel);
+
+ switch (dst->format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ /* Will overwrite color components of adjacent pixels for odd
+ * image sizes or not update color on odd start lines -
+ * who cares? */
+ if ((y & 1) == 0)
+ {
+ memcpy (&dst_op.line2[x_dst >> 1],
+ &src_op.line2[x_src >> 1],
+ width >> 1);
+ memcpy (&dst_op.line3[x_dst >> 1],
+ &src_op.line3[x_src >> 1],
+ width >> 1);
+ }
+ break;
+ }
}
}
}
static glitz_bool_t
-_glitz_format_match (glitz_pixel_masks_t *masks1,
- glitz_pixel_masks_t *masks2,
- unsigned long mask)
+_glitz_format_match (glitz_pixel_format_t *format1,
+ glitz_pixel_format_t *format2,
+ unsigned long mask)
{
- if (masks1->bpp != masks2->bpp)
+ if (format1->fourcc != format2->fourcc)
return 0;
- if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
- if (masks1->red_mask != masks2->red_mask)
+ switch (format1->fourcc) {
+ case GLITZ_FOURCC_RGB:
+ if (format1->masks.bpp != format2->masks.bpp)
return 0;
- if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
- if (masks1->green_mask != masks2->green_mask)
- return 0;
+ if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
+ if (format1->masks.red_mask != format2->masks.red_mask)
+ return 0;
- if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
- if (masks1->blue_mask != masks2->blue_mask)
- return 0;
+ if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
+ if (format1->masks.green_mask != format2->masks.green_mask)
+ return 0;
- if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
- if (masks1->alpha_mask != masks2->alpha_mask)
- return 0;
+ if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
+ if (format1->masks.blue_mask != format2->masks.blue_mask)
+ return 0;
+
+ if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
+ if (format1->masks.alpha_mask != format2->masks.alpha_mask)
+ return 0;
+ break;
+ default:
+ return 1;
+ }
return 1;
}
@@ -467,29 +725,32 @@ _glitz_find_gl_pixel_format (glitz_pixel_format_t *format,
unsigned long color_mask,
unsigned long feature_mask)
{
- int i, n_formats;
+ int i;
- n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
- for (i = 0; i < n_formats; i++)
+ for (i = 0; i < N_RGB_FORMATS; i++)
{
- if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks,
- &format->masks, color_mask))
- return &_gl_pixel_formats[i];
+ if (_glitz_format_match (&_gl_rgb_pixel_formats[i].pixel,
+ format, color_mask))
+ return &_gl_rgb_pixel_formats[i];
}
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
{
- n_formats = sizeof (_gl_packed_pixel_formats) /
- sizeof (glitz_gl_pixel_format_t);
-
- for (i = 0; i < n_formats; i++)
+ for (i = 0; i < N_PACKED_RGB_FORMATS; i++)
{
- if (_glitz_format_match (&_gl_packed_pixel_formats[i].pixel.masks,
- &format->masks, color_mask))
- return &_gl_packed_pixel_formats[i];
+ if (_glitz_format_match (&_gl_packed_rgb_pixel_formats[i].pixel,
+ format, color_mask))
+ return &_gl_packed_rgb_pixel_formats[i];
}
}
+ for (i = 0; i < N_YUV_FORMATS; i++)
+ {
+ if (_glitz_format_match (&_gl_yuv_pixel_formats[i].pixel,
+ format, color_mask))
+ return &_gl_yuv_pixel_formats[i];
+ }
+
return NULL;
}
@@ -505,10 +766,10 @@ _component_size (unsigned long mask)
}
static glitz_bool_t
-_glitz_format_diff (glitz_pixel_masks_t *masks,
- glitz_color_format_t *pixel_color,
- glitz_color_format_t *internal_color,
- int *diff)
+_glitz_rgb_format_diff (glitz_pixel_masks_t *masks,
+ glitz_color_format_t *pixel_color,
+ glitz_color_format_t *internal_color,
+ int *diff)
{
int size;
@@ -546,48 +807,69 @@ _glitz_find_best_gl_pixel_format (glitz_pixel_format_t *format,
glitz_color_format_t *internal_color,
unsigned long feature_mask)
{
- glitz_gl_pixel_format_t *best = NULL;
- glitz_color_format_t color;
- int i, n_formats, diff, best_diff = MAXSHORT;
+ glitz_gl_pixel_format_t *best = _gl_rgb_pixel_formats;
+ glitz_color_format_t color;
+ int i, diff, best_diff = MAXSHORT;
+ glitz_pixel_masks_t *masks;
+
+ switch (internal_color->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ case GLITZ_FOURCC_YUY2:
+ for (i = 0; i < N_YUV_FORMATS; i++)
+ {
+ glitz_fourcc_t fourcc;
- color.red_size = _component_size (format->masks.red_mask);
- color.green_size = _component_size (format->masks.green_mask);
- color.blue_size = _component_size (format->masks.blue_mask);
- color.alpha_size = _component_size (format->masks.alpha_mask);
+ fourcc = internal_color->fourcc;
+ if (_gl_yuv_pixel_formats[i].pixel.fourcc == fourcc)
+ return &_gl_yuv_pixel_formats[i];
+ }
+ default:
+ break;
+ }
+
+ switch (format->fourcc) {
+ case GLITZ_FOURCC_RGB:
+ color.red_size = _component_size (format->masks.red_mask);
+ color.green_size = _component_size (format->masks.green_mask);
+ color.blue_size = _component_size (format->masks.blue_mask);
+ color.alpha_size = _component_size (format->masks.alpha_mask);
+ break;
+ case GLITZ_FOURCC_YV12:
+ case GLITZ_FOURCC_YUY2:
+ color.red_size = color.green_size = color.blue_size = 8;
+ color.alpha_size = 0;
+ break;
+ default:
+ color.red_size = color.green_size = color.blue_size =
+ color.alpha_size = 8;
+ break;
+ }
- n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
- for (i = 0; best_diff > 0 && i < n_formats; i++)
+ for (i = 0; best_diff > 0 && i < N_RGB_FORMATS; i++)
{
- if (_glitz_format_diff (&_gl_pixel_formats[i].pixel.masks,
- &color,
- internal_color,
- &diff))
+ masks = &_gl_rgb_pixel_formats[i].pixel.masks;
+ if (_glitz_rgb_format_diff (masks, &color, internal_color, &diff))
{
if (diff < best_diff)
{
- best = &_gl_pixel_formats[i];
+ best = &_gl_rgb_pixel_formats[i];
best_diff = diff;
}
}
}
- if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
- {
- n_formats = sizeof (_gl_packed_pixel_formats) /
- sizeof (glitz_gl_pixel_format_t);
+ if (!(feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK))
+ return best;
- for (i = 0; best_diff > 0 && i < n_formats; i++)
+ for (i = 0; best_diff > 0 && i < N_PACKED_RGB_FORMATS; i++)
+ {
+ masks = &_gl_packed_rgb_pixel_formats[i].pixel.masks;
+ if (_glitz_rgb_format_diff (masks, &color, internal_color, &diff))
{
- if (_glitz_format_diff (&_gl_packed_pixel_formats[i].pixel.masks,
- &color,
- internal_color,
- &diff))
+ if (diff < best_diff)
{
- if (diff < best_diff)
- {
- best = &_gl_packed_pixel_formats[i];
- best_diff = diff;
- }
+ best = &_gl_packed_rgb_pixel_formats[i];
+ best_diff = diff;
}
}
}
@@ -652,7 +934,6 @@ glitz_set_pixels (glitz_surface_t *dst,
src_image.data =
glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY);
- src_image.data += format->skip_lines * format->bytes_per_line;
src_image.format = format;
src_image.width = src_image.height = 1;
@@ -663,7 +944,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
+ format->xoffset,format->skip_lines,
+ 0, 0, 1, 1);
} else
dst->solid.alpha = 0xffff;
@@ -674,7 +956,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
+ format->xoffset,format->skip_lines,
+ 0, 0, 1, 1);
} else
dst->solid.red = 0;
@@ -685,7 +968,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
+ format->xoffset,format->skip_lines,
+ 0, 0, 1, 1);
} else
dst->solid.green = 0;
@@ -696,7 +980,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
+ format->xoffset,format->skip_lines,
+ 0, 0, 1, 1);
} else
dst->solid.blue = 0;
@@ -738,9 +1023,11 @@ glitz_set_pixels (glitz_surface_t *dst,
/* find direct format */
gl_format =
- _glitz_find_gl_pixel_format (format,
- color_mask,
+ _glitz_find_gl_pixel_format (format, color_mask,
dst->drawable->backend->feature_mask);
+ if (gl_format && gl_format->pixel.fourcc != dst->format->color.fourcc)
+ gl_format = NULL;
+
if (gl_format == NULL)
{
unsigned long feature_mask;
@@ -748,8 +1035,7 @@ glitz_set_pixels (glitz_surface_t *dst,
feature_mask = dst->drawable->backend->feature_mask;
transform |= GLITZ_TRANSFORM_PIXELS_MASK;
gl_format =
- _glitz_find_best_gl_pixel_format (format,
- &dst->format->color,
+ _glitz_find_best_gl_pixel_format (format, &dst->format->color,
feature_mask);
}
@@ -762,7 +1048,7 @@ glitz_set_pixels (glitz_surface_t *dst,
}
if (height > 1) {
- if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
+ if (format->scanline_order != gl_format->pixel.scanline_order)
transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK;
}
@@ -792,11 +1078,25 @@ glitz_set_pixels (glitz_surface_t *dst,
{
if (!data)
{
- int stride, bpp;
+ int size;
+
+ switch (gl_format->pixel.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ bytes_per_line = (width + 3) & -4;
+ bytes_per_pixel = 1;
+ size = bytes_per_line * height +
+ bytes_per_line * ((height + 1) >> 1);
+ break;
+ default:
+ bytes_per_line =
+ (((width * gl_format->pixel.masks.bpp) / 8) + 3) &
+ -4;
+ bytes_per_pixel = gl_format->pixel.masks.bpp / 8;
+ size = bytes_per_line * height;
+ break;
+ }
- bpp = gl_format->pixel.masks.bpp;
- stride = (((width * bpp) / 8) + 3) & -4;
- data = malloc (stride * height);
+ data = malloc (size);
if (!data)
{
glitz_surface_status_add (dst,
@@ -807,13 +1107,13 @@ glitz_set_pixels (glitz_surface_t *dst,
dst_image.data = pixels = data;
dst_image.format = &gl_format->pixel;
- ptr =
- glitz_buffer_map (buffer,
- GLITZ_BUFFER_ACCESS_READ_ONLY);
+ ptr = glitz_buffer_map (buffer,
+ GLITZ_BUFFER_ACCESS_READ_ONLY);
src_image.format = format;
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
- gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
+ bytes_per_line / bytes_per_pixel);
}
dst_image.width = box.x2 - box.x1;
@@ -822,13 +1122,13 @@ glitz_set_pixels (glitz_surface_t *dst,
src_image.width = box.x2 - box.x1;
src_image.height = box.y2 - box.y1;
- src_image.data = ptr + (format->skip_lines + box.y1 - y_dst) *
- format->bytes_per_line;
+ src_image.data = ptr;
_glitz_pixel_transform (transform,
&src_image,
&dst_image,
- format->xoffset + box.x1 - x_dst, 0,
+ format->xoffset + box.x1 - x_dst,
+ format->skip_lines + box.y1 - y_dst,
0, 0,
box.x2 - box.x1, box.y2 - box.y1);
}
@@ -840,7 +1140,14 @@ glitz_set_pixels (glitz_surface_t *dst,
GLITZ_GL_PIXEL_UNPACK_BUFFER);
bytes_per_line = format->bytes_per_line;
- bytes_per_pixel = format->masks.bpp / 8;
+ switch (format->fourcc) {
+ case GLITZ_FOURCC_YV12:
+ bytes_per_pixel = 1;
+ break;
+ default:
+ bytes_per_pixel = format->masks.bpp / 8;
+ }
+
if (bytes_per_line)
{
if ((bytes_per_line % 4) == 0)
@@ -868,12 +1175,59 @@ glitz_set_pixels (glitz_surface_t *dst,
(format->xoffset + box.x1 - x_dst) * bytes_per_pixel;
}
- gl->tex_sub_image_2d (texture->target, 0,
- texture->box.x1 + box.x1,
- texture->box.y2 - box.y2,
- box.x2 - box.x1, box.y2 - box.y1,
- gl_format->format, gl_format->type,
- pixels);
+ switch (gl_format->pixel.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ gl->tex_sub_image_2d (texture->target, 0,
+ box.x1,
+ texture->box.y2 - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1,
+ gl_format->format, gl_format->type,
+ pixels);
+
+ if ((bytes_per_line % 8) == 0)
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
+ else if ((bytes_per_line % 4) == 0)
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2);
+ else
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
+
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
+ (bytes_per_line / bytes_per_pixel) >> 1);
+
+ gl->tex_sub_image_2d (texture->target, 0,
+ (box.x1 >> 1),
+ texture->height - ((box.y2 + 1) >> 1),
+ (box.x2 - box.x1 + 1) >> 1,
+ (box.y2 - box.y1 + 1) >> 1,
+ gl_format->format, gl_format->type,
+ pixels + bytes_per_line * height);
+
+ gl->tex_sub_image_2d (texture->target, 0,
+ (texture->width >> 1) + (box.x1 >> 1),
+ texture->height - ((box.y2 + 1) >> 1),
+ (box.x2 - box.x1 + 1) >> 1,
+ (box.y2 - box.y1 + 1) >> 1,
+ gl_format->format, gl_format->type,
+ pixels + bytes_per_line * height +
+ ((bytes_per_line * height) >> 2));
+ break;
+ case GLITZ_FOURCC_YUY2:
+ gl->tex_sub_image_2d (texture->target, 0,
+ texture->box.x1 + (box.x1 >> 1),
+ texture->box.y2 - box.y2,
+ (box.x2 - box.x1 + 1) >> 1,
+ box.y2 - box.y1,
+ gl_format->format, gl_format->type,
+ pixels);
+ break;
+ default:
+ gl->tex_sub_image_2d (texture->target, 0,
+ texture->box.x1 + box.x1,
+ texture->box.y2 - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1,
+ gl_format->format, gl_format->type,
+ pixels);
+ }
glitz_surface_damage (dst, &box,
GLITZ_DAMAGE_DRAWABLE_MASK |
diff --git a/src/glitz_program.c b/src/glitz_program.c
index 7caebc1..0578674 100644
--- a/src/glitz_program.c
+++ b/src/glitz_program.c
@@ -45,24 +45,24 @@
#define EXPAND_SRC_DECL "TEMP src;"
#define EXPAND_SRC_2D_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], 2D;", \
- "DP4 color.a, color, fragment.color;", \
- "MUL result.color, src, color.a;" }
+ "DP4 color.a, color, fragment.color;", \
+ "MUL result.color, src, color.a;" }
#define EXPAND_SRC_RECT_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], RECT;", \
- "DP4 color.a, color, fragment.color;", \
- "MUL result.color, src, color.a;" }
+ "DP4 color.a, color, fragment.color;", \
+ "MUL result.color, src, color.a;" }
#define EXPAND_MASK_DECL "TEMP mask;"
-#define EXPAND_MASK_2D_IN_OP \
- { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
- "DP4 mask.a, mask, fragment.color;", \
- "MUL result.color, color, mask.a;" }
+#define EXPAND_MASK_2D_IN_OP \
+ { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
+ "DP4 mask.a, mask, fragment.color;", \
+ "MUL result.color, color, mask.a;" }
#define EXPAND_MASK_RECT_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], RECT;", \
- "DP4 mask.a, mask, fragment.color;", \
- "MUL result.color, color, mask.a;" }
+ "DP4 mask.a, mask, fragment.color;", \
+ "MUL result.color, color, mask.a;" }
#define EXPAND_IN_NA \
{ "NA", "NA", "NA" }
@@ -140,6 +140,18 @@ static const struct _glitz_program_expand_t {
};
/*
+ * perspective divide.
+ */
+static const char *_perspective_divide[] = {
+ "RCP position.w, pos.w;",
+ "MUL position, pos, position.w;", NULL
+};
+
+static const char *_no_perspective_divide[] = {
+ "MOV position, pos;", NULL
+};
+
+/*
* general convolution filter.
*/
static const char *_convolution_header[] = {
@@ -148,79 +160,73 @@ static const char *_convolution_header[] = {
"TEMP color, in, coord, position;",
/* extra declarations */
- "%s"
-
- /* perspective divide */
- "RCP position.w, pos.w;",
- "MUL position, pos, position.w;", NULL
+ "%s", NULL
};
static const char *_convolution_sample_first[] = {
"MOV coord, 0.0;",
- "ADD coord.x, position.x, p[0].x;",
- "ADD coord.y, position.y, p[0].y;",
+ "ADD coord.xy, position.xyxx, p[0].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MUL color, in, p[0].z;", NULL
};
static const char *_convolution_sample[] = {
- "ADD coord.x, position.x, p[%d].x;",
- "ADD coord.y, position.y, p[%d].y;",
+ "ADD coord.xy, position.xyxx, p[%d].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MAD color, in, p[%d].z, color;", NULL
};
-
/*
* gradient filters.
*/
static const char *_gradient_header[] = {
- "PARAM gradient = program.local[0];",
- "PARAM stops[%d] = { program.local[1..%d] };",
+ "PARAM gradient[%d] = { program.local[0..%d] };",
+ "PARAM stops[%d] = { program.local[%d..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, second_color, stop0, stop1, position;",
/* extra declarations */
- "%s",
-
- /* perspective divide */
- "RCP position.w, pos.w;",
- "MUL position, pos, position.w;", NULL
+ "%s", NULL
};
/*
* linear gradient filter.
*
- * gradient.x = start offset
- * gradient.y = 1 / length
- * gradient.z = cos (angle)
- * gradient.w = -sin (angle)
+ * gradient.x = a
+ * gradient.y = b
+ * gradient.z = offset
*/
static const char *_linear_gradient_calculations[] = {
- "MUL position.x, gradient.z, position.x;",
- "MAD position.x, gradient.w, position.y, position.x;",
- "SUB position.z, position.x, gradient.x;",
- "MUL position.z, position.z, gradient.y;", NULL
+ "MUL position.xy, gradient[0], position;",
+ "ADD position.x, position.x, position.y;",
+ "ADD position.z, position.x, gradient[0].z;", NULL
};
/*
* radial gradient filter.
*
- * gradient.x = center point X coordinate
- * gradient.y = center point Y coordinate
- * gradient.z = radius0
- * gradient.w = 1 / (radius1 - radius0)
+ * gradient[0].x = fx
+ * gradient[0].y = fy
+ * gradient[0].z = dx
+ * gradient[0].w = dy
+ *
+ * gradient[1].x = m
+ * gradient[1].y = b
+ * gradient[1].z = 4a
+ * gradient[1].w = 1 / 2a
*/
static const char *_radial_gradient_calculations[] = {
- "SUB position, position, gradient;",
- "MUL position.x, position.x, position.x;",
- "MAD position.x, position.y, position.y, position.x;",
- "RSQ position.y, position.x;",
- "RCP position.x, position.y;",
- "MUL position.x, position.x, position.x;",
- "MUL position.x, position.x, position.y;",
- "SUB position.x, position.x, gradient.z;",
- "MUL position.z, position.x, gradient.w;", NULL
+ "SUB position, position.xyxx, gradient[0].xyxx;",
+ "MUL position.zw, position.xxxy, gradient[0];",
+ "ADD position.w, position.w, position.z;",
+ "MUL position.xyz, position.xyww, position.xyww;",
+ "ADD position.x, position.x, position.y;",
+ "MAD position.z, position.x, gradient[1].z, position.z;",
+ "RSQ position.z, position.z;",
+ "RCP position.z, position.z;",
+ "SUB position.x, position.z, position.w;",
+ "MUL position.x, position.x, gradient[1].w;",
+ "MAD position.z, position.x, gradient[1].x, gradient[1].y;", NULL
};
static const char *_gradient_fill_repeat[] = {
@@ -228,15 +234,12 @@ static const char *_gradient_fill_repeat[] = {
};
static const char *_gradient_fill_reflect[] = {
- "FLR position.w, position.z;",
- "MUL position.w, position.w, 0.5;",
- "FLR position.w, position.w;",
- "MUL position.y, position.w, 2.0;",
- "FLR position.x, position.z;",
- "SUB position.y, position.x, position.y;",
- "FRC position.x, position.z;",
- "SUB position.x, position.x, position.y;",
- "ABS position.z, position.x;", NULL
+ "MUL position.z, position.z, 0.5;"
+ "FRC position.z, position.z;"
+ "MUL position.z, position.z, 2.0;"
+ "SUB position.z, 1.0, position.z;"
+ "ABS position.z, position.z;"
+ "SUB position.z, 1.0, position.z;", NULL
};
static const char *_gradient_init_stops[] = {
@@ -263,7 +266,37 @@ static const char *_gradient_fetch_and_interpolate[] = {
"MUL_SAT position.z, position.z, stop0.w;",
/* linear interpolation */
- "LRP color, position.z, second_color, color;", NULL
+ "LRP color, position.z, second_color, color;",
+
+ /* multiply alpha */
+ "MUL color.rgb, color.rgba, color.a;", NULL
+};
+
+/*
+ * color conversion filters
+ */
+static const char *_colorspace_yv12_header[] = {
+ "PARAM offset = program.local[0];",
+ "PARAM minmax = program.local[1];",
+ "ATTRIB pos = fragment.texcoord[%s];",
+ "TEMP color, tmp, position;",
+
+ /* extra declarations */
+ "%s", NULL
+};
+
+static const char *_colorspace_yv12[] = {
+ "MAX position, position, minmax;",
+ "MIN position, position, minmax.zwww;",
+ "TEX color, position, texture[%s], %s;",
+ "MAD position, position, .5, offset.xyww;",
+ "TEX tmp.x, position, texture[%s], %s;",
+ "MAD color, color, 1.164, -0.073;", /* -1.164 * 16 / 255 */
+ "ADD position.x, position.x, offset.z;",
+ "TEX tmp.y, position, texture[%s], %s;",
+ "SUB tmp, tmp, { .5, .5 };",
+ "MAD color.xyz, { 1.596, -.813, 0 }, tmp.xxxw, color;",
+ "MAD color.xyz, { 0, -.391, 2.018 }, tmp.yyyw, color;", NULL
};
static struct _glitz_program_query {
@@ -276,9 +309,9 @@ static struct _glitz_program_query {
{ GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_PARAMETERS,
- GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 },
+ GLITZ_GL_MAX_PROGRAM_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_PARAMETERS,
- GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 },
+ GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS,
@@ -321,10 +354,10 @@ _glitz_program_under_limits (glitz_gl_proc_address_list_t *gl)
static glitz_gl_int_t
_glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
- char *program_string,
- int n_parameters)
+ char *string,
+ int n_parameters)
{
- glitz_gl_int_t error, pid = -1;
+ glitz_gl_int_t error = 0, pid = -1;
glitz_gl_uint_t program;
/* clear error flags */
@@ -334,11 +367,9 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program);
gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_FORMAT_ASCII,
- strlen (program_string),
- program_string);
+ strlen (string), string);
if (gl->get_error () == GLITZ_GL_NO_ERROR) {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
-
if (error == -1) {
glitz_gl_int_t value;
@@ -358,6 +389,14 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
}
}
+#ifdef DEBUG
+ else {
+ gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
+ }
+ if (error != -1)
+ fprintf (stderr, "fp error at pos %d beginning with '%.40s'\n",
+ error, string+error);
+#endif
if (pid == -1) {
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0);
@@ -368,7 +407,8 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
static void
-_string_array_to_char_array (char *dst, const char *src[])
+_string_array_to_char_array (char *dst,
+ const char *src[])
{
int i, n;
@@ -387,17 +427,26 @@ _string_array_to_char_array (char *dst, const char *src[])
#define GRADIENT_BASE_SIZE 2048
#define GRADIENT_STOP_SIZE 256
+#define COLORSPACE_BASE_SIZE 2048
+
static glitz_gl_uint_t
_glitz_create_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id,
+ int p_divide,
const glitz_program_expand_t *expand)
{
- char buffer[1024], *program = NULL, *tex, *p = NULL;
- char *texture_type, *extra_declarations;
+ char buffer[1024], *program = NULL, *tex, *p = NULL;
+ char *texture_type, *extra_declarations;
+ const char **pos_to_position;
const glitz_in_op_t *in;
- glitz_gl_uint_t fp;
- int i;
+ glitz_gl_uint_t fp;
+ int i;
+
+ if (p_divide)
+ pos_to_position = _perspective_divide;
+ else
+ pos_to_position = _no_perspective_divide;
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
@@ -438,12 +487,15 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
_string_array_to_char_array (buffer, _convolution_header);
p += sprintf (p, buffer, id, id - 1, tex, extra_declarations);
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer, _convolution_sample_first);
p += sprintf (p, buffer, tex, texture_type);
_string_array_to_char_array (buffer, _convolution_sample);
for (i = 1; i < id; i++)
- p += sprintf (p, buffer, i, i, tex, texture_type, i);
+ p += sprintf (p, buffer, i, tex, texture_type, i);
break;
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
@@ -465,17 +517,27 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _gradient_header);
- p += sprintf (p, buffer, id, id, tex, extra_declarations);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
case GLITZ_FP_LINEAR_GRADIENT_NEAREST:
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
+ p += sprintf (p, buffer, 1, 0, id, 1, id, tex, extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer,
_linear_gradient_calculations);
break;
default:
+ p += sprintf (p, buffer, 2, 1, id, 2, id + 1, tex,
+ extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer,
_radial_gradient_calculations);
break;
@@ -514,6 +576,25 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
id++;
break;
+ case GLITZ_FP_COLORSPACE_YV12:
+ program = malloc (COLORSPACE_BASE_SIZE);
+ if (program == NULL)
+ return 0;
+
+ p = program;
+
+ p += sprintf (p, "!!ARBfp1.0");
+
+ _string_array_to_char_array (buffer, _colorspace_yv12_header);
+ p += sprintf (p, buffer, tex, extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
+ _string_array_to_char_array (buffer, _colorspace_yv12);
+ p += sprintf (p, buffer, tex, texture_type, tex, texture_type,
+ tex, texture_type);
+ break;
default:
return 0;
}
@@ -525,8 +606,12 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
if (op->per_component)
p += sprintf (p, "%s", in->dot_product);
p += sprintf (p, "%s", in->mult);
+
sprintf (p, "END");
+#ifdef DEBUG
+ fprintf (stderr, "***** fp %d:\n%s\n\n", id, program);
+#endif
fp = _glitz_compile_arb_fragment_program (op->gl, program, id);
free (program);
@@ -545,22 +630,24 @@ glitz_program_map_fini (glitz_gl_proc_address_list_t *gl,
glitz_program_map_t *map)
{
glitz_gl_uint_t program;
- int i, j, k, x, y;
+ int i, j, k, x, y, z;
for (i = 0; i < GLITZ_COMBINE_TYPES; i++) {
for (j = 0; j < GLITZ_FP_TYPES; j++) {
for (x = 0; x < GLITZ_TEXTURE_LAST; x++) {
for (y = 0; y < GLITZ_TEXTURE_LAST; y++) {
- glitz_program_t *p = &map->filters[i][j].fp[x][y];
-
- if (p->name) {
- for (k = 0; k < p->size; k++)
- if (p->name[k] > 0) {
- program = p->name[k];
- gl->delete_programs (1, &program);
- }
-
- free (p->name);
+ for (z = 0; z < 2; z++) {
+ glitz_program_t *p = &map->filters[i][j].fp[x][y][z];
+
+ if (p->name) {
+ for (k = 0; k < p->size; k++)
+ if (p->name[k] > 0) {
+ program = p->name[k];
+ gl->delete_programs (1, &program);
+ }
+
+ free (p->name);
+ }
}
}
}
@@ -583,12 +670,30 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
int id)
{
glitz_program_map_t *map;
- glitz_program_t *program;
- int t0 = TEXTURE_INDEX (op->src);
- int t1 = TEXTURE_INDEX (op->mask);
+ glitz_program_t *program;
+ int t0 = TEXTURE_INDEX (op->src);
+ int t1 = TEXTURE_INDEX (op->mask);
+ int p_divide = 1;
+
+ switch (op->type) {
+ case GLITZ_COMBINE_TYPE_ARGBF:
+ case GLITZ_COMBINE_TYPE_ARGBF_SOLID:
+ case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC:
+ case GLITZ_COMBINE_TYPE_ARGBF_ARGB:
+ case GLITZ_COMBINE_TYPE_ARGBF_ARGBC:
+ if (!SURFACE_PROJECTIVE_TRANSFORM (op->src))
+ p_divide = 0;
+ break;
+ case GLITZ_COMBINE_TYPE_ARGB_ARGBF:
+ case GLITZ_COMBINE_TYPE_SOLID_ARGBF:
+ if (!SURFACE_PROJECTIVE_TRANSFORM (op->mask))
+ p_divide = 0;
+ default:
+ break;
+ }
map = op->dst->drawable->backend->program_map;
- program = &map->filters[op->type][fp_type].fp[t0][t1];
+ program = &map->filters[op->type][fp_type].fp[t0][t1][p_divide];
if (program->size < id) {
int old_size;
@@ -609,7 +714,7 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT);
program->name[id - 1] =
- _glitz_create_fragment_program (op, fp_type, id,
+ _glitz_create_fragment_program (op, fp_type, id, p_divide,
_program_expand_map[t0][t1]);
glitz_surface_pop_current (op->dst);
diff --git a/src/glitz_rect.c b/src/glitz_rect.c
index d9f5c04..22bf11e 100644
--- a/src/glitz_rect.c
+++ b/src/glitz_rect.c
@@ -144,6 +144,7 @@ glitz_set_rectangles (glitz_surface_t *dst,
else
{
static glitz_pixel_format_t pf = {
+ GLITZ_FOURCC_RGB,
{
32,
0xff000000,
diff --git a/src/glitz_surface.c b/src/glitz_surface.c
index 23d30bb..7e1cb03 100644
--- a/src/glitz_surface.c
+++ b/src/glitz_surface.c
@@ -90,8 +90,11 @@ glitz_surface_create (glitz_drawable_t *drawable,
glitz_texture_init (&surface->texture, width, height,
drawable->backend->texture_formats[format->id],
+ surface->format->color.fourcc,
feature_mask, unnormalized);
+ glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0);
+
if (width > 64 || height > 64)
{
glitz_surface_push_current (surface, GLITZ_CONTEXT_CURRENT);
@@ -490,7 +493,7 @@ glitz_surface_attach (glitz_surface_t *surface,
if (surface == drawable->front)
return;
- if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
+ if (surface->format->color.fourcc != GLITZ_FOURCC_RGB)
drawable = NULL;
if (drawable)
@@ -510,7 +513,7 @@ glitz_surface_attach (glitz_surface_t *surface,
if (surface == drawable->back)
return;
- if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
+ if (surface->format->color.fourcc != GLITZ_FOURCC_RGB)
drawable = NULL;
if (drawable)
@@ -847,13 +850,25 @@ glitz_surface_set_filter (glitz_surface_t *surface,
} else {
switch (filter) {
case GLITZ_FILTER_NEAREST:
- surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ switch (surface->format->color.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ break;
+ default:
+ surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ }
surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK;
break;
case GLITZ_FILTER_BILINEAR:
- surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ switch (surface->format->color.fourcc) {
+ case GLITZ_FOURCC_YV12:
+ surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ break;
+ default:
+ surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
+ }
surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK;
diff --git a/src/glitz_texture.c b/src/glitz_texture.c
index 53737e3..b372d83 100644
--- a/src/glitz_texture.c
+++ b/src/glitz_texture.c
@@ -34,6 +34,7 @@ glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
+ glitz_fourcc_t fourcc,
unsigned long feature_mask,
glitz_bool_t unnormalized)
{
@@ -44,24 +45,48 @@ glitz_texture_init (glitz_texture_t *texture,
texture->param.border_color.alpha = 0;
texture->format = texture_format;
- texture->name = 0;
+ texture->fourcc = fourcc;
+ texture->name = 0;
- if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)
- {
+ switch (fourcc) {
+ case GLITZ_FOURCC_YV12:
+ /* U and V plane added below */
+ texture->box.x1 = texture->box.y1 = 0;
+ texture->box.x2 = width;
+ texture->box.y2 = height;
+ texture->width = (width + 1) & ~1;
+ texture->height = (height + 1) & ~1;
+ texture->height += texture->height >> 1;
+ texture->flags = GLITZ_TEXTURE_FLAG_PADABLE_MASK;
+ break;
+ case GLITZ_FOURCC_YUY2:
+ /* 1 RGBA texel for 2 YUY2 pixels */
texture->box.x1 = texture->box.y1 = 0;
- texture->box.x2 = texture->width = width;
+ texture->box.x2 = texture->width = width >> 1;
texture->box.y2 = texture->height = height;
- texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
+ texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK |
+ GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
GLITZ_TEXTURE_FLAG_PADABLE_MASK;
- }
- else
- {
- texture->box.x1 = texture->box.y1 = 1;
- texture->box.x2 = width + 1;
- texture->box.y2 = height + 1;
- texture->width = width + 2;
- texture->height = height + 2;
- texture->flags = 0;
+ break;
+ default:
+ if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)
+ {
+ texture->box.x1 = texture->box.y1 = 0;
+ texture->box.x2 = texture->width = width;
+ texture->box.y2 = texture->height = height;
+ texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK |
+ GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
+ GLITZ_TEXTURE_FLAG_PADABLE_MASK;
+ }
+ else
+ {
+ texture->box.x1 = texture->box.y1 = 1;
+ texture->box.x2 = width + 1;
+ texture->box.y2 = height + 1;
+ texture->width = width + 2;
+ texture->height = height + 2;
+ texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK;
+ }
}
if (!unnormalized &&
@@ -154,8 +179,10 @@ glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
glitz_texture_bind (gl, texture);
- if (texture->box.x2 != texture->width ||
- texture->box.y2 != texture->height) {
+ if (TEXTURE_CLAMPABLE (texture) &&
+ (texture->box.x2 != texture->width ||
+ texture->box.y2 != texture->height))
+ {
data = malloc (texture->width * texture->height);
if (data)
memset (data, 0, texture->width * texture->height);
@@ -276,6 +303,7 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
if (flags & GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK)
{
plane.v[0] = plane.v[2] = 0.0f;
+
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[1] = 1.0f;
@@ -284,7 +312,6 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
else
{
plane.v[1] = -texture->texcoord_height_unit;
-
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) *
texture->texcoord_height_unit;
diff --git a/src/glitz_util.c b/src/glitz_util.c
index 3a2bb6a..4f58d7c 100644
--- a/src/glitz_util.c
+++ b/src/glitz_util.c
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
static glitz_extension_map gl_extensions[] = {
{ 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
@@ -108,14 +109,36 @@ glitz_extensions_query (glitz_gl_float_t version,
return mask;
}
+static glitz_gl_float_t
+_glitz_gl_version_string_to_float (const char *gl_version_string)
+{
+ glitz_gl_float_t version = 0.0f;
+ int i;
+
+ for (i = 0; isdigit (gl_version_string[i]); i++)
+ version = version * 10.0f + (gl_version_string[i] - 48);
+
+ if (gl_version_string[i++] != '.')
+ return 0.0f;
+
+ version = version * 10.0f + (gl_version_string[i] - 48);
+
+ return (version + 0.1f) / 10.0f;
+}
+
static glitz_status_t
_glitz_query_gl_extensions (glitz_gl_proc_address_list_t *gl,
glitz_gl_float_t *gl_version,
unsigned long *feature_mask)
{
const char *gl_extensions_string;
+ const char *gl_version_string;
+
+ gl_version_string = (const char *) gl->get_string (GLITZ_GL_VERSION);
+ if (!gl_version_string)
+ return GLITZ_STATUS_NOT_SUPPORTED;
- *gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION));
+ *gl_version = _glitz_gl_version_string_to_float (gl_version_string);
if (*gl_version < 1.2f)
return GLITZ_STATUS_NOT_SUPPORTED;
@@ -315,7 +338,8 @@ glitz_backend_init (glitz_backend_t *backend,
glitz_create_surface_formats (backend->gl,
&backend->formats,
&backend->texture_formats,
- &backend->n_formats);
+ &backend->n_formats,
+ backend->feature_mask);
_glitz_add_drawable_formats (backend->gl,
backend->feature_mask,
&backend->drawable_formats,
diff --git a/src/glitzint.h b/src/glitzint.h
index ef149e9..8f92d09 100644
--- a/src/glitzint.h
+++ b/src/glitzint.h
@@ -253,7 +253,9 @@ typedef int glitz_combine_type_t;
#define GLITZ_FP_RADIAL_GRADIENT_NEAREST 6
#define GLITZ_FP_RADIAL_GRADIENT_REPEAT 7
#define GLITZ_FP_RADIAL_GRADIENT_REFLECT 8
-#define GLITZ_FP_TYPES 9
+#define GLITZ_FP_COLORSPACE_YV12 9
+#define GLITZ_FP_UNSUPPORTED 10
+#define GLITZ_FP_TYPES 11
typedef struct _glitz_program_t {
glitz_gl_int_t *name;
@@ -261,7 +263,7 @@ typedef struct _glitz_program_t {
} glitz_program_t;
typedef struct _glitz_filter_map_t {
- glitz_program_t fp[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST];
+ glitz_program_t fp[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST][2];
} glitz_filter_map_t;
typedef struct _glitz_program_map_t {
@@ -453,13 +455,17 @@ typedef struct _glitz_vec4_t {
} glitz_vec4_t;
#define GLITZ_TEXTURE_FLAG_ALLOCATED_MASK (1L << 0)
-#define GLITZ_TEXTURE_FLAG_REPEATABLE_MASK (1L << 1)
-#define GLITZ_TEXTURE_FLAG_PADABLE_MASK (1L << 2)
-#define GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK (1L << 3)
+#define GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK (1L << 1)
+#define GLITZ_TEXTURE_FLAG_REPEATABLE_MASK (1L << 2)
+#define GLITZ_TEXTURE_FLAG_PADABLE_MASK (1L << 3)
+#define GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK (1L << 4)
#define TEXTURE_ALLOCATED(texture) \
((texture)->flags & GLITZ_TEXTURE_FLAG_ALLOCATED_MASK)
+#define TEXTURE_CLAMPABLE(texture) \
+ ((texture)->flags & GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK)
+
#define TEXTURE_REPEATABLE(texture) \
((texture)->flags & GLITZ_TEXTURE_FLAG_REPEATABLE_MASK)
@@ -479,17 +485,19 @@ typedef struct _glitz_texture {
glitz_gl_uint_t name;
glitz_gl_enum_t target;
glitz_gl_int_t format;
+ glitz_fourcc_t fourcc;
unsigned long flags;
glitz_texture_parameters_t param;
- int width;
- int height;
+ int width;
+ int height;
- glitz_box_t box;
+ glitz_box_t box;
+ glitz_box_t box_internal;
- glitz_float_t texcoord_width_unit;
- glitz_float_t texcoord_height_unit;
+ glitz_float_t texcoord_width_unit;
+ glitz_float_t texcoord_height_unit;
} glitz_texture_t;
struct _glitz_texture_object {
@@ -739,7 +747,8 @@ void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
- int *n_formats);
+ int *n_formats,
+ unsigned long features);
extern void __internal_linkage
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
@@ -764,6 +773,7 @@ glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
+ glitz_fourcc_t fourcc,
unsigned long feature_mask,
glitz_bool_t unnormalized);
diff --git a/src/glx/glitz_glx_drawable.c b/src/glx/glitz_glx_drawable.c
index 7c80925..ab94294 100644
--- a/src/glx/glitz_glx_drawable.c
+++ b/src/glx/glitz_glx_drawable.c
@@ -216,6 +216,7 @@ glitz_glx_destroy (void *abstract_drawable)
GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (drawable->base.backend->gl,
&drawable->screen_info->program_map);
+ glitz_program_map_init (&drawable->screen_info->program_map);
glitz_glx_pop_current (abstract_drawable);
}
diff --git a/src/glx/glitz_glx_format.c b/src/glx/glitz_glx_format.c
index 0e18e79..8f24437 100644
--- a/src/glx/glitz_glx_format.c
+++ b/src/glx/glitz_glx_format.c
@@ -45,6 +45,9 @@ _glitz_glx_format_compare (const void *elem1,
for (; i < 2; i++)
{
+ if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
+ score[i] -= 1000;
+
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
@@ -119,8 +122,9 @@ _glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
&visual_templ, &num_visuals);
/* No pbuffers without fbconfigs */
- format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
- format.d.id = 0;
+ format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
+ format.d.id = 0;
+ format.d.color.fourcc = GLITZ_FOURCC_RGB;
for (i = 0; i < num_visuals; i++)
{
@@ -243,7 +247,8 @@ _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info)
if (value & GLX_PBUFFER_BIT)
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
- format.d.id = 0;
+ format.d.id = 0;
+ format.d.color.fourcc = GLITZ_FOURCC_RGB;
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID,
&value);
diff --git a/src/wgl/glitz_wgl_format.c b/src/wgl/glitz_wgl_format.c
index b06da69..90332e1 100644
--- a/src/wgl/glitz_wgl_format.c
+++ b/src/wgl/glitz_wgl_format.c
@@ -51,6 +51,9 @@ _glitz_wgl_format_compare (const void *elem1,
for (; i < 2; i++)
{
+ if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
+ score[i] -= 1000;
+
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)