[cairo-commit] glitz/src glitz.h, 1.35, 1.36 glitz_compose.c, 1.14, 1.15 glitz_context.c, 1.3, 1.4 glitz_filter.c, 1.10, 1.11 glitz_format.c, 1.11, 1.12 glitz_gl.h, 1.17, 1.18 glitz_pixel.c, 1.21, 1.22 glitz_program.c, 1.18, 1.19 glitz_rect.c, 1.18, 1.19 glitz_surface.c, 1.31, 1.32 glitz_texture.c, 1.20, 1.21 glitz_util.c, 1.15, 1.16 glitzint.h, 1.37, 1.38

David Reveman commit at pdx.freedesktop.org
Tue Nov 29 14:41:29 PST 2005


Committed by: davidr

Update of /cvs/cairo/glitz/src
In directory gabe:/tmp/cvs-serv1190/src

Modified Files:
	glitz.h glitz_compose.c glitz_context.c glitz_filter.c 
	glitz_format.c glitz_gl.h glitz_pixel.c glitz_program.c 
	glitz_rect.c glitz_surface.c glitz_texture.c glitz_util.c 
	glitzint.h 
Log Message:
Add YUV surfaces

Index: glitz.h
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- glitz.h	9 Nov 2005 12:32:24 -0000	1.35
+++ glitz.h	29 Nov 2005 22:41:26 -0000	1.36
@@ -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 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 @@
   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 @@
 } glitz_pixel_masks_t;
 
 typedef struct _glitz_pixel_format {
+  glitz_fourcc_t               fourcc;
   glitz_pixel_masks_t          masks;
   int                          xoffset;
   int                          skip_lines;

Index: glitz_compose.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_compose.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- glitz_compose.c	14 Sep 2005 15:57:16 -0000	1.14
+++ glitz_compose.c	29 Nov 2005 22:41:26 -0000	1.15
@@ -347,7 +347,7 @@
 
     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 @@
      ((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)      \
+	   )                                                            \
 	  )                                                             \
 	 )                                                              \
 	)

Index: glitz_context.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_context.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- glitz_context.c	14 Sep 2005 15:57:16 -0000	1.3
+++ glitz_context.c	29 Nov 2005 22:41:26 -0000	1.4
@@ -110,6 +110,11 @@
 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_DAMAGE_SOLID_MASK);
     }
 
+    context->lose_current = lose_current;
+
     drawable->backend->make_current (drawable, context);
 }
 slim_hidden_def(glitz_context_make_current);

Index: glitz_filter.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_filter.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- glitz_filter.c	14 Sep 2005 15:57:16 -0000	1.10
+++ glitz_filter.c	29 Nov 2005 22:41:26 -0000	1.11
@@ -107,6 +107,10 @@
 
 	_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_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 @@
 	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 @@
 	    dh = stop_x - start_x;
 	    dv = stop_y - start_y;
 
-	    length = sqrtf (dh * dh + dv * dv);
-
-	    angle = -atan2f (dv, dh);
+	    length = dh * dh + dv * dv;
 
-	    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 @@
 	break;
     case GLITZ_FILTER_BILINEAR:
     case GLITZ_FILTER_NEAREST:
-	if (surface->filter_params)
-	    free (surface->filter_params);
+	switch (surface->format->color.fourcc) {
+	case GLITZ_FOURCC_YV12:
+	    if (_glitz_filter_params_ensure (surface, 2))
+		return GLITZ_STATUS_NO_MEMORY;
 
-	surface->filter_params = NULL;
+	    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;
+	}
 	break;
     }
 
@@ -325,6 +373,9 @@
 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 @@
 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 @@
 
 	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 @@
 	    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 @@
     } 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;
     }
 }

Index: glitz_format.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_format.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- glitz_format.c	14 Sep 2005 15:57:16 -0000	1.11
+++ glitz_format.c	29 Nov 2005 22:41:26 -0000	1.12
@@ -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 @@
 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 @@
 	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 @@
 				   _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 @@
     }
 }
 
-/* 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_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 @@
     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 @@
 	    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 @@
 	    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_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 @@
 	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;
     }

Index: glitz_gl.h
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_gl.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- glitz_gl.h	9 Nov 2005 12:32:24 -0000	1.17
+++ glitz_gl.h	29 Nov 2005 22:41:27 -0000	1.18
@@ -202,24 +202,25 @@
 #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

Index: glitz_pixel.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_pixel.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- glitz_pixel.c	14 Sep 2005 15:57:16 -0000	1.21
+++ glitz_pixel.c	29 Nov 2005 22:41:27 -0000	1.22
@@ -37,23 +37,10 @@
     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 @@
 	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 @@
     }
 };
 
+#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_pixel_format_t _solid_format[] = {
     {
+	GLITZ_FOURCC_RGB,
 	{
 	    16,
 	    0x0000ffff,
@@ -116,6 +148,7 @@
 	0, 0, 0,
 	GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
     }, {
+	GLITZ_FOURCC_RGB,
 	{
 	    16,
 	    0x00000000,
@@ -126,6 +159,7 @@
 	0, 0, 0,
 	GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
     }, {
+	GLITZ_FOURCC_RGB,
 	{
 	    16,
 	    0x00000000,
@@ -136,6 +170,7 @@
 	0, 0, 0,
 	GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
     }, {
+	GLITZ_FOURCC_RGB,
 	{
 	    16,
 	    0x00000000,
@@ -153,19 +188,19 @@
 } 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 @@
     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 (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 @@
 			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;
+    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;
+    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 @@
 	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 @@
 	}
 	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 @@
 			     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 @@
 }
 
 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_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;
 
-    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);
+    switch (internal_color->fourcc) {
+    case GLITZ_FOURCC_YV12:
+    case GLITZ_FOURCC_YUY2:
+	for (i = 0; i < N_YUV_FORMATS; i++)
+	{
+	    glitz_fourcc_t fourcc;
 
-    n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
-    for (i = 0; best_diff > 0 && i < n_formats; i++)
+	    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;
+    }
+
+    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 @@
 
 		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_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_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_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_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 @@
 
     /* 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 @@
 	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 @@
     }
 
     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 @@
 	    {
 		if (!data)
 		{
-		    int stride, bpp;
+		    int size;
 
-		    bpp = gl_format->pixel.masks.bpp;
-		    stride = (((width * bpp) / 8) + 3) & -4;
-		    data = malloc (stride * height);
+		    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;
+		    }
+
+		    data = malloc (size);
 		    if (!data)
 		    {
 			glitz_surface_status_add (dst,
@@ -807,13 +1107,13 @@
 		    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 @@
 		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_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 @@
 		    (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 |

Index: glitz_program.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_program.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- glitz_program.c	14 Sep 2005 15:57:16 -0000	1.18
+++ glitz_program.c	29 Nov 2005 22:41:27 -0000	1.19
@@ -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 @@
 };
 
 /*
+ * 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 @@
     "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_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 @@
     "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 @@
     { 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 @@
 
 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 @@
     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 @@
 	    }
 	}
     }
+#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 @@
 }
 
 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 @@
 #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 @@
 	_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 @@
 	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 @@
 
 	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 @@
     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_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];
+		    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);
-			    }
+			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);
+			    free (p->name);
+			}
 		    }
 		}
 	    }
@@ -583,12 +670,30 @@
 			    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_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);

Index: glitz_rect.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_rect.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- glitz_rect.c	14 Sep 2005 15:57:16 -0000	1.18
+++ glitz_rect.c	29 Nov 2005 22:41:27 -0000	1.19
@@ -144,6 +144,7 @@
     else
     {
 	static glitz_pixel_format_t pf = {
+	    GLITZ_FOURCC_RGB,
 	    {
 		32,
 		0xff000000,

Index: glitz_surface.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_surface.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- glitz_surface.c	14 Sep 2005 15:57:16 -0000	1.31
+++ glitz_surface.c	29 Nov 2005 22:41:27 -0000	1.32
@@ -90,8 +90,11 @@
 
     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 @@
 	    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 @@
 	    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 @@
     } 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;

Index: glitz_texture.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_texture.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- glitz_texture.c	14 Sep 2005 15:57:16 -0000	1.20
+++ glitz_texture.c	29 Nov 2005 22:41:27 -0000	1.21
@@ -34,6 +34,7 @@
 		    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 @@
 	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 = texture->width = width;
+	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 >> 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_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 @@
     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 @@
 	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;

Index: glitz_util.c
===================================================================
RCS file: /cvs/cairo/glitz/src/glitz_util.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- glitz_util.c	14 Sep 2005 15:57:16 -0000	1.15
+++ glitz_util.c	29 Nov 2005 22:41:27 -0000	1.16
@@ -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 @@
     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 = atof ((const char *) gl->get_string (GLITZ_GL_VERSION));
+    gl_version_string = (const char *) gl->get_string (GLITZ_GL_VERSION);
+    if (!gl_version_string)
+	return GLITZ_STATUS_NOT_SUPPORTED;
+
+    *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_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,

Index: glitzint.h
===================================================================
RCS file: /cvs/cairo/glitz/src/glitzint.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- glitzint.h	9 Nov 2005 12:32:24 -0000	1.37
+++ glitzint.h	29 Nov 2005 22:41:27 -0000	1.38
@@ -253,7 +253,9 @@
 #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 @@
 } 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 @@
 } 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 @@
   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 @@
 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 @@
 		    int             width,
 		    int             height,
 		    glitz_gl_int_t  texture_format,
+		    glitz_fourcc_t  fourcc,
 		    unsigned long   feature_mask,
 		    glitz_bool_t    unnormalized);
 



More information about the cairo-commit mailing list