From 60bbdc23f8b64ab4410818f679531909739653b1 Mon Sep 17 00:00:00 2001 From: David Reveman Date: Tue, 29 Nov 2005 22:41:26 +0000 Subject: Add YUV surfaces --- src/agl/glitz_agl_format.c | 4 + src/egl/glitz_egl_config.c | 6 +- src/egl/glitz_egl_surface.c | 1 + src/glitz.h | 30 +- src/glitz_compose.c | 9 +- src/glitz_context.c | 7 + src/glitz_filter.c | 213 +++++++++----- src/glitz_format.c | 98 ++++--- src/glitz_gl.h | 37 +-- src/glitz_pixel.c | 662 +++++++++++++++++++++++++++++++++---------- src/glitz_program.c | 283 ++++++++++++------ src/glitz_rect.c | 1 + src/glitz_surface.c | 23 +- src/glitz_texture.c | 61 ++-- src/glitz_util.c | 28 +- src/glitzint.h | 32 ++- src/glx/glitz_glx_drawable.c | 1 + src/glx/glitz_glx_format.c | 11 +- src/wgl/glitz_wgl_format.c | 3 + 19 files changed, 1089 insertions(+), 421 deletions(-) (limited to 'src') 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, ¶ms, &n_params); _glitz_filter_params_set (&dn, 3.0f, ¶ms, &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, ¶ms, &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, ¶ms, &n_params); _glitz_filter_params_set (&start_y, 0.0f, ¶ms, &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, ¶ms, &n_params); - _glitz_filter_params_set (&vecs->v[1], 0.5f, ¶ms, &n_params); + _glitz_filter_params_set (&x0, 0.5f, ¶ms, &n_params); + _glitz_filter_params_set (&y0, 0.5f, ¶ms, &n_params); _glitz_filter_params_set (&r0, 0.0f, ¶ms, &n_params); - _glitz_filter_params_set (&r1, 0.5f, ¶ms, &n_params); + + _glitz_filter_params_set (&x1, x0, ¶ms, &n_params); + _glitz_filter_params_set (&y1, y0, ¶ms, &n_params); + _glitz_filter_params_set (&r1, r0 + 0.5f, ¶ms, &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 -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" } @@ -139,6 +139,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. */ @@ -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 #include +#include 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) -- cgit v1.2.3