diff options
-rw-r--r-- | ChangeLog | 118 | ||||
-rw-r--r-- | README | 22 | ||||
-rw-r--r-- | TODO | 12 | ||||
-rw-r--r-- | configure.in | 30 | ||||
-rw-r--r-- | src/glitz.c | 1028 | ||||
-rw-r--r-- | src/glitz.h | 99 | ||||
-rw-r--r-- | src/glitz_agl_context.c | 8 | ||||
-rw-r--r-- | src/glitz_agl_extension.c | 27 | ||||
-rw-r--r-- | src/glitz_agl_info.c | 60 | ||||
-rw-r--r-- | src/glitz_agl_surface.c | 4 | ||||
-rw-r--r-- | src/glitz_aglint.h | 23 | ||||
-rw-r--r-- | src/glitz_color_range.c | 108 | ||||
-rw-r--r-- | src/glitz_format.c | 16 | ||||
-rw-r--r-- | src/glitz_gl.h | 155 | ||||
-rw-r--r-- | src/glitz_glx_context.c | 76 | ||||
-rw-r--r-- | src/glitz_glx_extension.c | 27 | ||||
-rw-r--r-- | src/glitz_glx_info.c | 71 | ||||
-rw-r--r-- | src/glitz_glx_surface.c | 74 | ||||
-rw-r--r-- | src/glitz_glxext.h | 6 | ||||
-rw-r--r-- | src/glitz_glxint.h | 19 | ||||
-rw-r--r-- | src/glitz_pixel.c | 411 | ||||
-rw-r--r-- | src/glitz_program.c | 1106 | ||||
-rw-r--r-- | src/glitz_programmatic.c | 113 | ||||
-rw-r--r-- | src/glitz_render.c | 819 | ||||
-rw-r--r-- | src/glitz_surface.c | 39 | ||||
-rw-r--r-- | src/glitz_texture.c | 4 | ||||
-rw-r--r-- | src/glitzint.h | 321 |
27 files changed, 2835 insertions, 1961 deletions
@@ -1,3 +1,121 @@ +2004-07-20 David Reveman <c99drn@cs.umu.se> + + * src/glitzint.h: Added glTexEnvfv, glColor4d and pixel buffer + functions to glitz_gl_proc_address_list_t. + Moved some stuff into glitz_color_range.c. + Added new glitz_render_op_t infrastructure. + Added component-alpha support. + Fixed some macros. + Added reference counting to glitz_surface_t. + programs -> program_map. + SHORT_MODULATE -> SHORT_MULT. + + * src/glitz_surface.c (glitz_surface_init): programs -> program_map. + Added reference counting to surfaces. + Added glitz_surface_set_component_alpha. + + * src/glitz_render.c: Added new glitz_render_op_t infrastructure. + This is a major improvement to the old mess. This new infrastructure + scales very well, is much easier to understand and is more efficient. + + * src/glitz_programmatic.c: GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE -> + GLITZ_PROGRAMMATIC_SURFACE_TYPE_LINEAR and + GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE -> + GLITZ_PROGRAMMATIC_SURFACE_TYPE_RADIAL. + (_glitz_programmatic_surface_create): Use MAXSHORT for static surface + size. + Removed glitz_programmatic_surface_setup. + Removed glitz_programmatic_surface_bind as that code should now be + in glitz_render.c. + + * src/glitz_program.c: Cleaned up and moved some that should be in + glitz_render.c. Added support for component-alpha. + + * src/glitz_pixel.c: Added new pixel buffer interface, which + allows for asynchronous pixel transfers and access to + high-performance memory. Modified pixel transfer functions + to use the new pixel buffer interface. + + * src/glitz_glxint.h: Added + GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK, + GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK, + GLITZ_GLX_FEATURE_PIXEL_BUFFER_OBJECT_MASK; + programs -> program_map. + + * src/glitz_glx_surface.c (_glitz_glx_set_features): Better check + for multi-texturing and check pixel buffer object extension + support. + programs -> program_map. + + * src/glitz_glx_info.c: Added glTexEnvfv, glColor4d and pixel buffer + functions to _glitz_glx_gl_proc_address. + (glitz_glx_thread_info_get): Fixed thread specific data + allocation. + (glitz_glx_display_destroy): Fixed memory leak. + (glitz_glx_screen_info_get): Use glitz_program_map_init to + initialize program map. + (glitz_glx_screen_destroy): Use glitz_program_map_fini to + clean up program map. + + * src/glitz_glx_extension.c: Check for GL_ARB_texture_env_combine, + GL_ARB_texture_env_dot3 and GL_EXT_pixel_buffer_object. + + * src/glitz_glx_context.c (glitz_glx_context_proc_address_lookup): + Lookup pixel buffer object function pointers. + + * src/glitz_gl.h: Added a bunch of new tokens and function + declarations. + + * src/glitz_format.c: OpenGL GL_ALPHA formats are now used for + alpha textures instead of GL_INTENSITY. + + * src/glitz_color_range.c: Moved some stuff from glitzint.h to this + file and use the new pixel buffer interface for asynchronous + color range data transfers. + + * src/glitz_aglint.h: Added + GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK, + GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK, + GLITZ_AGL_FEATURE_PIXEL_BUFFER_OBJECT_MASK. + programs -> program_map. + + * src/glitz_agl_surface.c: programs -> program_map. + + * src/glitz_agl_info.c: Added glTexEnvfv, glColor4d and pixel buffer + functions to _glitz_agl_gl_proc_address. + (glitz_agl_thread_info_get): Fixed thread specific data + allocation. + (glitz_agl_thread_info_init): Use glitz_program_map_init to + initialize program map. + (glitz_agl_thread_info_fini): Use glitz_program_map_fini to + clean up program map. + (glitz_agl_thread_info_fini): Do not free thread specific data here. + + * src/glitz_agl_extension.c: Check for GL_ARB_texture_env_combine, + GL_ARB_texture_env_dot3 and GL_EXT_pixel_buffer_object. + + * src/glitz.h: glitz_color_range_create now needs a surface + reference. + Added glitz_surface_set_component_alpha. + Added skip_lines to glitz_pixel_format_t. + Added new pixel buffer interface, which allows for asynchronous + pixel transfers and access to high-performance memory. + + * src/glitz.h: Added GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK, + GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK, + GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK, + GLITZ_FEATURE_COMPONENT_ALPHA_MASK. + + * src/glitz.c: Moved in my new glitz.c code, much of it is similar + to the old glitz.c code. However, this new code uses the new + glitz_render_op_t infrastructure and supports component alpha. + + * configure.in: Added GCC warning flags. + + * TODO: Updated todo list. + + * README: Added a short description of glitz. + 2004-06-21 David Reveman <c99drn@cs.umu.se> * src/glitz.h (GLITZ_REVISION): Bump version to 0.1.5. @@ -1 +1,21 @@ -glitz - OpenGL compositing library +glitz - OpenGL image compositing library + +Glitz is an OpenGL image compositing library. Glitz provides +Porter/Duff compositing of images and implicit mask generation for +geometric primitives including trapezoids, triangles, and rectangles. + +The semantics of glitz are designed to precisely match the +specification of the X Render extension. Glitz does not only implement +X Render features like component alpha and image transformations, but +also support additional features like convolution filters and color +gradients, which are not currently part of the X Render specification. + +The performance and capabilities of glitz are much dependent on +graphics hardware. Glitz does not in any way handle software +fall-backs when graphics hardware is insufficient. However, glitz +will report if any requested operation cannot be carried out by +graphics hardware, hence making a higher level software layer +responsible for appropriate actions. + +David Reveman +c99drn@cs.umu.se @@ -1,11 +1,9 @@ -* Text support. Glyph set management, glyph and string compositing - operations. Some ideas: Multi-texturing for compositing multiple glyphs - per render pass, Sub-pixel rendering, vector text; glyphs loaded into - display lists. - -* A programmable surface type which can store a set of rendering operations - in a display list. +* GL_MESA_pack_invert support. * Projective transformations. +* Retained-mode rendering. + * WGL (Windows GL) backend. + +* Mesa-solo backend. diff --git a/configure.in b/configure.in index e5a8ca9..935dd00 100644 --- a/configure.in +++ b/configure.in @@ -46,6 +46,36 @@ if test "x$GCC" = "xyes"; then *) CFLAGS="$CFLAGS -Wall" ;; esac + case " $CFLAGS " in + *[[\ \ ]]-Wpointer-arith[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -Wpointer-arith" ;; + esac + + case " $CFLAGS " in + *[[\ \ ]]-Wstrict-prototypes[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -Wstrict-prototypes" ;; + esac + + case " $CFLAGS " in + *[[\ \ ]]-Wmissing-prototypes[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;; + esac + + case " $CFLAGS " in + *[[\ \ ]]-Wmissing-declarations[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-declarations" ;; + esac + + case " $CFLAGS " in + *[[\ \ ]]-Wnested-externs[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -Wnested-externs" ;; + esac + + case " $CFLAGS " in + *[[\ \ ]]-fno-strict-aliasing[[\ \ ]]*) ;; + *) CFLAGS="$CFLAGS -fno-strict-aliasing" ;; + esac + if test "x$enable_ansi" = "xyes"; then case " $CFLAGS " in *[[\ \ ]]-ansi[[\ \ ]]*) ;; diff --git a/src/glitz.c b/src/glitz.c index ce90099..861b633 100644 --- a/src/glitz.c +++ b/src/glitz.c @@ -1,28 +1,26 @@ /* - * Copyright © 2004 David Reveman, Peter Nilsson - * + * Copyright © 2004 David Reveman + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the names of - * David Reveman and Peter Nilsson not be used in advertising or - * publicity pertaining to distribution of the software without - * specific, written prior permission. David Reveman and Peter Nilsson - * makes no representations about the suitability of this software for - * any purpose. It is provided "as is" without express or implied warranty. + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. * - * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND - * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Authors: David Reveman <c99drn@cs.umu.se> - * Peter Nilsson <c99pnn@cs.umu.se> + * Author: David Reveman <c99drn@cs.umu.se> */ #ifdef HAVE_CONFIG_H @@ -31,259 +29,6 @@ #include "glitzint.h" -#include <math.h> - -#define SURFACE_GLREPEAT(surface, texture) \ - (SURFACE_REPEAT (surface) && texture->repeatable) - -#define SURFACE_MANUALREPEAT(surface, texture) \ - ((surface->hint_mask & GLITZ_INT_HINT_REPEAT_MASK) && (!texture->repeatable)) - -#define SURFACE_ROTATE(surface) \ - (surface->transform && \ - ((surface->transform->m[0][1] != 0.0) || \ - (surface->transform->m[1][0] != 0.0))) - -/* This version of composite uses multi-texturing for direct - Porter-Duff compositing. It cannot handle rotating transformations - and will fall back to regular composite function if this is the case. */ -static glitz_bool_t -_glitz_composite_direct (glitz_operator_t op, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst, - int x_src, - int y_src, - int x_mask, - int y_mask, - int x_dst, - int y_dst, - int width, - int height) -{ - glitz_gl_proc_address_list_t *gl; - glitz_texture_t *src_texture; - glitz_texture_t *mask_texture; - glitz_bounding_box_double_t src_box, mask_box, dst_box; - glitz_bounding_box_t dirty_box; - glitz_point_t src_tl, src_br, mask_tl, mask_br; - glitz_render_type_t type; - - gl = dst->gl; - - type = glitz_render_type (src, mask, dst); - - if (type == GLITZ_RENDER_TYPE_NOT_SUPPORTED) - return 0; - - /* We cannot continue if we have a rotating transformation. */ - if (SURFACE_ROTATE (src) || SURFACE_ROTATE (mask)) - return 0; - - src_texture = glitz_surface_get_texture (src); - mask_texture = glitz_surface_get_texture (mask); - - /* Texture has not been allocated, hence source and the result of this - operation is undefined. So lets do nothing. */ - if ((!src_texture) || (!mask_texture)) - return 1; - - if (SURFACE_MANUALREPEAT (src, src_texture) || - SURFACE_MANUALREPEAT (mask, mask_texture)) - return 0; - - if (!glitz_surface_push_current (dst, GLITZ_CN_SURFACE_DRAWABLE_CURRENT)) { - glitz_surface_pop_current (dst); - return 0; - } - - gl->disable (GLITZ_GL_SCISSOR_TEST); - - glitz_render_enable (type, - src, mask, dst, - src_texture, mask_texture, 0xffff); - - glitz_set_operator (gl, op); - - gl->active_texture_arb (GLITZ_GL_TEXTURE0_ARB); - glitz_texture_bind (gl, src_texture); - - gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, - GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - - if (src->transform) - glitz_texture_ensure_filter (gl, src_texture, src->filter); - else - glitz_texture_ensure_filter (gl, src_texture, GLITZ_FILTER_NEAREST); - - glitz_texture_ensure_repeat (gl, - src_texture, - src->hint_mask & GLITZ_INT_HINT_REPEAT_MASK); - - dst->gl->active_texture_arb (GLITZ_GL_TEXTURE1_ARB); - glitz_texture_bind (gl, mask_texture); - - gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, - GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - - if (mask->transform) - glitz_texture_ensure_filter (gl, mask_texture, mask->filter); - else - glitz_texture_ensure_filter (gl, mask_texture, GLITZ_FILTER_NEAREST); - - dst_box.x1 = x_dst; - dst_box.y1 = y_dst; - dst_box.x2 = dst_box.x1 + width; - dst_box.y2 = dst_box.y1 + height; - - if (!SURFACE_REPEAT (src)) { - src_box.x1 = src_box.y1 = 0.0; - src_box.x2 = src->width; - src_box.y2 = src->height; - - if (src->transform) - glitz_matrix_transform_bounding_box (src->transform, - &src_box.x1, &src_box.y1, - &src_box.x2, &src_box.y2); - - src_box.x1 += x_dst - x_src; - src_box.x2 += x_dst - x_src; - src_box.y1 += y_dst - y_src; - src_box.y2 += y_dst - y_src; - - if (!SURFACE_PROGRAMMATIC (src)) - glitz_intersect_bounding_box_double (&dst_box, &src_box, &dst_box); - } - - if (!SURFACE_REPEAT (mask)) { - mask_box.x1 = mask_box.y1 = 0.0; - mask_box.x2 = mask->width; - mask_box.y2 = mask->height; - - if (mask->transform) - glitz_matrix_transform_bounding_box (mask->transform, - &mask_box.x1, &mask_box.y1, - &mask_box.x2, &mask_box.y2); - - mask_box.x1 += x_dst - x_mask; - mask_box.x2 += x_dst - x_mask; - mask_box.y1 += y_dst - y_mask; - mask_box.y2 += y_dst - y_mask; - - if (!SURFACE_PROGRAMMATIC (mask)) - glitz_intersect_bounding_box_double (&dst_box, &mask_box, &dst_box); - } - - if ((dst_box.x2 - dst_box.x1) <= 0 || (dst_box.y2 - dst_box.y1) <= 0) - return 1; - - if (SURFACE_REPEAT (src)) { - src_br.y = src->height - - (((y_src % src->height) + (int) (dst_box.y2 - dst_box.y1)) % - src->height); - src_tl.y = (dst_box.y2 - dst_box.y1) + src_br.y; - src_tl.x = x_src % src->width; - src_br.x = (dst_box.x2 - dst_box.x1) + src_tl.x; - } else { - glitz_intersect_bounding_box_double (&src_box, &dst_box, &src_box); - - src_tl.x = src_box.x1 - x_dst + x_src; - src_br.x = src_box.x2 - x_dst + x_src; - src_tl.y = src_box.y1 - y_dst + y_src; - src_br.y = src_box.y2 - y_dst + y_src; - - if (src->transform) { - glitz_matrix_transform_point (src->inverse_transform, - &src_tl.x, &src_tl.y); - glitz_matrix_transform_point (src->inverse_transform, - &src_br.x, &src_br.y); - } - } - - src_tl.x = (src_tl.x / src->width) * src_texture->texcoord_width; - src_tl.y = (src_tl.y / src->height) * src_texture->texcoord_height; - src_br.x = (src_br.x / src->width) * src_texture->texcoord_width; - src_br.y = (src_br.y / src->height) * src_texture->texcoord_height; - - if (!SURFACE_REPEAT (src)) { - src_tl.y = src_texture->texcoord_height - src_tl.y; - src_br.y = src_texture->texcoord_height - src_br.y; - } - - if (SURFACE_REPEAT (mask)) { - mask_br.y = mask->height - - (((y_mask % mask->height) + (int) (dst_box.y2 - dst_box.y1)) % - mask->height); - mask_tl.y = (dst_box.y2 - dst_box.y1) + mask_br.y; - mask_tl.x = x_mask % mask->width; - mask_br.x = (dst_box.x2 - dst_box.x1) + mask_tl.x; - } else { - glitz_intersect_bounding_box_double (&mask_box, &dst_box, &mask_box); - - mask_tl.x = mask_box.x1 - x_dst + x_mask; - mask_br.x = mask_box.x2 - x_dst + x_mask; - mask_tl.y = mask_box.y1 - y_dst + y_mask; - mask_br.y = mask_box.y2 - y_dst + y_mask; - - if (mask->transform) { - glitz_matrix_transform_point (mask->inverse_transform, - &mask_tl.x, &mask_tl.y); - glitz_matrix_transform_point (mask->inverse_transform, - &mask_br.x, &mask_br.y); - } - } - - mask_tl.x = (mask_tl.x / mask->width) * mask_texture->texcoord_width; - mask_tl.y = (mask_tl.y / mask->height) * mask_texture->texcoord_height; - mask_br.x = (mask_br.x / mask->width) * mask_texture->texcoord_width; - mask_br.y = (mask_br.y / mask->height) * mask_texture->texcoord_height; - - if (!SURFACE_REPEAT (mask)) { - mask_tl.y = mask_texture->texcoord_height - mask_tl.y; - mask_br.y = mask_texture->texcoord_height - mask_br.y; - } - - gl->begin (GLITZ_GL_QUADS); - - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE0_ARB, src_tl.x, src_tl.y); - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE1_ARB, mask_tl.x, mask_tl.y); - gl->vertex_2d (dst_box.x1, dst_box.y1); - - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE0_ARB, src_br.x, src_tl.y); - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE1_ARB, mask_br.x, mask_tl.y); - gl->vertex_2d (dst_box.x2, dst_box.y1); - - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE0_ARB, src_br.x, src_br.y); - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE1_ARB, mask_br.x, mask_br.y); - gl->vertex_2d (dst_box.x2, dst_box.y2); - - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE0_ARB, src_tl.x, src_br.y); - gl->multi_tex_coord_2d_arb (GLITZ_GL_TEXTURE1_ARB, mask_tl.x, mask_br.y); - gl->vertex_2d (dst_box.x1, dst_box.y2); - - gl->end (); - - gl->active_texture_arb (GLITZ_GL_TEXTURE1_ARB); - glitz_texture_unbind (gl, mask_texture); - - gl->active_texture_arb (GLITZ_GL_TEXTURE0_ARB); - glitz_texture_unbind (gl, src_texture); - - glitz_render_disable (type, dst); - - dirty_box.x1 = floor (dst_box.x1); - dirty_box.y1 = floor (dst_box.y1); - dirty_box.x2 = ceil (dst_box.x2); - dirty_box.y2 = ceil (dst_box.y2); - glitz_surface_dirty (dst, &dirty_box); - - glitz_surface_pop_current (dst); - - return 1; -} - static void glitz_mask_bounds (glitz_surface_t *src, glitz_surface_t *mask, @@ -375,6 +120,13 @@ glitz_mask_bounds (glitz_surface_t *src, } } +glitz_gl_uint_t _texture_units[] = { + 0, + GLITZ_GL_TEXTURE0, + GLITZ_GL_TEXTURE1, + GLITZ_GL_TEXTURE2 +}; + typedef enum { GLITZ_REPEAT_NONE = 0, GLITZ_REPEAT_SOUTHEAST, @@ -397,49 +149,27 @@ glitz_composite (glitz_operator_t op, int width, int height) { - glitz_gl_proc_address_list_t *gl; + glitz_gl_proc_address_list_t *gl = dst->gl; glitz_surface_t *intermediate = NULL; - glitz_texture_t *texture; + glitz_texture_t *texture, *mask_texture = NULL; glitz_point_t tl, bl, br, tr; glitz_bounding_box_t clip; - glitz_render_type_t type; + glitz_render_op_t render_op; glitz_gl_uint_t list = 0; - unsigned short opacity = 0xffff; - - gl = dst->gl; + int texture_unit = 0; - if (SURFACE_PROGRAMMATIC (src)) - glitz_programmatic_surface_setup (src, - width + abs (x_src), - height + abs (y_src)); - - if (mask) { - if (SURFACE_PROGRAMMATIC (mask)) { - glitz_programmatic_surface_setup (mask, - width + abs (x_mask), - height + abs (y_mask)); - - if (SURFACE_SOLID (mask)) { - opacity = ((glitz_programmatic_surface_t *) mask)->u.solid.color.alpha; - mask = NULL; - } - } + glitz_render_op_init (&render_op, &src, &mask, dst, + &x_src, &y_src, &x_mask, &y_mask); + if (render_op.type == GLITZ_RENDER_TYPE_NA) { + glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); + return; } - - if (mask) { + + if (render_op.type == GLITZ_RENDER_TYPE_INTERMEDIATE) { glitz_bounding_box_t dst_bounds, mask_bounds; glitz_intermediate_t intermediate_type; static glitz_color_t clear_color = { 0x0000, 0x0000, 0x0000, 0x0000 }; - if ((dst->feature_mask & GLITZ_FEATURE_ARB_MULTITEXTURE_MASK) && - _glitz_composite_direct (op, - src, mask, dst, - x_src, y_src, - x_mask, y_mask, - x_dst, y_dst, - width, height)) - return; - dst_bounds.x1 = x_dst; dst_bounds.x2 = x_dst + width; dst_bounds.y1 = y_dst; @@ -450,7 +180,7 @@ glitz_composite (glitz_operator_t op, &dst_bounds, &mask_bounds); if ((mask_bounds.x2 - x_dst) <= 0 || (mask_bounds.y2 - y_dst) <= 0) return; - + if (src->transform && (!SURFACE_REPEAT (src))) intermediate_type = GLITZ_INTERMEDIATE_RGBA_STENCIL; else @@ -496,12 +226,21 @@ glitz_composite (glitz_operator_t op, width = intermediate->width; height = intermediate->height; src = intermediate; + mask = NULL; x_src = y_src = 0; - } + glitz_render_op_init (&render_op, &src, &mask, dst, + &x_src, &y_src, &x_mask, &y_mask); + if (render_op.type == GLITZ_RENDER_TYPE_NA) { + glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); + glitz_surface_destroy (intermediate); + return; + } + } + texture = glitz_surface_get_texture (src); - /* Texture has not been allocated, hence source and the result of this + /* Source texture has not been allocated, hence source and the result of this operation is undefined. So lets do nothing. */ if (!texture) return; @@ -510,258 +249,497 @@ glitz_composite (glitz_operator_t op, glitz_surface_pop_current (dst); return; } + + if (mask) { /* MULTI-TEXTURE */ + glitz_bounding_box_double_t src_box, mask_box, dst_box; + glitz_point_t src_tl, src_br, mask_tl, mask_br; + glitz_gl_enum_t src_texture_unit = 0; - glitz_texture_bind (gl, texture); - - clip.x1 = x_dst; - clip.y1 = y_dst; - clip.x2 = clip.x1 + width; - clip.y2 = clip.y1 + height; + mask_texture = glitz_surface_get_texture (mask); + + /* Mask texture has not been allocated, hence source and the result of this + operation is undefined. So lets do nothing. */ + if (!mask_texture) { + glitz_surface_pop_current (dst); + return; + } + + dst_box.x1 = x_dst; + dst_box.y1 = y_dst; + dst_box.x2 = dst_box.x1 + width; + dst_box.y2 = dst_box.y1 + height; + + if (!SURFACE_REPEAT (src)) { + src_box.x1 = src_box.y1 = 0.0; + src_box.x2 = src->width; + src_box.y2 = src->height; + + if (src->transform) + glitz_matrix_transform_bounding_box (src->transform, + &src_box.x1, &src_box.y1, + &src_box.x2, &src_box.y2); + + src_box.x1 += x_dst - x_src; + src_box.x2 += x_dst - x_src; + src_box.y1 += y_dst - y_src; + src_box.y2 += y_dst - y_src; - if (SURFACE_CLEAR_EXTERIOR (dst)) { - gl->clear_stencil (0x0); - gl->clear (GLITZ_GL_STENCIL_BUFFER_BIT); - glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_SET, 0x1); - } + if (!SURFACE_PROGRAMMATIC (src)) + glitz_intersect_bounding_box_double (&dst_box, &src_box, &dst_box); + } - type = glitz_render_type (src, NULL, dst); - - gl->scissor (clip.x1, dst->height - (clip.y1 + height), width, height); - - glitz_set_operator (gl, op); - - glitz_render_enable (type, src, NULL, dst, texture, NULL, opacity); + if (!SURFACE_REPEAT (mask)) { + mask_box.x1 = mask_box.y1 = 0.0; + mask_box.x2 = mask->width; + mask_box.y2 = mask->height; + + if (mask->transform) + glitz_matrix_transform_bounding_box (mask->transform, + &mask_box.x1, &mask_box.y1, + &mask_box.x2, &mask_box.y2); - if ((!src->transform) && SURFACE_GLREPEAT (src, texture)) { - /* CASE 1: Repeat, no transformation and power of two sized texture, - GL can do repeat for us. */ - double repeat_factor_x, repeat_factor_y; - - glitz_texture_ensure_repeat (gl, texture, 1); - glitz_texture_ensure_filter (gl, texture, GLITZ_FILTER_NEAREST); - - bl.x = tl.x = x_dst; - tr.y = tl.y = y_dst; - tr.x = br.x = x_dst + width; - bl.y = br.y = y_dst + height; - - /* Shift coordinates with source offset */ - if (x_src) { - x_src = (x_src % src->width); - tl.x -= x_src; - bl.x -= x_src; + mask_box.x1 += x_dst - x_mask; + mask_box.x2 += x_dst - x_mask; + mask_box.y1 += y_dst - y_mask; + mask_box.y2 += y_dst - y_mask; + + if (!SURFACE_PROGRAMMATIC (mask)) + glitz_intersect_bounding_box_double (&dst_box, &mask_box, &dst_box); } - if (y_src) { - y_src = (y_src % src->height); - tl.y -= y_src; - tr.y -= y_src; + + if ((dst_box.x2 - dst_box.x1) <= 0 || (dst_box.y2 - dst_box.y1) <= 0) { + glitz_surface_pop_current (dst); + return; } - /* Align with top left edge */ - bl.y += texture->height - (((int) (br.y - tl.y)) % texture->height); - br.y += texture->height - (((int) (br.y - tl.y)) % texture->height); - - repeat_factor_x = (br.x - tl.x) / (double) texture->width; - repeat_factor_y = (br.y - tl.y) / (double) texture->height; + if (SURFACE_REPEAT (src)) { + src_br.y = src->height - + (((y_src % src->height) + (int) (dst_box.y2 - dst_box.y1)) % + src->height); + src_tl.y = (dst_box.y2 - dst_box.y1) + src_br.y; + src_tl.x = x_src % src->width; + src_br.x = (dst_box.x2 - dst_box.x1) + src_tl.x; + } else { + glitz_intersect_bounding_box_double (&src_box, &dst_box, &src_box); + + src_tl.x = src_box.x1 - x_dst + x_src; + src_br.x = src_box.x2 - x_dst + x_src; + src_tl.y = src_box.y1 - y_dst + y_src; + src_br.y = src_box.y2 - y_dst + y_src; + + if (src->transform) { + glitz_matrix_transform_point (src->inverse_transform, + &src_tl.x, &src_tl.y); + glitz_matrix_transform_point (src->inverse_transform, + &src_br.x, &src_br.y); + } + } - if (dst->multi_sample) { - list = dst->gl->gen_lists (1); - dst->gl->new_list (list, GLITZ_GL_COMPILE); + src_tl.x = (src_tl.x / src->width) * texture->texcoord_width; + src_tl.y = (src_tl.y / src->height) * texture->texcoord_height; + src_br.x = (src_br.x / src->width) * texture->texcoord_width; + src_br.y = (src_br.y / src->height) * texture->texcoord_height; + + if (!SURFACE_REPEAT (src)) { + src_tl.y = texture->texcoord_height - src_tl.y; + src_br.y = texture->texcoord_height - src_br.y; + } + + if (SURFACE_REPEAT (mask)) { + mask_br.y = mask->height - + (((y_mask % mask->height) + (int) (dst_box.y2 - dst_box.y1)) % + mask->height); + mask_tl.y = (dst_box.y2 - dst_box.y1) + mask_br.y; + mask_tl.x = x_mask % mask->width; + mask_br.x = (dst_box.x2 - dst_box.x1) + mask_tl.x; + } else { + glitz_intersect_bounding_box_double (&mask_box, &dst_box, &mask_box); + + mask_tl.x = mask_box.x1 - x_dst + x_mask; + mask_br.x = mask_box.x2 - x_dst + x_mask; + mask_tl.y = mask_box.y1 - y_dst + y_mask; + mask_br.y = mask_box.y2 - y_dst + y_mask; + + if (mask->transform) { + glitz_matrix_transform_point (mask->inverse_transform, + &mask_tl.x, &mask_tl.y); + glitz_matrix_transform_point (mask->inverse_transform, + &mask_br.x, &mask_br.y); + } } - - gl->begin (GLITZ_GL_QUADS); - gl->tex_coord_2d (0.0, repeat_factor_y); - gl->vertex_2d (tl.x, tl.y); - gl->tex_coord_2d (repeat_factor_x, repeat_factor_y); - gl->vertex_2d (tr.x, tr.y); - gl->tex_coord_2d (repeat_factor_x, 0.0); - gl->vertex_2d (br.x, br.y); - gl->tex_coord_2d (0.0, 0.0); - gl->vertex_2d (bl.x, bl.y); - gl->end (); - - } else { - /* CASE 2: Either none power of two sized texture or - transformation is set. */ - glitz_point_t base_tl, base_bl, base_br, base_tr; - int x_dir, y_dir, continue_y, continue_x, x_is_ok, y_is_ok, - in_destination_area; - double save_base_x1, save_base_x2; - glitz_repeat_direction_t repeat_direction; - glitz_texture_ensure_repeat (gl, texture, 0); + mask_tl.x = (mask_tl.x / mask->width) * mask_texture->texcoord_width; + mask_tl.y = (mask_tl.y / mask->height) * mask_texture->texcoord_height; + mask_br.x = (mask_br.x / mask->width) * mask_texture->texcoord_width; + mask_br.y = (mask_br.y / mask->height) * mask_texture->texcoord_height; - base_bl.x = base_tl.x = 0; - base_tr.y = base_tl.y = 0; - base_tr.x = base_br.x = src->width; - base_bl.y = base_br.y = src->height; + if (!SURFACE_REPEAT (mask)) { + mask_tl.y = mask_texture->texcoord_height - mask_tl.y; + mask_br.y = mask_texture->texcoord_height - mask_br.y; + } + + gl->disable (GLITZ_GL_SCISSOR_TEST); + + texture_unit++; + glitz_texture_bind (gl, mask_texture); + + if (mask->transform) + glitz_texture_ensure_filter (gl, mask_texture, mask->filter); + else + glitz_texture_ensure_filter (gl, mask_texture, GLITZ_FILTER_NEAREST); + + glitz_texture_ensure_repeat (gl, mask_texture, SURFACE_REPEAT (mask)); - /* Start repeating in southeast direction */ - repeat_direction = GLITZ_REPEAT_SOUTHEAST; - x_dir = y_dir = 1; + while (texture_unit < render_op.render->texture_units) { + src_texture_unit = _texture_units[++texture_unit]; + gl->active_texture (src_texture_unit); + glitz_texture_bind (gl, texture); + } if (src->transform) glitz_texture_ensure_filter (gl, texture, src->filter); else glitz_texture_ensure_filter (gl, texture, GLITZ_FILTER_NEAREST); - if (dst->multi_sample) { - list = dst->gl->gen_lists (1); - dst->gl->new_list (list, GLITZ_GL_COMPILE); + glitz_texture_ensure_repeat (gl, texture, SURFACE_REPEAT (src)); + + glitz_render_op_set_textures (&render_op, texture, mask_texture); + glitz_set_operator (gl, op); + + if (render_op.component_alpha) { + list = gl->gen_lists (1); + gl->new_list (list, GLITZ_GL_COMPILE); + } else + glitz_render_enable (&render_op); + + gl->begin (GLITZ_GL_QUADS); + + gl->multi_tex_coord_2d (GLITZ_GL_TEXTURE0, mask_tl.x, mask_tl.y); + gl->multi_tex_coord_2d (src_texture_unit, src_tl.x, src_tl.y); + gl->vertex_2d (dst_box.x1, dst_box.y1); + + gl->multi_tex_coord_2d (GLITZ_GL_TEXTURE0, mask_br.x, mask_tl.y); + gl->multi_tex_coord_2d (src_texture_unit, src_br.x, src_tl.y); + gl->vertex_2d (dst_box.x2, dst_box.y1); + + gl->multi_tex_coord_2d (GLITZ_GL_TEXTURE0, mask_br.x, mask_br.y); + gl->multi_tex_coord_2d (src_texture_unit, src_br.x, src_br.y); + gl->vertex_2d (dst_box.x2, dst_box.y2); + + gl->multi_tex_coord_2d (GLITZ_GL_TEXTURE0, mask_tl.x, mask_br.y); + gl->multi_tex_coord_2d (src_texture_unit, src_tl.x, src_br.y); + gl->vertex_2d (dst_box.x1, dst_box.y2); + + gl->end (); + + clip.x1 = dst_box.x1; + clip.y1 = dst_box.y1; + clip.x2 = dst_box.x2 + 0.5; + clip.y2 = dst_box.y2 + 0.5; + + } else { /* SINGLE-TEXTURE */ + + while (texture_unit < render_op.render->texture_units) { + if (texture_unit++) + gl->active_texture (_texture_units[texture_unit]); + glitz_texture_bind (gl, texture); } + + clip.x1 = x_dst; + clip.y1 = y_dst; + clip.x2 = clip.x1 + width; + clip.y2 = clip.y1 + height; + + if (SURFACE_CLEAR_EXTERIOR (dst)) { + gl->clear_stencil (0x0); + gl->clear (GLITZ_GL_STENCIL_BUFFER_BIT); + glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_SET, 0x1); + } + + gl->scissor (clip.x1, dst->height - (clip.y1 + height), width, height); + + glitz_render_op_set_textures (&render_op, texture, NULL); + glitz_set_operator (gl, op); + + if (dst->multi_sample || render_op.component_alpha) + list = gl->gen_lists (1); + + if ((!src->transform) && SURFACE_REPEAT (src) && texture->repeatable) { + /* CASE 1: Repeat, no transformation and power of two sized texture, + GL can do repeat for us. */ + double repeat_factor_x, repeat_factor_y; + + glitz_texture_ensure_repeat (gl, texture, 1); + glitz_texture_ensure_filter (gl, texture, GLITZ_FILTER_NEAREST); + + bl.x = tl.x = x_dst; + tr.y = tl.y = y_dst; + tr.x = br.x = x_dst + width; + bl.y = br.y = y_dst + height; + + /* Shift coordinates with source offset */ + if (x_src) { + x_src = (x_src % src->width); + tl.x -= x_src; + bl.x -= x_src; + } + if (y_src) { + y_src = (y_src % src->height); + tl.y -= y_src; + tr.y -= y_src; + } - while (repeat_direction) { - save_base_x1 = base_tl.x; - save_base_x2 = base_tr.x; + /* Align with top left edge */ + bl.y += texture->height - (((int) (br.y - tl.y)) % texture->height); + br.y += texture->height - (((int) (br.y - tl.y)) % texture->height); + + repeat_factor_x = (br.x - tl.x) / (double) texture->width; + repeat_factor_y = (br.y - tl.y) / (double) texture->height; + + if (list) + gl->new_list (list, GLITZ_GL_COMPILE); + else + glitz_render_enable (&render_op); + + gl->begin (GLITZ_GL_QUADS); + gl->tex_coord_2d (0.0, repeat_factor_y); + gl->vertex_2d (tl.x, tl.y); + gl->tex_coord_2d (repeat_factor_x, repeat_factor_y); + gl->vertex_2d (tr.x, tr.y); + gl->tex_coord_2d (repeat_factor_x, 0.0); + gl->vertex_2d (br.x, br.y); + gl->tex_coord_2d (0.0, 0.0); + gl->vertex_2d (bl.x, bl.y); + gl->end (); + + } else { + /* CASE 2: Either none power of two sized texture or + transformation is set. */ + glitz_point_t base_tl, base_bl, base_br, base_tr; + int x_dir, y_dir, continue_y, continue_x, x_is_ok, y_is_ok, + in_destination_area; + double save_base_x1, save_base_x2, min, max; + glitz_repeat_direction_t repeat_direction; + + glitz_texture_ensure_repeat (gl, texture, 0); + + base_bl.x = base_tl.x = 0; + base_tr.y = base_tl.y = 0; + base_tr.x = base_br.x = src->width; + base_bl.y = base_br.y = src->height; + + /* Start repeating in southeast direction */ + repeat_direction = GLITZ_REPEAT_SOUTHEAST; + x_dir = y_dir = 1; + + if (src->transform) + glitz_texture_ensure_filter (gl, texture, src->filter); + else + glitz_texture_ensure_filter (gl, texture, GLITZ_FILTER_NEAREST); + + if (list) + gl->new_list (list, GLITZ_GL_COMPILE); + else + glitz_render_enable (&render_op); + + while (repeat_direction) { + save_base_x1 = base_tl.x; + save_base_x2 = base_tr.x; - do { - continue_y = continue_x = in_destination_area = 0; do { - bl = base_bl; - br = base_br; - tl = base_tl; - tr = base_tr; + continue_y = continue_x = in_destination_area = 0; + do { + bl = base_bl; + br = base_br; + tl = base_tl; + tr = base_tr; - if (src->transform) { - glitz_matrix_transform_point (src->transform, &tl.x, &tl.y); - glitz_matrix_transform_point (src->transform, &bl.x, &bl.y); - glitz_matrix_transform_point (src->transform, &tr.x, &tr.y); - glitz_matrix_transform_point (src->transform, &br.x, &br.y); - } - - tl.x += x_dst - x_src; - bl.x += x_dst - x_src; - tr.x += x_dst - x_src; - br.x += x_dst - x_src; - - tl.y += y_dst - y_src; - bl.y += y_dst - y_src; - tr.y += y_dst - y_src; - br.y += y_dst - y_src; + if (src->transform) { + glitz_matrix_transform_point (src->transform, &tl.x, &tl.y); + glitz_matrix_transform_point (src->transform, &bl.x, &bl.y); + glitz_matrix_transform_point (src->transform, &tr.x, &tr.y); + glitz_matrix_transform_point (src->transform, &br.x, &br.y); + } + + tl.x += x_dst - x_src; + bl.x += x_dst - x_src; + tr.x += x_dst - x_src; + br.x += x_dst - x_src; - if ((tl.x > (x_dst + width) && bl.x > (x_dst + width)) || - (tr.x < x_dst && br.x < x_dst)) - x_is_ok = 0; - else - x_is_ok = 1; - - if ((tl.y > (y_dst + height) && tr.y > (y_dst + height)) || - (bl.y < y_dst && br.y < y_dst)) - y_is_ok = 0; - else - y_is_ok = 1; - - if (x_is_ok && y_is_ok) { - gl->begin (GLITZ_GL_QUADS); - gl->tex_coord_2d (0.0, texture->texcoord_height); - gl->vertex_2d (tl.x, tl.y); - gl->tex_coord_2d (texture->texcoord_width, - texture->texcoord_height); - gl->vertex_2d (tr.x, tr.y); - gl->tex_coord_2d (texture->texcoord_width, 0.0); - gl->vertex_2d (br.x, br.y); - gl->tex_coord_2d (0.0, 0.0); - gl->vertex_2d (bl.x, bl.y); - gl->end (); - in_destination_area = 1; - } + tl.y += y_dst - y_src; + bl.y += y_dst - y_src; + tr.y += y_dst - y_src; + br.y += y_dst - y_src; - if (SURFACE_REPEAT (src)) { - base_bl.x += src->width * x_dir; - base_tl.x += src->width * x_dir; - base_tr.x += src->width * x_dir; - base_br.x += src->width * x_dir; + min = MIN (tl.x, MIN (bl.x, MIN (tr.x, br.x))); + max = MAX (tl.x, MAX (bl.x, MAX (tr.x, br.x))); + + if ((min > (x_dst + width)) || (max < x_dst)) + x_is_ok = 0; + else + x_is_ok = 1; - if (y_is_ok) - continue_y = 1; + min = MIN (tl.y, MIN (bl.y, MIN (tr.y, br.y))); + max = MAX (tl.y, MAX (bl.y, MAX (tr.y, br.y))); - if (in_destination_area) - continue_x = (x_is_ok && y_is_ok); + if ((min > (y_dst + height)) || (max < y_dst)) + y_is_ok = 0; else - continue_x = (x_is_ok || y_is_ok); + y_is_ok = 1; + + if (x_is_ok && y_is_ok) { + gl->begin (GLITZ_GL_QUADS); + gl->tex_coord_2d (0.0, texture->texcoord_height); + gl->vertex_2d (tl.x, tl.y); + gl->tex_coord_2d (texture->texcoord_width, + texture->texcoord_height); + gl->vertex_2d (tr.x, tr.y); + gl->tex_coord_2d (texture->texcoord_width, 0.0); + gl->vertex_2d (br.x, br.y); + gl->tex_coord_2d (0.0, 0.0); + gl->vertex_2d (bl.x, bl.y); + gl->end (); + in_destination_area = 1; + } + + if (SURFACE_REPEAT (src)) { + base_bl.x += src->width * x_dir; + base_tl.x += src->width * x_dir; + base_tr.x += src->width * x_dir; + base_br.x += src->width * x_dir; + + if (y_is_ok) + continue_y = 1; + + if (in_destination_area) + continue_x = (x_is_ok && y_is_ok); + else + continue_x = (x_is_ok || y_is_ok); + } + } while (SURFACE_REPEAT (src) && continue_x); + + if (SURFACE_REPEAT (src)) { + base_bl.y += src->height * y_dir; + base_tl.y += src->height * y_dir; + base_tr.y += src->height * y_dir; + base_br.y += src->height * y_dir; + + base_tl.x = base_bl.x = save_base_x1; + base_tr.x = base_br.x = save_base_x2; + } + } while (SURFACE_REPEAT (src) && continue_y); + + if (src->transform && SURFACE_REPEAT (src)) { + switch (repeat_direction) { + case GLITZ_REPEAT_SOUTHEAST: + y_dir = -1; + base_tl.y = base_tr.y = -src->height; + base_bl.y = base_br.y = 0.0; + repeat_direction = GLITZ_REPEAT_SOUTHWEST; + break; + case GLITZ_REPEAT_SOUTHWEST: + x_dir = -1; + base_tl.y = base_tr.y = -src->height; + base_bl.y = base_br.y = 0.0; + base_tl.x = base_bl.x = -src->width; + base_tr.x = base_br.x = 0.0; + repeat_direction = GLITZ_REPEAT_NORTHEAST; + break; + case GLITZ_REPEAT_NORTHEAST: + y_dir = 1; + base_tl.y = base_tr.y = 0.0; + base_bl.y = base_br.y = src->height; + base_tl.x = base_bl.x = -src->width; + base_tr.x = base_br.x = 0.0; + repeat_direction = GLITZ_REPEAT_NORTHWEST; + break; + case GLITZ_REPEAT_NORTHWEST: + repeat_direction = GLITZ_REPEAT_NONE; + break; + case GLITZ_REPEAT_NONE: + break; } - } while (SURFACE_REPEAT (src) && continue_x); - - if (SURFACE_REPEAT (src)) { - base_bl.y += src->height * y_dir; - base_tl.y += src->height * y_dir; - base_tr.y += src->height * y_dir; - base_br.y += src->height * y_dir; - - base_tl.x = base_bl.x = save_base_x1; - base_tr.x = base_br.x = save_base_x2; - } - } while (SURFACE_REPEAT (src) && continue_y); - - if (src->transform && SURFACE_REPEAT (src)) { - switch (repeat_direction) { - case GLITZ_REPEAT_SOUTHEAST: - y_dir = -1; - base_tl.y = base_tr.y = -src->height; - base_bl.y = base_br.y = 0.0; - repeat_direction = GLITZ_REPEAT_SOUTHWEST; - break; - case GLITZ_REPEAT_SOUTHWEST: - x_dir = -1; - base_tl.y = base_tr.y = -src->height; - base_bl.y = base_br.y = 0.0; - base_tl.x = base_bl.x = -src->width; - base_tr.x = base_br.x = 0.0; - repeat_direction = GLITZ_REPEAT_NORTHEAST; - break; - case GLITZ_REPEAT_NORTHEAST: - y_dir = 1; - base_tl.y = base_tr.y = 0.0; - base_bl.y = base_br.y = src->height; - base_tl.x = base_bl.x = -src->width; - base_tr.x = base_br.x = 0.0; - repeat_direction = GLITZ_REPEAT_NORTHWEST; - break; - case GLITZ_REPEAT_NORTHWEST: + } else repeat_direction = GLITZ_REPEAT_NONE; - break; - case GLITZ_REPEAT_NONE: - break; - } - } else - repeat_direction = GLITZ_REPEAT_NONE; + } } } if (list) { - int i; - unsigned int mask = *dst->stencil_mask & ~0x1; - gl->end_list (); - for (i = 0; i < dst->multi_sample->n_samples; i++) { - if ((i + 1) == dst->multi_sample->n_samples) - glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_CLIP, - mask | (i + 1)); - else - glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_CLIP_EQUAL, - mask | (i + 1)); - - glitz_render_enable (type, src, NULL, dst, texture, NULL, - SHORT_MODULATE (dst->multi_sample->weights[i], - opacity)); - + if (dst->multi_sample) { + unsigned int mask = *dst->stencil_mask & ~0x1; + unsigned short alpha, opacity; + int i; + + glitz_render_op_get_alpha_mask (&render_op, NULL, NULL, NULL, &opacity); + + for (i = 0; i < dst->multi_sample->n_samples; i++) { + if ((i + 1) == dst->multi_sample->n_samples) + glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_CLIP, + mask | (i + 1)); + else + glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_CLIP_EQUAL, + mask | (i + 1)); + + alpha = SHORT_MULT (dst->multi_sample->weights[i], opacity); + glitz_render_op_set_alpha_mask (&render_op, 0x0, 0x0, 0x0, alpha); + + glitz_render_enable (&render_op); + + gl->call_list (list); + } + } else { + glitz_render_op_set_alpha_mask (&render_op, 0xffff, 0x0, 0x0, 0x0); + glitz_render_enable (&render_op); + gl->color_mask (1, 0, 0, 0); + gl->call_list (list); + + glitz_render_op_set_alpha_mask (&render_op, 0x0, 0x0, 0xffff, 0x0); + glitz_render_enable (&render_op); + gl->color_mask (0, 0, 1, 0); gl->call_list (list); + + if (render_op.component_alpha == GLITZ_COMPONENT_ALPHA_ARGB) { + glitz_render_op_set_alpha_mask (&render_op, 0x0, 0xffff, 0x0, 0x0); + glitz_render_enable (&render_op); + gl->color_mask (0, 1, 0, 0); + gl->call_list (list); + + glitz_render_op_set_alpha_mask (&render_op, 0x0, 0x0, 0x0, 0xffff); + glitz_render_enable (&render_op); + gl->color_mask (0, 0, 0, 1); + gl->call_list (list); + } else { + glitz_render_op_set_alpha_mask (&render_op, 0x0, 0xffff, 0x0, 0x0); + glitz_render_enable (&render_op); + gl->color_mask (0, 1, 0, 1); + gl->call_list (list); + } } gl->delete_lists (list, 1); } - - glitz_render_disable (type, dst); - - glitz_texture_unbind (gl, texture); + glitz_render_disable (&render_op); + + for (; texture_unit; texture_unit--) { + if (texture_unit == 1 && mask) + glitz_texture_unbind (gl, mask_texture); + else + glitz_texture_unbind (gl, texture); + + if (texture_unit > 1) + gl->active_texture (_texture_units[texture_unit - 1]); + } + if (SURFACE_CLEAR_EXTERIOR (dst)) { glitz_set_operator (gl, GLITZ_OPERATOR_SRC); - glitz_set_stencil_operator (dst->gl, - GLITZ_STENCIL_OPERATOR_CLIP_EQUAL, 0x0); + glitz_set_stencil_operator (gl, GLITZ_STENCIL_OPERATOR_CLIP_EQUAL, 0x0); - gl->color_4us (0x0000, 0x0000, 0x0000, 0x0000); + gl->color_mask (1, 1, 1, 1); + gl->color_4us (0x0, 0x0, 0x0, 0x0); gl->begin (GLITZ_GL_QUADS); gl->vertex_2d (0.0, 0.0); @@ -774,7 +752,7 @@ glitz_composite (glitz_operator_t op, glitz_surface_dirty (dst, &clip); glitz_surface_pop_current (dst); - + if (intermediate) glitz_surface_destroy (intermediate); } @@ -920,8 +898,6 @@ glitz_copy_area (glitz_surface_t *src, } if (!status) { - int rowstride = 1; - char *data; static glitz_pixel_format_t pf = { { 32, @@ -930,20 +906,24 @@ glitz_copy_area (glitz_surface_t *src, 0x0000ff00, 0x000000ff }, - 0, 0, + 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }; - - rowstride = (rowstride + 3) & -4; - data = malloc (height * rowstride); - if (!data) { + glitz_pixel_buffer_t *buffer = + glitz_pixel_buffer_create (src, + NULL, + width * height * 4, + GLITZ_PIXEL_BUFFER_HINT_STATIC_COPY); + if (!buffer) { glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); return; } + + glitz_pixel_buffer_set_format (buffer, &pf); - glitz_get_pixels (src, x_src, y_src, width, height, &pf, data); - glitz_put_pixels (dst, x_dst, y_dst, width, height, &pf, data); + glitz_get_pixels (src, x_src, y_src, width, height, buffer); + glitz_put_pixels (dst, x_dst, y_dst, width, height, buffer); - free (data); + glitz_pixel_buffer_destroy (buffer); } } diff --git a/src/glitz.h b/src/glitz.h index 217c490..63ef283 100644 --- a/src/glitz.h +++ b/src/glitz.h @@ -131,16 +131,20 @@ typedef enum { GLITZ_OPERATOR_SATURATE } glitz_operator_t; -#define GLITZ_FEATURE_OFFSCREEN_DRAWING_MASK (1L << 0) -#define GLITZ_FEATURE_CONVOLUTION_FILTER_MASK (1L << 1) -#define GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK (1L << 2) -#define GLITZ_FEATURE_TEXTURE_NPOT_MASK (1L << 3) -#define GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK (1L << 4) -#define GLITZ_FEATURE_MULTISAMPLE_MASK (1L << 5) -#define GLITZ_FEATURE_OFFSCREEN_MULTISAMPLE_MASK (1L << 6) -#define GLITZ_FEATURE_ARB_MULTITEXTURE_MASK (1L << 7) -#define GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 8) -#define GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 9) +#define GLITZ_FEATURE_OFFSCREEN_DRAWING_MASK (1L << 0) +#define GLITZ_FEATURE_CONVOLUTION_FILTER_MASK (1L << 1) +#define GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK (1L << 2) +#define GLITZ_FEATURE_TEXTURE_NPOT_MASK (1L << 3) +#define GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK (1L << 4) +#define GLITZ_FEATURE_MULTISAMPLE_MASK (1L << 5) +#define GLITZ_FEATURE_OFFSCREEN_MULTISAMPLE_MASK (1L << 6) +#define GLITZ_FEATURE_ARB_MULTITEXTURE_MASK (1L << 7) +#define GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK (1L << 8) +#define GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK (1L << 9) +#define GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 10) +#define GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 11) +#define GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK (1L << 12) +#define GLITZ_FEATURE_COMPONENT_ALPHA_MASK (1L << 13) typedef enum { GLITZ_STANDARD_ARGB32, @@ -215,10 +219,12 @@ typedef enum { const char * glitz_status_string (glitz_status_t status); + /* glitz_color_range.c */ +typedef struct _glitz_surface glitz_surface_t; typedef struct _glitz_color_range glitz_color_range_t; - + typedef enum { GLITZ_EXTEND_PAD, GLITZ_EXTEND_REPEAT, @@ -226,12 +232,13 @@ typedef enum { } glitz_extend_t; glitz_color_range_t * -glitz_color_range_create (unsigned int size); +glitz_color_range_create (glitz_surface_t *surface, + unsigned int size); void glitz_color_range_destroy (glitz_color_range_t *color_range); -unsigned char * +char * glitz_color_range_get_data (glitz_color_range_t *color_range); void @@ -248,8 +255,6 @@ glitz_color_range_set_extend (glitz_color_range_t *color_range, /* glitz_surface.c */ -typedef struct _glitz_surface glitz_surface_t; - typedef enum { GLITZ_POLYEDGE_SHARP, GLITZ_POLYEDGE_SMOOTH @@ -285,6 +290,10 @@ glitz_surface_set_repeat (glitz_surface_t *surface, glitz_bool_t repeat); void +glitz_surface_set_component_alpha (glitz_surface_t *surface, + glitz_bool_t component_alpha); + +void glitz_surface_set_filter (glitz_surface_t *surface, glitz_filter_t filter); @@ -405,7 +414,7 @@ glitz_surface_create_similar (glitz_surface_t *templ, unsigned long glitz_surface_get_hints (glitz_surface_t *surface); - + /* glitz_pixel.c */ @@ -425,18 +434,67 @@ typedef struct _glitz_pixel_masks { typedef struct _glitz_pixel_format { glitz_pixel_masks_t masks; int xoffset; + int skip_lines; int bytes_per_line; glitz_pixel_scanline_order_t scanline_order; } glitz_pixel_format_t; +typedef struct _glitz_pixel_buffer glitz_pixel_buffer_t; + +typedef enum { + GLITZ_PIXEL_BUFFER_HINT_STREAM_DRAW, + GLITZ_PIXEL_BUFFER_HINT_STREAM_READ, + GLITZ_PIXEL_BUFFER_HINT_STREAM_COPY, + GLITZ_PIXEL_BUFFER_HINT_STATIC_DRAW, + GLITZ_PIXEL_BUFFER_HINT_STATIC_READ, + GLITZ_PIXEL_BUFFER_HINT_STATIC_COPY, + GLITZ_PIXEL_BUFFER_HINT_DYNAMIC_DRAW, + GLITZ_PIXEL_BUFFER_HINT_DYNAMIC_READ, + GLITZ_PIXEL_BUFFER_HINT_DYNAMIC_COPY +} glitz_buffer_hint_t; + +glitz_pixel_buffer_t * +glitz_pixel_buffer_create (glitz_surface_t *surface, + char *data, + unsigned int size, + glitz_buffer_hint_t hint); + +glitz_pixel_buffer_t * +glitz_pixel_buffer_create_for_data (char *data, + glitz_pixel_format_t *format); + +void +glitz_pixel_buffer_destroy (glitz_pixel_buffer_t *buffer); + +void +glitz_pixel_buffer_set_format (glitz_pixel_buffer_t *buffer, + glitz_pixel_format_t *format); + +void +glitz_pixel_buffer_get_format (glitz_pixel_buffer_t *buffer, + glitz_pixel_format_t *format); + +typedef enum { + GLITZ_PIXEL_BUFFER_ACCESS_READ_ONLY, + GLITZ_PIXEL_BUFFER_ACCESS_WRITE_ONLY, + GLITZ_PIXEL_BUFFER_ACCESS_READ_WRITE +} glitz_pixel_buffer_access_t; + +char * +glitz_pixel_buffer_get_data (glitz_pixel_buffer_t *buffer, + glitz_pixel_buffer_access_t access); + +void +glitz_pixel_buffer_put_back_data (glitz_pixel_buffer_t *buffer); + void glitz_put_pixels (glitz_surface_t *dst, int x_dst, int y_dst, int width, int height, - glitz_pixel_format_t *format, - char *pixels); + glitz_pixel_buffer_t *buffer); + void glitz_get_pixels (glitz_surface_t *src, @@ -444,9 +502,8 @@ glitz_get_pixels (glitz_surface_t *src, int y_src, int width, int height, - glitz_pixel_format_t *format, - char *pixels); - + glitz_pixel_buffer_t *buffer); + /* glitz_rect.c */ diff --git a/src/glitz_agl_context.c b/src/glitz_agl_context.c index e25c11e..01e5c3c 100644 --- a/src/glitz_agl_context.c +++ b/src/glitz_agl_context.c @@ -88,17 +88,17 @@ glitz_agl_context_set_surface_anti_aliasing (glitz_agl_surface_t *surface) { if (surface->base.format->multisample.supported) { if (surface->base.polyedge == GLITZ_POLYEDGE_SMOOTH) { - glEnable (GLITZ_GL_MULTISAMPLE_ARB); + glEnable (GLITZ_GL_MULTISAMPLE); if (surface->thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_FILTER_MASK) { if (surface->base.polyedge_smooth_hint == GLITZ_POLYEDGE_SMOOTH_HINT_FAST) - glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT_NV, GLITZ_GL_FASTEST); + glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT, GLITZ_GL_FASTEST); else - glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT_NV, GLITZ_GL_NICEST); + glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT, GLITZ_GL_NICEST); } } else - glDisable (GLITZ_GL_MULTISAMPLE_ARB); + glDisable (GLITZ_GL_MULTISAMPLE); } } diff --git a/src/glitz_agl_extension.c b/src/glitz_agl_extension.c index afc2f52..296b3ec 100644 --- a/src/glitz_agl_extension.c +++ b/src/glitz_agl_extension.c @@ -38,12 +38,16 @@ static glitz_extension_map gl_extensions[] = { { "GL_ARB_texture_non_power_of_two", GLITZ_AGL_FEATURE_TEXTURE_NPOT_MASK }, { "GL_ARB_texture_mirrored_repeat", GLITZ_AGL_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK }, + { "GL_ARB_texture_env_combine", + GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK }, + { "GL_ARB_texture_env_dot3", GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK }, { "GL_ARB_multisample", GLITZ_AGL_FEATURE_MULTISAMPLE_MASK }, { "GL_NV_multisample_filter_hint", GLITZ_AGL_FEATURE_MULTISAMPLE_FILTER_MASK }, { "GL_ARB_multitexture", GLITZ_AGL_FEATURE_ARB_MULTITEXTURE_MASK }, { "GL_ARB_vertex_program", GLITZ_AGL_FEATURE_ARB_VERTEX_PROGRAM_MASK }, { "GL_ARB_fragment_program", GLITZ_AGL_FEATURE_ARB_FRAGMENT_PROGRAM_MASK }, + { "GL_EXT_pixel_buffer_object", GLITZ_AGL_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, { NULL, 0 } }; @@ -98,6 +102,25 @@ glitz_agl_query_extensions (glitz_agl_thread_info_t *thread_info) if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_ARB_MULTITEXTURE_MASK) { thread_info->feature_mask |= GLITZ_FEATURE_ARB_MULTITEXTURE_MASK; + + if (thread_info->agl_feature_mask & + GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK) + thread_info->feature_mask |= GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK; + + if (thread_info->agl_feature_mask & + GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK) + thread_info->feature_mask |= GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK; + + if ((thread_info->feature_mask & + GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK) && + (thread_info->feature_mask & + GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK)) { + GLint max_texture_units; + + glGetIntegerv (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units); + if (max_texture_units >= 3) + thread_info->feature_mask |= GLITZ_FEATURE_COMPONENT_ALPHA_MASK; + } if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_ARB_VERTEX_PROGRAM_MASK) @@ -107,4 +130,8 @@ glitz_agl_query_extensions (glitz_agl_thread_info_t *thread_info) GLITZ_AGL_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) thread_info->feature_mask |= GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK; } + + if (thread_info->agl_feature_mask & + GLITZ_AGL_FEATURE_PIXEL_BUFFER_OBJECT_MASK) + thread_info->feature_mask |= GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; } diff --git a/src/glitz_agl_info.c b/src/glitz_agl_info.c index 26e4cda..06d098a 100644 --- a/src/glitz_agl_info.c +++ b/src/glitz_agl_info.c @@ -41,8 +41,10 @@ glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = { (glitz_gl_vertex_2i_t) glVertex2i, (glitz_gl_vertex_2d_t) glVertex2d, (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, (glitz_gl_tex_coord_2d_t) glTexCoord2d, (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4d_t) glColor4d, (glitz_gl_scissor_t) glScissor, (glitz_gl_blend_func_t) glBlendFunc, (glitz_gl_clear_t) glClear, @@ -91,14 +93,20 @@ glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = { (glitz_gl_end_list_t) glEndList, (glitz_gl_call_list_t) glCallList, - (glitz_gl_active_texture_arb_t) glActiveTextureARB, - (glitz_gl_multi_tex_coord_2d_arb_t) glMultiTexCoord2dARB, - (glitz_gl_gen_programs_arb_t) glGenProgramsARB, - (glitz_gl_delete_programs_arb_t) glDeleteProgramsARB, - (glitz_gl_program_string_arb_t) glProgramStringARB, - (glitz_gl_bind_program_arb_t) glBindProgramARB, - (glitz_gl_program_local_param_4d_arb_t) glProgramLocalParameter4dARB, - (glitz_gl_get_program_iv_arb_t) glGetProgramivARB, + (glitz_gl_active_texture_t) glActiveTextureARB, + (glitz_gl_multi_tex_coord_2d_t) glMultiTexCoord2dARB, + (glitz_gl_gen_programs_t) glGenProgramsARB, + (glitz_gl_delete_programs_t) glDeleteProgramsARB, + (glitz_gl_program_string_t) glProgramStringARB, + (glitz_gl_bind_program_t) glBindProgramARB, + (glitz_gl_program_local_param_4d_t) glProgramLocalParameter4dARB, + (glitz_gl_get_program_iv_t) glGetProgramivARB, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0, 0 }; @@ -127,17 +135,25 @@ glitz_agl_thread_info_destroy (void *p) glitz_agl_thread_info_t * glitz_agl_thread_info_get (void) { + glitz_agl_thread_info_t *thread_info; + void *p; + if (!tsd_initialized) { - glitz_agl_thread_info_t *info = malloc (sizeof (glitz_agl_thread_info_t)); - glitz_agl_thread_info_init (info); - pthread_key_create (&info_tsd, glitz_agl_thread_info_destroy); - pthread_setspecific (info_tsd, info); - tsd_initialized = 1; - return info; + } + + p = pthread_getspecific (info_tsd); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_agl_thread_info_t)); + glitz_agl_thread_info_init (thread_info); + + pthread_setspecific (info_tsd, thread_info); } else - return (glitz_agl_thread_info_t *) pthread_getspecific (info_tsd); + thread_info = (glitz_agl_thread_info_t *) p; + + return thread_info; } #else @@ -185,7 +201,7 @@ glitz_agl_thread_info_init (glitz_agl_thread_info_t *thread_info) thread_info->contexts = NULL; thread_info->n_contexts = 0; - memset (&thread_info->programs, 0, sizeof (glitz_programs_t)); + glitz_program_map_init (&thread_info->program_map); thread_info->root_context.pixel_format = aglChoosePixelFormat (NULL, 0, attrib); @@ -201,9 +217,9 @@ glitz_agl_thread_info_init (glitz_agl_thread_info_t *thread_info) GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK)) { glitz_gl_uint_t texture_indirections; - _glitz_agl_gl_proc_address.get_program_iv_arb - (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, + _glitz_agl_gl_proc_address.get_program_iv + (GLITZ_GL_FRAGMENT_PROGRAM, + GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, &texture_indirections); /* Convolution filter programs require support for at least nine @@ -226,8 +242,8 @@ glitz_agl_thread_info_fini (glitz_agl_thread_info_t *thread_info) int i; aglSetCurrentContext (thread_info->root_context.context); - glitz_programs_fini (&_glitz_agl_gl_proc_address, - &thread_info->programs); + glitz_program_map_fini (&_glitz_agl_gl_proc_address, + &thread_info->program_map); aglSetCurrentContext (NULL); if (thread_info->context_stack) @@ -246,8 +262,6 @@ glitz_agl_thread_info_fini (glitz_agl_thread_info_t *thread_info) free (thread_info->format_ids); aglDestroyContext (thread_info->root_context.context); - - free (thread_info); } void diff --git a/src/glitz_agl_surface.c b/src/glitz_agl_surface.c index 6c0cfef..e97bdb3 100644 --- a/src/glitz_agl_surface.c +++ b/src/glitz_agl_surface.c @@ -215,7 +215,7 @@ _glitz_agl_surface_create (glitz_agl_thread_info_t *thread_info, thread_info->n_formats, width, height, - &thread_info->programs, + &thread_info->program_map, texture_mask); surface->thread_info = thread_info; @@ -279,7 +279,7 @@ glitz_agl_surface_create_for_window (glitz_format_t *format, thread_info->n_formats, width, height, - &thread_info->programs, + &thread_info->program_map, thread_info->texture_mask); surface->thread_info = thread_info; diff --git a/src/glitz_aglint.h b/src/glitz_aglint.h index 913a30e..cec527d 100644 --- a/src/glitz_aglint.h +++ b/src/glitz_aglint.h @@ -36,15 +36,18 @@ #include <Carbon/Carbon.h> #include <AGL/agl.h> -#define GLITZ_AGL_FEATURE_PBUFFER_MASK (1L << 0) -#define GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK (1L << 1) -#define GLITZ_AGL_FEATURE_TEXTURE_NPOT_MASK (1L << 2) -#define GLITZ_AGL_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK (1L << 3) -#define GLITZ_AGL_FEATURE_MULTISAMPLE_MASK (1L << 4) -#define GLITZ_AGL_FEATURE_MULTISAMPLE_FILTER_MASK (1L << 5) -#define GLITZ_AGL_FEATURE_ARB_MULTITEXTURE_MASK (1L << 6) -#define GLITZ_AGL_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 7) -#define GLITZ_AGL_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 8) +#define GLITZ_AGL_FEATURE_PBUFFER_MASK (1L << 0) +#define GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK (1L << 1) +#define GLITZ_AGL_FEATURE_TEXTURE_NPOT_MASK (1L << 2) +#define GLITZ_AGL_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK (1L << 3) +#define GLITZ_AGL_FEATURE_MULTISAMPLE_MASK (1L << 4) +#define GLITZ_AGL_FEATURE_MULTISAMPLE_FILTER_MASK (1L << 5) +#define GLITZ_AGL_FEATURE_ARB_MULTITEXTURE_MASK (1L << 6) +#define GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK (1L << 7) +#define GLITZ_AGL_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK (1L << 8) +#define GLITZ_AGL_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 9) +#define GLITZ_AGL_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 10) +#define GLITZ_AGL_FEATURE_PIXEL_BUFFER_OBJECT_MASK (1L << 11) typedef struct _glitz_agl_surface_t glitz_agl_surface_t; @@ -77,7 +80,7 @@ typedef struct _glitz_agl_thread_info_t { long int agl_feature_mask; long int texture_mask; - glitz_programs_t programs; + glitz_program_map_t program_map; } glitz_agl_thread_info_t; struct _glitz_agl_surface_t { diff --git a/src/glitz_color_range.c b/src/glitz_color_range.c index 62a91a5..d31a45a 100644 --- a/src/glitz_color_range.c +++ b/src/glitz_color_range.c @@ -31,32 +31,25 @@ #include "glitzint.h" -static void -glitz_color_range_init (glitz_color_range_t *color_range, - unsigned int size) -{ - color_range->texture = 0; - color_range->filter = GLITZ_FILTER_NEAREST; - color_range->extend = GLITZ_EXTEND_PAD; - color_range->ref_count = 1; - color_range->data = malloc (size * 4); - color_range->size = size; - color_range->update_mask = GLITZ_COLOR_RANGE_UPDATE_ALL_MASK; - color_range->delete_textures = NULL; -} - -static void -glitz_color_range_fini (glitz_color_range_t *color_range) -{ - if (color_range->texture) - color_range->delete_textures (1, &color_range->texture); - - if (color_range->data) - free (color_range->data); -} +#define GLITZ_COLOR_RANGE_UPDATE_TEXTURE_MASK (1L << 0) +#define GLITZ_COLOR_RANGE_UPDATE_FILTER_MASK (1L << 1) +#define GLITZ_COLOR_RANGE_UPDATE_EXTEND_MASK (1L << 2) +#define GLITZ_COLOR_RANGE_UPDATE_ALL_MASK ((1L << 3) - 1) + +struct _glitz_color_range { + unsigned int size; + glitz_gl_uint_t texture; + glitz_filter_t filter; + glitz_extend_t extend; + unsigned long update_mask; + unsigned int ref_count; + glitz_pixel_buffer_t *buffer; + glitz_surface_t *surface; +}; glitz_color_range_t * -glitz_color_range_create (unsigned int size) +glitz_color_range_create (glitz_surface_t *surface, + unsigned int size) { glitz_color_range_t *color_range; @@ -64,13 +57,30 @@ glitz_color_range_create (unsigned int size) if (!color_range) return NULL; - glitz_color_range_init (color_range, size); + color_range->texture = 0; + color_range->filter = GLITZ_FILTER_NEAREST; + color_range->extend = GLITZ_EXTEND_PAD; + color_range->ref_count = 1; - if (!color_range->data) { + /* If data is not POT and NPOT texture support is missing we force + the size to POT */ + if ((!(surface->feature_mask & GLITZ_FEATURE_TEXTURE_NPOT_MASK)) && + (!glitz_uint_is_power_of_two (size))) + glitz_uint_to_power_of_two (&size); + + color_range->size = size; + color_range->buffer = + glitz_pixel_buffer_create (surface, NULL, size * 4 /* ARGB32 */, + GLITZ_PIXEL_BUFFER_HINT_STATIC_DRAW); + if (color_range->buffer == NULL) { free (color_range); return NULL; } + color_range->update_mask = GLITZ_COLOR_RANGE_UPDATE_ALL_MASK; + color_range->surface = surface; + glitz_surface_reference (surface); + return color_range; } slim_hidden_def(glitz_color_range_create); @@ -79,7 +89,7 @@ void glitz_color_range_reference (glitz_color_range_t *color_range) { if (color_range == NULL) - return; + return; color_range->ref_count++; } @@ -94,7 +104,19 @@ glitz_color_range_destroy (glitz_color_range_t *color_range) if (color_range->ref_count) return; - glitz_color_range_fini (color_range); + glitz_pixel_buffer_destroy (color_range->buffer); + + if (color_range->texture) { + glitz_surface_push_current (color_range->surface, + GLITZ_CN_ANY_CONTEXT_CURRENT); + + color_range->surface->gl->delete_textures (1, &color_range->texture); + + glitz_surface_pop_current (color_range->surface); + } + + glitz_surface_destroy (color_range->surface); + free (color_range); } @@ -104,23 +126,16 @@ glitz_color_range_bind (glitz_gl_proc_address_list_t *gl, unsigned long feature_mask) { if (color_range->update_mask & GLITZ_COLOR_RANGE_UPDATE_TEXTURE_MASK) { + char *data; - if (!color_range->texture) { + if (!color_range->texture) gl->gen_textures (1, &color_range->texture); - color_range->delete_textures = gl->delete_textures; - } gl->enable (GLITZ_GL_TEXTURE_1D); gl->bind_texture (GLITZ_GL_TEXTURE_1D, color_range->texture); - - /* If data is not POT and NPOT texture support is missing we reallocate - a POT sized memory block for glTexImage1D */ - if ((!(feature_mask & GLITZ_FEATURE_TEXTURE_NPOT_MASK)) && - (!glitz_uint_is_power_of_two (color_range->size))) { - glitz_uint_to_power_of_two (&color_range->size); - - color_range->data = realloc (color_range->data, color_range->size * 4); - } + + data = glitz_pixel_buffer_bind (color_range->buffer, + GLITZ_GL_PIXEL_UNPACK_BUFFER); gl->tex_image_1d (GLITZ_GL_TEXTURE_1D, 0, GLITZ_GL_RGBA, color_range->size, 0, @@ -132,7 +147,9 @@ glitz_color_range_bind (glitz_gl_proc_address_list_t *gl, GLITZ_GL_UNSIGNED_BYTE, #endif - color_range->data); + data); + + glitz_pixel_buffer_unbind (color_range->buffer); color_range->update_mask &= ~GLITZ_COLOR_RANGE_UPDATE_TEXTURE_MASK; } else { @@ -185,7 +202,7 @@ glitz_color_range_bind (glitz_gl_proc_address_list_t *gl, if (feature_mask & GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK) gl->tex_parameter_i (GLITZ_GL_TEXTURE_1D, GLITZ_GL_TEXTURE_WRAP_S, - GLITZ_GL_MIRRORED_REPEAT_ARB); + GLITZ_GL_MIRRORED_REPEAT); else gl->tex_parameter_i (GLITZ_GL_TEXTURE_1D, GLITZ_GL_TEXTURE_WRAP_S, @@ -196,16 +213,19 @@ glitz_color_range_bind (glitz_gl_proc_address_list_t *gl, } } -unsigned char * +char * glitz_color_range_get_data (glitz_color_range_t *color_range) { - return color_range->data; + return glitz_pixel_buffer_get_data (color_range->buffer, + GLITZ_PIXEL_BUFFER_ACCESS_WRITE_ONLY); } slim_hidden_def(glitz_color_range_get_data); void glitz_color_range_put_back_data (glitz_color_range_t *color_range) { + glitz_pixel_buffer_put_back_data (color_range->buffer); + color_range->update_mask |= GLITZ_COLOR_RANGE_UPDATE_TEXTURE_MASK; } slim_hidden_def(glitz_color_range_put_back_data); diff --git a/src/glitz_format.c b/src/glitz_format.c index 48d530c..f77bf80 100644 --- a/src/glitz_format.c +++ b/src/glitz_format.c @@ -35,13 +35,13 @@ static glitz_format_t _texture_formats[] = { { - GLITZ_GL_INTENSITY4, 0, 0, 0, 4, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } + GLITZ_GL_ALPHA4, 0, 0, 0, 4, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } }, { - GLITZ_GL_INTENSITY8, 0, 0, 0, 8, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } + GLITZ_GL_ALPHA8, 0, 0, 0, 8, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } }, { - GLITZ_GL_INTENSITY12, 0, 0, 0, 12, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } + GLITZ_GL_ALPHA12, 0, 0, 0, 12, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } }, { - GLITZ_GL_INTENSITY16, 0, 0, 0, 16, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } + GLITZ_GL_ALPHA16, 0, 0, 0, 16, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } }, { GLITZ_GL_R3_G3_B2, 3, 3, 2, 0, 0, 0, 0, { 0, 1 }, { 0, 0 }, { 0, 0 } }, { @@ -106,12 +106,8 @@ glitz_format_for_each_texture_format (glitz_format_call_back_t call_back, gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, GLITZ_GL_TEXTURE_ALPHA_SIZE, &value); - if (value != _texture_formats[i].alpha_size) { - gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, - GLITZ_GL_TEXTURE_INTENSITY_SIZE, &value); - if (value != _texture_formats[i].alpha_size) - continue; - } + if (value != _texture_formats[i].alpha_size) + continue; call_back (&_texture_formats[i], ptr); } diff --git a/src/glitz_gl.h b/src/glitz_gl.h index 82f2d99..43a673d 100644 --- a/src/glitz_gl.h +++ b/src/glitz_gl.h @@ -28,6 +28,8 @@ #ifndef GLITZ_GL_H_INCLUDED #define GLITZ_GL_H_INCLUDED +#include <stddef.h> + typedef unsigned int glitz_gl_enum_t; typedef unsigned char glitz_gl_boolean_t; typedef void glitz_gl_void_t; @@ -41,6 +43,8 @@ typedef unsigned int glitz_gl_bitfield_t; typedef double glitz_gl_clampd_t; typedef float glitz_gl_clampf_t; typedef unsigned char glitz_gl_ubyte_t; +typedef ptrdiff_t glitz_gl_sizeiptr_t; + #define GLITZ_GL_FALSE 0x0 #define GLITZ_GL_TRUE 0x1 @@ -83,6 +87,7 @@ typedef unsigned char glitz_gl_ubyte_t; #define GLITZ_GL_TEXTURE_WRAP_T 0x2803 #define GLITZ_GL_TEXTURE_MAG_FILTER 0x2800 #define GLITZ_GL_TEXTURE_MIN_FILTER 0x2801 +#define GLITZ_GL_TEXTURE_ENV_COLOR 0x2201 #define GLITZ_GL_MODULATE 0x2100 #define GLITZ_GL_NEAREST 0x2600 #define GLITZ_GL_LINEAR 0x2601 @@ -92,7 +97,34 @@ typedef unsigned char glitz_gl_ubyte_t; #define GLITZ_GL_TEXTURE_GREEN_SIZE 0x805D #define GLITZ_GL_TEXTURE_BLUE_SIZE 0x805E #define GLITZ_GL_TEXTURE_ALPHA_SIZE 0x805F -#define GLITZ_GL_TEXTURE_INTENSITY_SIZE 0x8061 + +#define GLITZ_GL_TEXTURE 0x1702 +#define GLITZ_GL_SRC_COLOR 0x0300 + +#define GLITZ_GL_COMBINE 0x8570 +#define GLITZ_GL_COMBINE_RGB 0x8571 +#define GLITZ_GL_COMBINE_ALPHA 0x8572 +#define GLITZ_GL_SOURCE0_RGB 0x8580 +#define GLITZ_GL_SOURCE1_RGB 0x8581 +#define GLITZ_GL_SOURCE2_RGB 0x8582 +#define GLITZ_GL_SOURCE0_ALPHA 0x8588 +#define GLITZ_GL_SOURCE1_ALPHA 0x8589 +#define GLITZ_GL_SOURCE2_ALPHA 0x858A +#define GLITZ_GL_OPERAND0_RGB 0x8590 +#define GLITZ_GL_OPERAND1_RGB 0x8591 +#define GLITZ_GL_OPERAND2_RGB 0x8592 +#define GLITZ_GL_OPERAND0_ALPHA 0x8598 +#define GLITZ_GL_OPERAND1_ALPHA 0x8599 +#define GLITZ_GL_OPERAND2_ALPHA 0x859A +#define GLITZ_GL_RGB_SCALE 0x8573 +#define GLITZ_GL_ADD_SIGNED 0x8574 +#define GLITZ_GL_INTERPOLATE 0x8575 +#define GLITZ_GL_SUBTRACT 0x84E7 +#define GLITZ_GL_CONSTANT 0x8576 +#define GLITZ_GL_PRIMARY_COLOR 0x8577 +#define GLITZ_GL_PREVIOUS 0x8578 +#define GLITZ_GL_DOT3_RGB 0x86AE +#define GLITZ_GL_DOT3_RGBA 0x86AF #define GLITZ_GL_STENCIL_TEST 0x0B90 #define GLITZ_GL_KEEP 0x1E00 @@ -120,25 +152,24 @@ typedef unsigned char glitz_gl_ubyte_t; #define GLITZ_GL_BGR 0x80E0 #define GLITZ_GL_BGRA 0x80E1 -#define GLITZ_GL_INTENSITY 0x8049 -#define GLITZ_GL_INTENSITY4 0x804A -#define GLITZ_GL_INTENSITY8 0x804B -#define GLITZ_GL_INTENSITY12 0x804C -#define GLITZ_GL_INTENSITY16 0x804D -#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_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 @@ -168,26 +199,45 @@ typedef unsigned char glitz_gl_ubyte_t; #define GLITZ_GL_COMPILE 0x1300 -#define GLITZ_GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#define GLITZ_GL_TEXTURE_RECTANGLE 0x84F5 + +#define GLITZ_GL_MIRRORED_REPEAT 0x8370 -#define GLITZ_GL_MIRRORED_REPEAT_ARB 0x8370 +#define GLITZ_GL_TEXTURE0 0x84C0 +#define GLITZ_GL_TEXTURE1 0x84C1 +#define GLITZ_GL_TEXTURE2 0x84C2 +#define GLITZ_GL_ACTIVE_TEXTURE 0x84E0 +#define GLITZ_GL_MAX_TEXTURE_UNITS 0x84E2 -#define GLITZ_GL_TEXTURE0_ARB 0x84C0 -#define GLITZ_GL_TEXTURE1_ARB 0x84C1 -#define GLITZ_GL_TEXTURE2_ARB 0x84C2 -#define GLITZ_GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GLITZ_GL_MULTISAMPLE 0x809D -#define GLITZ_GL_MULTISAMPLE_ARB 0x809D +#define GLITZ_GL_MULTISAMPLE_FILTER_HINT 0x8534 -#define GLITZ_GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 +#define GLITZ_GL_VERTEX_PROGRAM 0x8620 +#define GLITZ_GL_PROGRAM_STRING 0x8628 +#define GLITZ_GL_PROGRAM_FORMAT_ASCII 0x8875 +#define GLITZ_GL_PROGRAM_ERROR_POSITION 0x864B -#define GLITZ_GL_VERTEX_PROGRAM_ARB 0x8620 -#define GLITZ_GL_PROGRAM_STRING_ARB 0x8628 -#define GLITZ_GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 -#define GLITZ_GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GLITZ_GL_FRAGMENT_PROGRAM 0x8804 +#define GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS 0x880D + +#define GLITZ_GL_PIXEL_PACK_BUFFER 0x88EB +#define GLITZ_GL_PIXEL_UNPACK_BUFFER 0x88EC + +#define GLITZ_GL_STREAM_DRAW 0x88E0 +#define GLITZ_GL_STREAM_READ 0x88E1 +#define GLITZ_GL_STREAM_COPY 0x88E2 +#define GLITZ_GL_STATIC_DRAW 0x88E4 +#define GLITZ_GL_STATIC_READ 0x88E5 +#define GLITZ_GL_STATIC_COPY 0x88E6 +#define GLITZ_GL_DYNAMIC_DRAW 0x88E8 +#define GLITZ_GL_DYNAMIC_READ 0x88E9 +#define GLITZ_GL_DYNAMIC_COPY 0x88EA + +#define GLITZ_GL_READ_ONLY 0x88B8 +#define GLITZ_GL_WRITE_ONLY 0x88B9 +#define GLITZ_GL_READ_WRITE 0x88BA -#define GLITZ_GL_FRAGMENT_PROGRAM_ARB 0x8804 -#define GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D typedef glitz_gl_void_t (* glitz_gl_enable_t) (glitz_gl_enum_t cap); @@ -203,6 +253,9 @@ typedef glitz_gl_void_t (* glitz_gl_vertex_2d_t) (glitz_gl_double_t x, glitz_gl_double_t y); typedef glitz_gl_void_t (* glitz_gl_tex_env_f_t) (glitz_gl_enum_t target, glitz_gl_enum_t pname, glitz_gl_float_t param); +typedef glitz_gl_void_t (* glitz_gl_tex_env_fv_t) + (glitz_gl_enum_t target, glitz_gl_enum_t pname, + const glitz_gl_float_t *params); typedef glitz_gl_void_t (* glitz_gl_tex_coord_2d_t) (glitz_gl_double_t s, glitz_gl_double_t t); typedef glitz_gl_void_t (* glitz_gl_scissor_t) @@ -211,6 +264,9 @@ typedef glitz_gl_void_t (* glitz_gl_scissor_t) typedef glitz_gl_void_t (* glitz_gl_color_4us_t) (glitz_gl_ushort_t red, glitz_gl_ushort_t green, glitz_gl_ushort_t blue, glitz_gl_ushort_t alpha); +typedef glitz_gl_void_t (* glitz_gl_color_4d_t) + (glitz_gl_double_t red, glitz_gl_double_t green, glitz_gl_double_t blue, + glitz_gl_double_t alpha); typedef glitz_gl_void_t (* glitz_gl_blend_func_t) (glitz_gl_enum_t sfactor, glitz_gl_enum_t dfactor); typedef glitz_gl_void_t (* glitz_gl_clear_t) @@ -326,6 +382,8 @@ typedef glitz_gl_void_t (* glitz_gl_copy_tex_sub_image_2d_t) glitz_gl_sizei_t width, glitz_gl_sizei_t height); typedef glitz_gl_void_t (* glitz_gl_get_integer_v_t) (glitz_gl_enum_t pname, glitz_gl_int_t *params); +typedef glitz_gl_void_t (* glitz_gl_get_pointer_v_t) + (glitz_gl_enum_t pname, glitz_gl_void_t **params); typedef glitz_gl_void_t (* glitz_gl_delete_lists_t) (glitz_gl_uint_t list, glitz_gl_sizei_t range); typedef glitz_gl_uint_t (* glitz_gl_gen_lists_t) @@ -336,24 +394,37 @@ typedef glitz_gl_void_t (* glitz_gl_end_list_t) (glitz_gl_void_t); typedef glitz_gl_void_t (* glitz_gl_call_list_t) (glitz_gl_uint_t list); -typedef glitz_gl_void_t (* glitz_gl_active_texture_arb_t) +typedef glitz_gl_void_t (* glitz_gl_active_texture_t) (glitz_gl_enum_t); -typedef glitz_gl_void_t (* glitz_gl_multi_tex_coord_2d_arb_t) +typedef glitz_gl_void_t (* glitz_gl_multi_tex_coord_2d_t) (glitz_gl_enum_t, glitz_gl_double_t, glitz_gl_double_t); -typedef glitz_gl_void_t (* glitz_gl_gen_programs_arb_t) +typedef glitz_gl_void_t (* glitz_gl_gen_programs_t) (glitz_gl_sizei_t, glitz_gl_uint_t *); -typedef glitz_gl_void_t (* glitz_gl_delete_programs_arb_t) +typedef glitz_gl_void_t (* glitz_gl_delete_programs_t) (glitz_gl_sizei_t, const glitz_gl_uint_t *); -typedef glitz_gl_void_t (* glitz_gl_program_string_arb_t) +typedef glitz_gl_void_t (* glitz_gl_program_string_t) (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_sizei_t, const glitz_gl_void_t *); -typedef glitz_gl_void_t (* glitz_gl_bind_program_arb_t) +typedef glitz_gl_void_t (* glitz_gl_bind_program_t) (glitz_gl_enum_t, glitz_gl_uint_t); -typedef glitz_gl_void_t (* glitz_gl_program_local_param_4d_arb_t) +typedef glitz_gl_void_t (* glitz_gl_program_local_param_4d_t) (glitz_gl_enum_t, glitz_gl_uint_t, glitz_gl_double_t, glitz_gl_double_t, glitz_gl_double_t, glitz_gl_double_t); -typedef glitz_gl_void_t (* glitz_gl_get_program_iv_arb_t) +typedef glitz_gl_void_t (* glitz_gl_get_program_iv_t) (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_uint_t *); +typedef glitz_gl_void_t (* glitz_gl_gen_buffers_t) + (glitz_gl_sizei_t, glitz_gl_uint_t *buffers); +typedef glitz_gl_void_t (* glitz_gl_delete_buffers_t) + (glitz_gl_sizei_t, const glitz_gl_uint_t *buffers); +typedef glitz_gl_void_t (* glitz_gl_bind_buffer_t) + (glitz_gl_enum_t, glitz_gl_uint_t buffer); +typedef glitz_gl_void_t (* glitz_gl_buffer_data_t) + (glitz_gl_enum_t, glitz_gl_sizeiptr_t, const glitz_gl_void_t *, + glitz_gl_enum_t); +typedef glitz_gl_void_t *(* glitz_gl_map_buffer_t) + (glitz_gl_enum_t, glitz_gl_enum_t); +typedef glitz_gl_boolean_t (* glitz_gl_unmap_buffer_t) + (glitz_gl_enum_t); #endif /* GLITZ_GL_H_INCLUDED */ diff --git a/src/glitz_glx_context.c b/src/glitz_glx_context.c index c062038..711ca13 100644 --- a/src/glitz_glx_context.c +++ b/src/glitz_glx_context.c @@ -203,45 +203,63 @@ glitz_glx_context_proc_address_lookup (glitz_glx_screen_info_t *screen_info, glitz_glx_thread_info_t *thread_info = screen_info->display_info->thread_info; - context->glx.bind_tex_image_arb = - (glitz_glx_bind_tex_image_arb_t) + context->glx.bind_tex_image = + (glitz_glx_bind_tex_image_t) glitz_glx_get_proc_address (thread_info, "glXBindTexImageARB"); - context->glx.release_tex_image_arb = - (glitz_glx_release_tex_image_arb_t) + context->glx.release_tex_image = + (glitz_glx_release_tex_image_t) glitz_glx_get_proc_address (thread_info, "glXReleaseTexImageARB"); - context->gl.active_texture_arb = - (glitz_gl_active_texture_arb_t) + context->gl.active_texture = + (glitz_gl_active_texture_t) glitz_glx_get_proc_address (thread_info, "glActiveTextureARB"); - context->gl.multi_tex_coord_2d_arb = - (glitz_gl_multi_tex_coord_2d_arb_t) + context->gl.multi_tex_coord_2d = + (glitz_gl_multi_tex_coord_2d_t) glitz_glx_get_proc_address (thread_info, "glMultiTexCoord2dARB"); - context->gl.gen_programs_arb = - (glitz_gl_gen_programs_arb_t) + context->gl.gen_programs = + (glitz_gl_gen_programs_t) glitz_glx_get_proc_address (thread_info, "glGenProgramsARB"); - context->gl.delete_programs_arb = - (glitz_gl_delete_programs_arb_t) + context->gl.delete_programs = + (glitz_gl_delete_programs_t) glitz_glx_get_proc_address (thread_info, "glDeleteProgramsARB"); - context->gl.program_string_arb = - (glitz_gl_program_string_arb_t) + context->gl.program_string = + (glitz_gl_program_string_t) glitz_glx_get_proc_address (thread_info, "glProgramStringARB"); - context->gl.bind_program_arb = - (glitz_gl_bind_program_arb_t) + context->gl.bind_program = + (glitz_gl_bind_program_t) glitz_glx_get_proc_address (thread_info, "glBindProgramARB"); - context->gl.program_local_param_4d_arb = - (glitz_gl_program_local_param_4d_arb_t) + context->gl.program_local_param_4d = + (glitz_gl_program_local_param_4d_t) glitz_glx_get_proc_address (thread_info, "glProgramLocalParameter4dARB"); - context->gl.get_program_iv_arb = - (glitz_gl_get_program_iv_arb_t) + context->gl.get_program_iv = + (glitz_gl_get_program_iv_t) glitz_glx_get_proc_address (thread_info, "glGetProgramivARB"); + context->gl.gen_buffers = + (glitz_gl_gen_buffers_t) + glitz_glx_get_proc_address (thread_info, "glGenBuffers"); + context->gl.delete_buffers = + (glitz_gl_delete_buffers_t) + glitz_glx_get_proc_address (thread_info, "glDeleteBuffers"); + context->gl.bind_buffer = + (glitz_gl_bind_buffer_t) + glitz_glx_get_proc_address (thread_info, "glBindBuffer"); + context->gl.buffer_data = + (glitz_gl_buffer_data_t) + glitz_glx_get_proc_address (thread_info, "glBufferData"); + context->gl.map_buffer = + (glitz_gl_map_buffer_t) + glitz_glx_get_proc_address (thread_info, "glMapBuffer"); + context->gl.unmap_buffer = + (glitz_gl_unmap_buffer_t) + glitz_glx_get_proc_address (thread_info, "glUnmapBuffer"); + if (screen_info->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) { - if (context->gl.get_program_iv_arb) { - context->gl.get_program_iv_arb - (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, - &context->texture_indirections); + if (context->gl.get_program_iv) { + context->gl.get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, + GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, + &context->texture_indirections); } } @@ -254,17 +272,17 @@ glitz_glx_context_set_surface_anti_aliasing (glitz_glx_surface_t *surface) { if (surface->base.format->multisample.supported) { if (surface->base.polyedge == GLITZ_POLYEDGE_SMOOTH) { - glEnable (GLITZ_GL_MULTISAMPLE_ARB); + glEnable (GLITZ_GL_MULTISAMPLE); if (surface->screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_FILTER_MASK) { if (surface->base.polyedge_smooth_hint == GLITZ_POLYEDGE_SMOOTH_HINT_FAST) - glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT_NV, GLITZ_GL_FASTEST); + glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT, GLITZ_GL_FASTEST); else - glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT_NV, GLITZ_GL_NICEST); + glHint (GLITZ_GL_MULTISAMPLE_FILTER_HINT, GLITZ_GL_NICEST); } } else - glDisable (GLITZ_GL_MULTISAMPLE_ARB); + glDisable (GLITZ_GL_MULTISAMPLE); } } diff --git a/src/glitz_glx_extension.c b/src/glitz_glx_extension.c index af5f2df..c7064a9 100644 --- a/src/glitz_glx_extension.c +++ b/src/glitz_glx_extension.c @@ -43,12 +43,16 @@ static glitz_extension_map client_glx_extensions[] = { { "GL_ARB_texture_non_power_of_two", GLITZ_GLX_FEATURE_TEXTURE_NPOT_MASK }, { "GL_ARB_texture_mirrored_repeat", GLITZ_GLX_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK }, + { "GL_ARB_texture_env_combine", + GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK }, + { "GL_ARB_texture_env_dot3", GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK }, { "GL_ARB_multisample", GLITZ_GLX_FEATURE_MULTISAMPLE_MASK }, { "GL_NV_multisample_filter_hint", GLITZ_GLX_FEATURE_MULTISAMPLE_FILTER_MASK }, { "GL_ARB_multitexture", GLITZ_GLX_FEATURE_ARB_MULTITEXTURE_MASK }, { "GL_ARB_vertex_program", GLITZ_GLX_FEATURE_ARB_VERTEX_PROGRAM_MASK }, { "GL_ARB_fragment_program", GLITZ_GLX_FEATURE_ARB_FRAGMENT_PROGRAM_MASK }, + { "GL_EXT_pixel_buffer_object", GLITZ_GLX_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, { NULL, 0 } }; @@ -134,6 +138,25 @@ glitz_glx_query_extensions (glitz_glx_screen_info_t *screen_info) screen_info->feature_mask |= GLITZ_FEATURE_ARB_MULTITEXTURE_MASK; if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK) + screen_info->feature_mask |= GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK; + + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK) + screen_info->feature_mask |= GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK; + + if ((screen_info->feature_mask & + GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK) && + (screen_info->feature_mask & + GLITZ_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK)) { + glitz_gl_int_t max_texture_units; + + glGetIntegerv (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units); + if (max_texture_units >= 3) + screen_info->feature_mask |= GLITZ_FEATURE_COMPONENT_ALPHA_MASK; + } + + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_ARB_VERTEX_PROGRAM_MASK) screen_info->feature_mask |= GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK; @@ -145,4 +168,8 @@ glitz_glx_query_extensions (glitz_glx_screen_info_t *screen_info) (screen_info->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK)) screen_info->feature_mask |= GLITZ_FEATURE_CONVOLUTION_FILTER_MASK; } + + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_PIXEL_BUFFER_OBJECT_MASK) + screen_info->feature_mask |= GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; } diff --git a/src/glitz_glx_info.c b/src/glitz_glx_info.c index 143df1d..23eb5e3 100644 --- a/src/glitz_glx_info.c +++ b/src/glitz_glx_info.c @@ -42,8 +42,10 @@ glitz_gl_proc_address_list_t _glitz_gl_proc_address = { (glitz_gl_vertex_2i_t) glVertex2i, (glitz_gl_vertex_2d_t) glVertex2d, (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, (glitz_gl_tex_coord_2d_t) glTexCoord2d, (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4d_t) glColor4d, (glitz_gl_scissor_t) glScissor, (glitz_gl_blend_func_t) glBlendFunc, (glitz_gl_clear_t) glClear, @@ -92,14 +94,20 @@ glitz_gl_proc_address_list_t _glitz_gl_proc_address = { (glitz_gl_end_list_t) glEndList, (glitz_gl_call_list_t) glCallList, - (glitz_gl_active_texture_arb_t) 0, - (glitz_gl_multi_tex_coord_2d_arb_t) 0, - (glitz_gl_gen_programs_arb_t) 0, - (glitz_gl_delete_programs_arb_t) 0, - (glitz_gl_program_string_arb_t) 0, - (glitz_gl_bind_program_arb_t) 0, - (glitz_gl_program_local_param_4d_arb_t) 0, - (glitz_gl_get_program_iv_arb_t) 0, + (glitz_gl_active_texture_t) 0, + (glitz_gl_multi_tex_coord_2d_t) 0, + (glitz_gl_gen_programs_t) 0, + (glitz_gl_delete_programs_t) 0, + (glitz_gl_program_string_t) 0, + (glitz_gl_bind_program_t) 0, + (glitz_gl_program_local_param_4d_t) 0, + (glitz_gl_get_program_iv_t) 0, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0, 1 }; @@ -108,8 +116,8 @@ glitz_glx_get_proc_address (glitz_glx_thread_info_t *info, const char *name) { glitz_function_pointer_t address = NULL; - if (info->glx.get_proc_address_arb) - address = info->glx.get_proc_address_arb ((glitz_gl_ubyte_t *) name); + if (info->glx.get_proc_address) + address = info->glx.get_proc_address ((glitz_gl_ubyte_t *) name); if (!address) { if (!info->dlhand) @@ -141,7 +149,7 @@ glitz_glx_proc_address_lookup (glitz_glx_thread_info_t *info) glitz_glx_get_proc_address (info, "glXDestroyPbuffer"); info->glx.make_context_current = (glitz_glx_make_context_current_t) glitz_glx_get_proc_address (info, "glXMakeContextCurrent"); - info->glx.get_proc_address_arb = (glitz_glx_get_proc_address_arb_t) + info->glx.get_proc_address = (glitz_glx_get_proc_address_t) glitz_glx_get_proc_address (info, "glXGetProcAddressARB"); info->glx.need_lookup = 0; @@ -211,25 +219,33 @@ static glitz_glx_thread_info_t * glitz_glx_thread_info_get (const char *gl_library) { glitz_glx_thread_info_t *thread_info; + void *p; if (!tsd_initialized) { - thread_info = malloc (sizeof (glitz_glx_thread_info_t)); - glitz_glx_thread_info_init (thread_info); - xthread_key_create (&info_tsd, glitz_glx_thread_info_destroy); - xthread_set_specific (info_tsd, thread_info); - tsd_initialized = 1; - } else { - void *p; + } - xthread_get_specific (info_tsd, &p); + xthread_get_specific (info_tsd, &p); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_glx_thread_info_t)); + glitz_glx_thread_info_init (thread_info); + + xthread_set_specific (info_tsd, thread_info); + } else thread_info = (glitz_glx_thread_info_t *) p; - } if (thread_info->glx.need_lookup) { - if (gl_library) - thread_info->gl_library = strdup (gl_library); + if (gl_library) { + int len = strlen (gl_library); + + thread_info->gl_library = malloc (len + 1); + if (thread_info->gl_library) { + memcpy (thread_info->gl_library, gl_library, len); + thread_info->gl_library[len] = '\0'; + } + } glitz_glx_proc_address_lookup (thread_info); } @@ -300,7 +316,10 @@ glitz_glx_display_destroy (glitz_glx_display_info_t *display_info) for (i = 0; i < display_info->n_screens; i++) glitz_glx_screen_destroy (display_info->screens[i]); - free (display_info->screens); + if (display_info->screens) + free (display_info->screens); + + free (display_info); } static void @@ -402,7 +421,7 @@ glitz_glx_screen_info_get (Display *display, screen_info->contexts = NULL; screen_info->n_contexts = 0; - memset (&screen_info->programs, 0, sizeof (glitz_programs_t)); + glitz_program_map_init (&screen_info->program_map); glitz_glx_create_root_context (screen_info); @@ -439,8 +458,8 @@ glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info) glXMakeCurrent (screen_info->display_info->display, screen_info->root_drawable, screen_info->root_context.context)) { - glitz_programs_fini (&screen_info->root_context.gl, - &screen_info->programs); + glitz_program_map_fini (&screen_info->root_context.gl, + &screen_info->program_map); } glXMakeCurrent (display, None, NULL); diff --git a/src/glitz_glx_surface.c b/src/glitz_glx_surface.c index b2230ab..f603f1c 100644 --- a/src/glitz_glx_surface.c +++ b/src/glitz_glx_surface.c @@ -171,11 +171,11 @@ _glitz_glx_set_features (glitz_glx_surface_t *surface) { surface->base.feature_mask = surface->screen_info->feature_mask; + surface->base.feature_mask &= ~GLITZ_FEATURE_ARB_MULTITEXTURE_MASK; surface->base.feature_mask &= ~GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK; surface->base.feature_mask &= ~GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK; surface->base.feature_mask &= ~GLITZ_FEATURE_CONVOLUTION_FILTER_MASK; - surface->base.feature_mask &= ~GLITZ_FEATURE_MULTISAMPLE_MASK; - surface->base.feature_mask &= ~GLITZ_FEATURE_OFFSCREEN_MULTISAMPLE_MASK; + surface->base.feature_mask &= ~GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; if (surface->context->glx.need_lookup) { glitz_surface_push_current (&surface->base, @@ -185,41 +185,49 @@ _glitz_glx_set_features (glitz_glx_surface_t *surface) if ((surface->screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_ARB_RENDER_TEXTURE_MASK) && - surface->context->glx.bind_tex_image_arb && - surface->context->glx.release_tex_image_arb) + surface->context->glx.bind_tex_image && + surface->context->glx.release_tex_image) surface->render_texture = 1; - if (surface->context->gl.active_texture_arb && - surface->context->gl.multi_tex_coord_2d_arb && - surface->context->gl.gen_programs_arb && - surface->context->gl.delete_programs_arb && - surface->context->gl.program_string_arb && - surface->context->gl.bind_program_arb) { - if (surface->screen_info->feature_mask & - GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) - surface->base.feature_mask |= GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK; - - if (surface->screen_info->feature_mask & - GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK) - surface->base.feature_mask |= GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK; + if (surface->context->gl.active_texture && + surface->context->gl.multi_tex_coord_2d) { + surface->base.feature_mask |= GLITZ_FEATURE_ARB_MULTITEXTURE_MASK; + + if (surface->context->gl.gen_programs && + surface->context->gl.delete_programs && + surface->context->gl.program_string && + surface->context->gl.bind_program && + surface->context->gl.program_local_param_4d) { + + if (surface->screen_info->feature_mask & + GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) + surface->base.feature_mask |= GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK; + + if (surface->screen_info->feature_mask & + GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK) + surface->base.feature_mask |= GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK; - if ((surface->base.feature_mask & GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK) && - (surface->base.feature_mask & - GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) && - surface->context->gl.program_local_param_4d_arb && - surface->context->texture_indirections >= 9) { - /* Convolution filter programs require support for at least nine - texture indirections. */ - surface->base.feature_mask |= GLITZ_FEATURE_CONVOLUTION_FILTER_MASK; + if ((surface->base.feature_mask & + GLITZ_FEATURE_ARB_VERTEX_PROGRAM_MASK) && + (surface->base.feature_mask & + GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) && + surface->context->texture_indirections >= 9) { + /* Convolution filter programs require support for at least nine + texture indirections. */ + surface->base.feature_mask |= GLITZ_FEATURE_CONVOLUTION_FILTER_MASK; + } } } - if (surface->screen_info->feature_mask & GLITZ_FEATURE_MULTISAMPLE_MASK) - surface->base.feature_mask |= GLITZ_FEATURE_MULTISAMPLE_MASK; - - if (surface->screen_info->feature_mask & - GLITZ_FEATURE_OFFSCREEN_MULTISAMPLE_MASK) - surface->base.feature_mask |= GLITZ_FEATURE_OFFSCREEN_MULTISAMPLE_MASK; + if (surface->context->gl.gen_buffers && + surface->context->gl.delete_buffers && + surface->context->gl.bind_buffer && + surface->context->gl.buffer_data && + surface->context->gl.map_buffer && + surface->context->gl.unmap_buffer) + if (surface->screen_info->feature_mask & + GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) + surface->base.feature_mask |= GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; } static glitz_surface_t * @@ -247,7 +255,7 @@ _glitz_glx_surface_create (glitz_glx_screen_info_t *screen_info, screen_info->n_formats, width, height, - &screen_info->programs, + &screen_info->program_map, screen_info->texture_mask); surface->screen_info = screen_info; @@ -318,7 +326,7 @@ glitz_glx_surface_create_for_window (Display *display, screen_info->n_formats, width, height, - &screen_info->programs, + &screen_info->program_map, screen_info->texture_mask); surface->screen_info = screen_info; diff --git a/src/glitz_glxext.h b/src/glitz_glxext.h index 22fbcc1..58266e0 100644 --- a/src/glitz_glxext.h +++ b/src/glitz_glxext.h @@ -94,7 +94,7 @@ typedef XID GLXPbuffer; #endif -typedef glitz_function_pointer_t (* glitz_glx_get_proc_address_arb_t) +typedef glitz_function_pointer_t (* glitz_glx_get_proc_address_t) (const glitz_gl_ubyte_t *); typedef GLXFBConfig *(* glitz_glx_get_fbconfigs_t) (Display *display, int screen, int *n_elements); @@ -114,9 +114,9 @@ typedef Bool (* glitz_glx_make_context_current_t) #define GLX_SAMPLES_ARB 0x186a1 #endif -typedef Bool *(* glitz_glx_bind_tex_image_arb_t) +typedef Bool *(* glitz_glx_bind_tex_image_t) (Display *display, GLXPbuffer pbuffer, int buffer); -typedef Bool (* glitz_glx_release_tex_image_arb_t) +typedef Bool (* glitz_glx_release_tex_image_t) (Display *display, GLXPbuffer pbuffer, int buffer); #endif /* GLITZ_GLXEXT_H_INCLUDED */ diff --git a/src/glitz_glxint.h b/src/glitz_glxint.h index f091eaf..7f2b54e 100644 --- a/src/glitz_glxint.h +++ b/src/glitz_glxint.h @@ -44,17 +44,20 @@ #define GLITZ_GLX_FEATURE_CLIENT_MULTISAMPLE_MASK (1L << 4) #define GLITZ_GLX_FEATURE_MULTISAMPLE_FILTER_MASK (1L << 5) #define GLITZ_GLX_FEATURE_ARB_MULTITEXTURE_MASK (1L << 6) -#define GLITZ_GLX_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 7) -#define GLITZ_GLX_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 8) -#define GLITZ_GLX_FEATURE_GLX13_MASK (1L << 9) -#define GLITZ_GLX_FEATURE_ARB_RENDER_TEXTURE_MASK (1L << 10) +#define GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK (1L << 7) +#define GLITZ_GLX_FEATURE_ARB_TEXTURE_ENV_DOT3_MASK (1L << 8) +#define GLITZ_GLX_FEATURE_ARB_VERTEX_PROGRAM_MASK (1L << 9) +#define GLITZ_GLX_FEATURE_ARB_FRAGMENT_PROGRAM_MASK (1L << 10) +#define GLITZ_GLX_FEATURE_GLX13_MASK (1L << 11) +#define GLITZ_GLX_FEATURE_ARB_RENDER_TEXTURE_MASK (1L << 12) +#define GLITZ_GLX_FEATURE_PIXEL_BUFFER_OBJECT_MASK (1L << 13) typedef struct _glitz_glx_surface glitz_glx_surface_t; typedef struct _glitz_glx_screen_info_t glitz_glx_screen_info_t; typedef struct _glitz_glx_display_info_t glitz_glx_display_info_t; typedef struct _glitz_glx_static_proc_address_list_t { - glitz_glx_get_proc_address_arb_t get_proc_address_arb; + glitz_glx_get_proc_address_t get_proc_address; glitz_glx_get_fbconfigs_t get_fbconfigs; glitz_glx_get_fbconfig_attrib_t get_fbconfig_attrib; glitz_glx_get_visual_from_fbconfig_t get_visual_from_fbconfig; @@ -65,8 +68,8 @@ typedef struct _glitz_glx_static_proc_address_list_t { } glitz_glx_static_proc_address_list_t; typedef struct _glitz_glx_proc_address_list_t { - glitz_glx_bind_tex_image_arb_t bind_tex_image_arb; - glitz_glx_release_tex_image_arb_t release_tex_image_arb; + glitz_glx_bind_tex_image_t bind_tex_image; + glitz_glx_release_tex_image_t release_tex_image; glitz_bool_t need_lookup; } glitz_glx_proc_address_list_t; @@ -120,7 +123,7 @@ struct _glitz_glx_screen_info_t { long int glx_feature_mask; long int texture_mask; - glitz_programs_t programs; + glitz_program_map_t program_map; }; struct _glitz_glx_surface { diff --git a/src/glitz_pixel.c b/src/glitz_pixel.c index 419c99d..77fe0a6 100644 --- a/src/glitz_pixel.c +++ b/src/glitz_pixel.c @@ -1,25 +1,24 @@ /* - * Copyright © 2004 David Reveman, Peter Nilsson - * + * Copyright © 2004 David Reveman + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the names of - * David Reveman and Peter Nilsson not be used in advertising or - * publicity pertaining to distribution of the software without - * specific, written prior permission. David Reveman and Peter Nilsson - * makes no representations about the suitability of this software for - * any purpose. It is provided "as is" without express or implied warranty. + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. * - * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND - * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <c99drn@cs.umu.se> */ @@ -48,7 +47,7 @@ static struct _glitz_gl_pixel_format { 0x00000000, 0x00000000 }, - 0, 0, + 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }, GLITZ_GL_ALPHA, @@ -62,7 +61,7 @@ static struct _glitz_gl_pixel_format { 0x0000ff00, 0x000000ff }, - 0, 0, + 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }, @@ -73,7 +72,6 @@ static struct _glitz_gl_pixel_format { #endif GLITZ_GL_UNSIGNED_BYTE - }, { { { @@ -83,7 +81,7 @@ static struct _glitz_gl_pixel_format { 0x0000ff00, 0x000000ff }, - 0, 0, + 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }, GLITZ_GL_BGRA, @@ -289,9 +287,7 @@ _glitz_pixel_transform (unsigned long transform, glitz_image_t *src, glitz_image_t *dst, int x_src, - int y_src, int x_dst, - int y_dst, int width, int height) { @@ -356,11 +352,11 @@ _glitz_pixel_transform (unsigned long transform, for (y = 0; y < height; y++) { if (src->format->scanline_order != dst->format->scanline_order) - src_op.line = &src->data[(src->height - (y + y_src) - 1) * src_stride]; + src_op.line = &src->data[(src->height - y - 1) * src_stride]; else - src_op.line = &src->data[(y + y_src) * src_stride]; + src_op.line = &src->data[y * src_stride]; - dst_op.line = &dst->data[(y + y_dst) * dst_stride]; + dst_op.line = &dst->data[y * dst_stride]; if (transform & GLITZ_TRANSFORM_PIXELS_MASK) { for (x = 0; x < width; x++) { @@ -410,21 +406,257 @@ _glitz_best_gl_pixel_format (glitz_format_t *format) return &_gl_format_map[GLITZ_GL_FORMAT_A]; } +struct _glitz_pixel_buffer { + glitz_gl_sizei_t size; + glitz_gl_uint_t name; + glitz_gl_enum_t target; + char *data; + int owns_data; + glitz_surface_t *surface; + glitz_pixel_format_t format; +}; + +glitz_pixel_buffer_t * +glitz_pixel_buffer_create (glitz_surface_t *surface, + char *data, + unsigned int size, + glitz_buffer_hint_t hint) +{ + glitz_pixel_buffer_t *buffer; + glitz_gl_enum_t usage; + + buffer = malloc (sizeof (glitz_pixel_buffer_t)); + if (buffer == NULL) + return NULL; + + buffer->size = size; + buffer->name = 0; + + switch (hint) { + case GLITZ_PIXEL_BUFFER_HINT_STREAM_DRAW: + usage = GLITZ_GL_STREAM_DRAW; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_STREAM_READ: + usage = GLITZ_GL_STREAM_READ; + buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_STREAM_COPY: + usage = GLITZ_GL_STREAM_COPY; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_STATIC_DRAW: + usage = GLITZ_GL_STATIC_DRAW; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_STATIC_READ: + usage = GLITZ_GL_STATIC_READ; + buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_STATIC_COPY: + usage = GLITZ_GL_STATIC_COPY; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_DYNAMIC_DRAW: + usage = GLITZ_GL_DYNAMIC_DRAW; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + case GLITZ_PIXEL_BUFFER_HINT_DYNAMIC_READ: + usage = GLITZ_GL_DYNAMIC_READ; + buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER; + break; + default: + usage = GLITZ_GL_DYNAMIC_COPY; + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + } + + if (surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) { + buffer->surface = surface; + glitz_surface_reference (surface); + + glitz_surface_push_current (surface, GLITZ_CN_ANY_CONTEXT_CURRENT); + + surface->gl->gen_buffers (1, &buffer->name); + if (buffer->name) { + surface->gl->bind_buffer (buffer->target, buffer->name); + surface->gl->buffer_data (buffer->target, size, data, usage); + } + + glitz_surface_pop_current (surface); + } else + buffer->surface = NULL; + + if (buffer->name == 0) { + buffer->data = malloc (size); + if (buffer->data == NULL) { + free (buffer); + return NULL; + } + + if (data) + memcpy (buffer->data, data, size); + + buffer->owns_data = 1; + } + + buffer->format = _glitz_best_gl_pixel_format (surface->format)->pixel; + + return buffer; +} + +glitz_pixel_buffer_t * +glitz_pixel_buffer_create_for_data (char *data, + glitz_pixel_format_t *format) +{ + glitz_pixel_buffer_t *buffer; + + buffer = malloc (sizeof (glitz_pixel_buffer_t)); + if (buffer == NULL) + return NULL; + + buffer->name = 0; + buffer->size = 0; + buffer->data = data; + buffer->owns_data = 0; + buffer->surface = NULL; + buffer->target = 0; + buffer->format = *format; + + return buffer; +} + +void +glitz_pixel_buffer_destroy (glitz_pixel_buffer_t *buffer) +{ + glitz_surface_t *surface = buffer->surface; + + if (surface && + surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) { + glitz_surface_push_current (surface, GLITZ_CN_ANY_CONTEXT_CURRENT); + + surface->gl->delete_buffers (1, &buffer->name); + + glitz_surface_pop_current (surface); + + glitz_surface_destroy (surface); + } else if (buffer->owns_data) + free (buffer->data); + + free (buffer); +} + +void +glitz_pixel_buffer_set_format (glitz_pixel_buffer_t *buffer, + glitz_pixel_format_t *format) +{ + buffer->format = *format; +} + +void +glitz_pixel_buffer_get_format (glitz_pixel_buffer_t *buffer, + glitz_pixel_format_t *format) +{ + *format = buffer->format; +} + +char * +glitz_pixel_buffer_get_data (glitz_pixel_buffer_t *buffer, + glitz_pixel_buffer_access_t access) +{ + char *pointer = NULL; + glitz_surface_t *surface = buffer->surface; + + if (surface && + surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) { + glitz_gl_enum_t buffer_access; + + glitz_surface_push_current (surface, GLITZ_CN_ANY_CONTEXT_CURRENT); + + switch (access) { + case GLITZ_PIXEL_BUFFER_ACCESS_READ_ONLY: + buffer_access = GLITZ_GL_READ_ONLY; + break; + case GLITZ_PIXEL_BUFFER_ACCESS_WRITE_ONLY: + buffer_access = GLITZ_GL_WRITE_ONLY; + break; + default: + buffer_access = GLITZ_GL_READ_WRITE; + break; + } + + surface->gl->bind_buffer (buffer->target, buffer->name); + pointer = (char *) surface->gl->map_buffer (buffer->target, + buffer_access); + + glitz_surface_pop_current (surface); + } + + if (pointer == NULL) + pointer = buffer->data; + + return pointer; +} + +void +glitz_pixel_buffer_put_back_data (glitz_pixel_buffer_t *buffer) +{ + glitz_surface_t *surface = buffer->surface; + + if (surface && + surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) { + glitz_surface_push_current (surface, GLITZ_CN_ANY_CONTEXT_CURRENT); + + if (surface->gl->unmap_buffer (buffer->target)) { + /* don't know what to do here, maybe glitz_pixel_buffer_put_back_data + should return a status value */ + } + surface->gl->bind_buffer (buffer->target, 0); + + glitz_surface_pop_current (surface); + } +} + +char * +glitz_pixel_buffer_bind (glitz_pixel_buffer_t *buffer, + glitz_gl_enum_t target) +{ + glitz_surface_t *surface = buffer->surface; + + if (surface && + surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) { + surface->gl->bind_buffer (target, buffer->name); + buffer->target = target; + + return NULL; + } + + return buffer->data; +} + +void +glitz_pixel_buffer_unbind (glitz_pixel_buffer_t *buffer) +{ + glitz_surface_t *surface = buffer->surface; + + if (surface && + surface->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) + surface->gl->bind_buffer (buffer->target, 0); +} + void glitz_put_pixels (glitz_surface_t *dst, int x_dst, int y_dst, int width, int height, - glitz_pixel_format_t *format, - char *pixels) + glitz_pixel_buffer_t *buffer) { glitz_gl_proc_address_list_t *gl; glitz_bool_t drawable; - char *data = NULL; - glitz_gl_pixel_format_t *gl_format = NULL; + char *pixels, *data = NULL; + glitz_gl_pixel_format_t *format = NULL; unsigned long transform = 0; - glitz_gl_enum_t image_format; int xoffset, bytes_per_line; if (SURFACE_PROGRAMMATIC (dst)) @@ -438,21 +670,26 @@ glitz_put_pixels (glitz_surface_t *dst, gl = dst->gl; - if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) + if (buffer->format.scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; /* find direct format */ - gl_format = _glitz_find_gl_pixel_format (format); - if (gl_format == NULL) { + format = _glitz_find_gl_pixel_format (&buffer->format); + if (format == NULL) { transform |= GLITZ_TRANSFORM_PIXELS_MASK; - gl_format = _glitz_best_gl_pixel_format (dst->format); + format = _glitz_best_gl_pixel_format (dst->format); } + + if (glitz_surface_try_push_current (dst, GLITZ_CN_SURFACE_DRAWABLE_CURRENT)) + drawable = 1; + else + drawable = 0; if (transform) { glitz_image_t src_image, dst_image; int stride; - stride = (((width * gl_format->pixel.masks.bpp) / 8) + 3) & -4; + stride = (((width * format->pixel.masks.bpp) / 8) + 3) & -4; data = malloc (stride * height); if (!data) { @@ -461,34 +698,38 @@ glitz_put_pixels (glitz_surface_t *dst, } dst_image.data = data; - dst_image.format = &gl_format->pixel; + dst_image.format = &format->pixel; dst_image.width = width; dst_image.height = height; - src_image.data = pixels; - src_image.format = format; + src_image.data = + glitz_pixel_buffer_get_data (buffer, + GLITZ_PIXEL_BUFFER_ACCESS_READ_ONLY); + src_image.data += buffer->format.skip_lines * + buffer->format.bytes_per_line; + src_image.format = &buffer->format; src_image.width = width; src_image.height = height; _glitz_pixel_transform (transform, &src_image, &dst_image, - format->xoffset, 0, - 0, 0, + buffer->format.xoffset, + 0, width, height); + + glitz_pixel_buffer_put_back_data (buffer); + pixels = data; xoffset = 0; bytes_per_line = stride; } else { - xoffset = format->xoffset; - bytes_per_line = format->bytes_per_line; + xoffset = buffer->format.xoffset; + bytes_per_line = buffer->format.bytes_per_line; + pixels = glitz_pixel_buffer_bind (buffer, GLITZ_GL_PIXEL_UNPACK_BUFFER); + pixels += buffer->format.skip_lines * bytes_per_line; } - - if (glitz_surface_try_push_current (dst, GLITZ_CN_SURFACE_DRAWABLE_CURRENT)) - drawable = 1; - else - drawable = 0; - + glitz_texture_bind (gl, &dst->texture); gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); @@ -505,24 +746,18 @@ glitz_put_pixels (glitz_surface_t *dst, else gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2); } else - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); - - if (gl_format->format == GLITZ_GL_ALPHA) - image_format = GLITZ_GL_LUMINANCE; - else - image_format = gl_format->format; + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); gl->tex_sub_image_2d (dst->texture.target, 0, x_dst, dst->height - y_dst - height, width, height, - image_format, gl_format->type, + format->format, format->type, pixels); - + if (drawable) { glitz_point_t tl, br; - gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, - GLITZ_GL_TEXTURE_ENV_MODE, + gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, GLITZ_GL_REPLACE); dst->gl->color_4us (0x0, 0x0, 0x0, 0xffff); @@ -559,6 +794,9 @@ glitz_put_pixels (glitz_surface_t *dst, } glitz_texture_unbind (dst->gl, &dst->texture); + + if (transform == 0) + glitz_pixel_buffer_unbind (buffer); glitz_surface_pop_current (dst); @@ -572,14 +810,13 @@ glitz_get_pixels (glitz_surface_t *src, int y_src, int width, int height, - glitz_pixel_format_t *format, - char *pixels) + glitz_pixel_buffer_t *buffer) { glitz_gl_proc_address_list_t *gl; glitz_bool_t drawable; glitz_texture_t *texture = NULL; - char *p, *data = NULL; - glitz_gl_pixel_format_t *gl_format = NULL; + char *pixels, *data = NULL; + glitz_gl_pixel_format_t *format = NULL; unsigned long transform = 0; int src_x = 0, src_y = 0, src_w = width, src_h = height; int xoffset, bytes_per_line; @@ -609,14 +846,14 @@ glitz_get_pixels (glitz_surface_t *src, transform |= GLITZ_TRANSFORM_COPY_REGION_MASK; } - if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) + if (buffer->format.scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; /* find direct format */ - gl_format = _glitz_find_gl_pixel_format (format); - if (gl_format == NULL) { + format = _glitz_find_gl_pixel_format (&buffer->format); + if (format == NULL) { transform |= GLITZ_TRANSFORM_PIXELS_MASK; - gl_format = _glitz_best_gl_pixel_format (src->format); + format = _glitz_best_gl_pixel_format (src->format); } if (transform) { @@ -629,20 +866,21 @@ glitz_get_pixels (glitz_surface_t *src, src_y = y_src; } - stride = (((src_w * gl_format->pixel.masks.bpp) / 8) + 3) & -4; + stride = (((src_w * format->pixel.masks.bpp) / 8) + 3) & -4; data = malloc (stride * src_h); if (!data) { glitz_surface_status_add (src, GLITZ_STATUS_NO_MEMORY_MASK); return; } - p = data; + pixels = data; xoffset = 0; bytes_per_line = stride; } else { - xoffset = format->xoffset; - bytes_per_line = format->bytes_per_line; - p = pixels; + xoffset = buffer->format.xoffset; + bytes_per_line = buffer->format.bytes_per_line; + pixels = glitz_pixel_buffer_bind (buffer, GLITZ_GL_PIXEL_PACK_BUFFER); + pixels += buffer->format.skip_lines * bytes_per_line; } gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, 0); @@ -664,38 +902,45 @@ glitz_get_pixels (glitz_surface_t *src, if (drawable) { gl->read_pixels (x_src, src->height - y_src - height, width, height, - gl_format->format, gl_format->type, - p); + format->format, format->type, + pixels); } else { glitz_texture_bind (gl, texture); gl->get_tex_image (texture->target, 0, - gl_format->format, gl_format->type, - p); + format->format, format->type, + pixels); glitz_texture_unbind (gl, texture); } - glitz_surface_pop_current (src); - if (transform) { glitz_image_t src_image, dst_image; - src_image.data = data; - src_image.format = &gl_format->pixel; + src_image.data = data + src_y * format->pixel.bytes_per_line; + src_image.format = &format->pixel; src_image.width = src_w; src_image.height = src_h; - dst_image.data = pixels; - dst_image.format = format; + dst_image.data = + glitz_pixel_buffer_get_data (buffer, + GLITZ_PIXEL_BUFFER_ACCESS_WRITE_ONLY); + dst_image.data += buffer->format.skip_lines * + buffer->format.bytes_per_line; + dst_image.format = &buffer->format; dst_image.width = width; dst_image.height = height; _glitz_pixel_transform (transform, &src_image, &dst_image, - src_x, src_y, - format->xoffset, 0, + src_x, + buffer->format.xoffset, width, height); - } + + glitz_pixel_buffer_put_back_data (buffer); + } else + glitz_pixel_buffer_unbind (buffer); + + glitz_surface_pop_current (src); if (data) free (data); diff --git a/src/glitz_program.c b/src/glitz_program.c index 3c0fd16..ef64c8a 100644 --- a/src/glitz_program.c +++ b/src/glitz_program.c @@ -1,28 +1,26 @@ /* - * Copyright © 2004 David Reveman, Peter Nilsson - * + * Copyright © 2004 David Reveman + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the names of - * David Reveman and Peter Nilsson not be used in advertising or - * publicity pertaining to distribution of the software without - * specific, written prior permission. David Reveman and Peter Nilsson - * makes no representations about the suitability of this software for - * any purpose. It is provided "as is" without express or implied warranty. + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. * - * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND - * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Authors: David Reveman <c99drn@cs.umu.se> - * Peter Nilsson <c99pnn@cs.umu.se> + * Author: David Reveman <c99drn@cs.umu.se> */ #ifdef HAVE_CONFIG_H @@ -34,94 +32,69 @@ #include <stdio.h> #define EXPAND_NONE "" -#define EXPAND_2D_TEX "2D" -#define EXPAND_RECT_TEX "RECT" -#define EXPAND_NO_PD_OP \ - "MOV result.color, color;\n" - -#define EXPAND_SRC_TEMP "TEMP src;\n" -#define EXPAND_SRC_2D_PD_OP \ - "TEX src, fragment.texcoord[0], texture[0], 2D;\n" \ - "MUL result.color, src, color.a;\n" -#define EXPAND_SRC_RECT_PD_OP \ - "TEX src, fragment.texcoord[0], texture[0], RECT;\n" \ - "MUL result.color, src, color.a;\n" - -#define EXPAND_MASK_TEMP "TEMP mask;\n" -#define EXPAND_MASK_2D_PD_OP \ - "TEX mask, fragment.texcoord[1], texture[1], 2D;\n" \ - "MUL result.color, color, mask.a;\n" -#define EXPAND_MASK_RECT_PD_OP \ - "TEX mask, fragment.texcoord[1], texture[1], RECT;\n" \ - "MUL result.color, color, mask.a;\n" +#define EXPAND_2D "2D" +#define EXPAND_RECT "RECT" + +#define EXPAND_NO_IN_OP \ + "MUL result.color, color, fragment.color.a;" + +#define EXPAND_SRC_TEMP "TEMP src;" +#define EXPAND_SRC_2D_IN_OP \ + "TEX src, fragment.texcoord[1], texture[1], 2D;" \ + "DP4 color.a, color, fragment.color;" \ + "MUL result.color, src, color.a;" +#define EXPAND_SRC_RECT_IN_OP \ + "TEX src, fragment.texcoord[1], texture[1], RECT;" \ + "DP4 color.a, color, fragment.color;" \ + "MUL result.color, src, color.a;" + +#define EXPAND_MASK_TEMP "TEMP mask;" +#define EXPAND_MASK_2D_IN_OP \ + "TEX 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 \ + "TEX mask, fragment.texcoord[0], texture[0], RECT;" \ + "DP4 mask.a, mask, fragment.color;" \ + "MUL result.color, color, mask.a;" typedef struct _glitz_program_expand_t glitz_program_expand_t; static const struct _glitz_program_expand_t { - int index; - char *tex; - char *temporary; - char *operation; -} _program_expand_map[] = { - - /* src is operation surface */ - - /* GLITZ_PROGRAM_2DSRC_2DMASK_OFFSET */ - { 0, EXPAND_2D_TEX, EXPAND_MASK_TEMP, EXPAND_MASK_2D_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_2DMASK_OFFSET */ - { 0, EXPAND_RECT_TEX, EXPAND_MASK_TEMP, EXPAND_MASK_2D_PD_OP }, - - /* GLITZ_PROGRAM_2DSRC_RECTMASK_OFFSET */ - { 0, EXPAND_2D_TEX, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_RECTMASK_OFFSET */ - { 0, EXPAND_RECT_TEX, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_2DMASK_OFFSET */ - { 0, EXPAND_NONE, EXPAND_MASK_TEMP, EXPAND_MASK_2D_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_RECTMASK_OFFSET */ - { 0, EXPAND_NONE, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_PD_OP }, - - /* GLITZ_PROGRAM_2DSRC_NOMASK_OFFSET */ - { 0, EXPAND_2D_TEX, EXPAND_NONE, EXPAND_NO_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_NOMASK_OFFSET */ - { 0, EXPAND_RECT_TEX, EXPAND_NONE, EXPAND_NO_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_NOMASK_OFFSET */ - { 0, EXPAND_NONE, EXPAND_NONE, EXPAND_NO_PD_OP }, - - - /* mask is operation surface */ - - /* GLITZ_PROGRAM_2DSRC_2DMASK_OFFSET */ - { 1, EXPAND_2D_TEX, EXPAND_SRC_TEMP, EXPAND_SRC_2D_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_2DMASK_OFFSET */ - { 1, EXPAND_2D_TEX, EXPAND_SRC_TEMP, EXPAND_SRC_RECT_PD_OP }, - - /* GLITZ_PROGRAM_2DSRC_RECTMASK_OFFSET */ - { 1, EXPAND_RECT_TEX, EXPAND_SRC_TEMP, EXPAND_SRC_2D_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_RECTMASK_OFFSET */ - { 1, EXPAND_RECT_TEX, EXPAND_SRC_TEMP, EXPAND_SRC_RECT_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_2DMASK_OFFSET */ - { 1, EXPAND_2D_TEX, EXPAND_NONE, EXPAND_NO_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_RECTMASK_OFFSET */ - { 1, EXPAND_RECT_TEX, EXPAND_NONE, EXPAND_NO_PD_OP }, - - /* GLITZ_PROGRAM_2DSRC_NOMASK_OFFSET */ - { 1, EXPAND_NONE, EXPAND_SRC_TEMP, EXPAND_SRC_2D_PD_OP }, - - /* GLITZ_PROGRAM_RECTSRC_NOMASK_OFFSET */ - { 1, EXPAND_NONE, EXPAND_SRC_TEMP, EXPAND_SRC_RECT_PD_OP }, - - /* GLITZ_PROGRAM_NOSRC_NOMASK_OFFSET */ - { 1, EXPAND_NONE, EXPAND_NONE, EXPAND_NO_PD_OP } + char *texture; + char *declarations; + char *in; +} _program_expand_map[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST] = { + { + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_NONE] */ + { EXPAND_NONE, EXPAND_NONE, EXPAND_NO_IN_OP }, + + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_2D] */ + { EXPAND_NONE, EXPAND_MASK_TEMP, EXPAND_MASK_2D_IN_OP }, + + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_RECT] */ + { EXPAND_NONE, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_IN_OP } + }, { + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_NONE] */ + { EXPAND_2D, EXPAND_NONE, EXPAND_NO_IN_OP }, + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_2D] */ + { EXPAND_2D, EXPAND_MASK_TEMP, EXPAND_MASK_2D_IN_OP }, + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_RECT] */ + { EXPAND_2D, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_IN_OP } + }, { + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_NONE] */ + { EXPAND_RECT, EXPAND_NONE, EXPAND_NO_IN_OP }, + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_2D] */ + { EXPAND_RECT, EXPAND_MASK_TEMP, EXPAND_MASK_2D_IN_OP }, + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_RECT] */ + { EXPAND_RECT, EXPAND_MASK_TEMP, EXPAND_MASK_RECT_IN_OP } + } }; /* @@ -133,46 +106,20 @@ static const struct _glitz_program_expand_t { * * Author: David Reveman <c99drn@cs.umu.se> */ -static char *_glitz_vertex_program_convolution = -"!!ARBvp1.0\n" -"OPTION ARB_position_invariant;\n" -"ATTRIB coord = vertex.texcoord[%d];\n" -"PARAM vertical_offset = program.local[0];\n" -"PARAM horizontal_offset = program.local[1];\n" -"MOV result.texcoord[%d], coord;\n" -"ADD result.texcoord[2], coord, vertical_offset;\n" -"SUB result.texcoord[3], coord, vertical_offset;\n" -"ADD result.texcoord[4], coord, horizontal_offset;\n" -"SUB result.texcoord[5], coord, horizontal_offset;\n" -"MOV result.texcoord[%d], vertex.texcoord[%d];\n" -"END"; - -/* - * Porter-Duff compositing (SRC in MASK). - * Texture unit 0 is SRC. - * Texture unit 1 is MASK. - * - * Author: David Reveman <c99drn@cs.umu.se> - */ -static char *_glitz_fragment_program_simple = -"!!ARBfp1.0\n" -"TEMP color;\n" - -/* temporary */ -"%s" - -/* src texture */ -"TEX color, fragment.texcoord[0], texture[0], %s;\n" - -/* pd operation */ -"%s" - -"END"; - -typedef enum { - GLITZ_CONVOLUTION_3X3_GENERAL = 1, - GLITZ_CONVOLUTION_3X3_SIMPLE = 2 -} glitz_convolution_type_t; +static const char *_glitz_vertex_program_convolution[] = { + "!!ARBvp1.0", + "OPTION ARB_position_invariant;", + "ATTRIB coord = vertex.texcoord[%s];", + "PARAM vertical_offset = program.local[0];", + "PARAM horizontal_offset = program.local[1];", + "MOV result.texcoord[%s], coord;", + "ADD result.texcoord[2], coord, vertical_offset;", + "SUB result.texcoord[3], coord, vertical_offset;", + "ADD result.texcoord[4], coord, horizontal_offset;", + "SUB result.texcoord[5], coord, horizontal_offset;", + "MOV result.texcoord[%s], vertex.texcoord[%s];", + "END", NULL +}; /* * General 3x3 convolution filter. @@ -184,286 +131,216 @@ typedef enum { * * Author: David Reveman <c99drn@cs.umu.se> */ -static char *_glitz_fragment_program_convolution = -"!!ARBfp1.0\n" -"ATTRIB east = fragment.texcoord[2];\n" -"ATTRIB west = fragment.texcoord[3];\n" -"ATTRIB south = fragment.texcoord[4];\n" -"ATTRIB north = fragment.texcoord[5];\n" -"PARAM k0 = program.local[0];\n" -"PARAM k1 = program.local[1];\n" -"PARAM k2 = program.local[2];\n" -"TEMP color, in, coord;\n" - -/* temporary */ -"%s" - -/* center */ -"TEX in, fragment.texcoord[%d], texture[%d], %s;\n" -"MUL color, in, k1.y;\n" - -/* north west */ -"MOV coord.x, west.x;\n" -"MOV coord.y, north.y;\n" -"TEX in, coord, texture[%d], %s;\n" -"MAD color, in, k0.x, color;\n" - -/* north */ -"TEX in, north, texture[%d], %s;\n" -"MAD color, in, k0.y, color;\n" - -/* north east */ -"MOV coord.x, east.x;\n" -"TEX in, coord, texture[%d], %s;\n" -"MAD color, in, k0.z, color;\n" - -/* east */ -"TEX in, east, texture[%d], %s;\n" -"MAD color, in, k1.x, color;\n" - -/* south east */ -"MOV coord.y, south.y;\n" -"TEX in, coord, texture[%d], %s;\n" -"MAD color, in, k2.z, color;\n" - -/* south */ -"TEX in, south, texture[%d], %s;\n" -"MAD color, in, k2.y, color;\n" - -/* south west */ -"MOV coord.x, west.x;\n" -"TEX in, coord, texture[%d], %s;\n" -"MAD color, in, k2.x, color;\n" - -/* west */ -"TEX in, west, texture[%d], %s;\n" -"MAD color, in, k1.x, color;\n" - -/* pd operation */ -"%s" - -"END"; +static const char *_glitz_fragment_program_convolution[] = { + "!!ARBfp1.0", + "ATTRIB east = fragment.texcoord[2];", + "ATTRIB west = fragment.texcoord[3];", + "ATTRIB south = fragment.texcoord[4];", + "ATTRIB north = fragment.texcoord[5];", + "PARAM k0 = program.local[0];", + "PARAM k1 = program.local[1];", + "PARAM k2 = program.local[2];", + "TEMP color, in, coord;", + + /* extra declerations */ + "%s", + + /* center */ + "TEX in, fragment.texcoord[%s], texture[%s], %s;", + "MUL color, in, k1.y;", + + /* north west */ + "MOV coord.x, west.x;", + "MOV coord.y, north.y;", + "TEX in, coord, texture[%s], %s;", + "MAD color, in, k0.x, color;", + + /* north */ + "TEX in, north, texture[%s], %s;", + "MAD color, in, k0.y, color;", + + /* north east */ + "MOV coord.x, east.x;", + "TEX in, coord, texture[%s], %s;", + "MAD color, in, k0.z, color;", + + /* east */ + "TEX in, east, texture[%s], %s;", + "MAD color, in, k1.x, color;", + + /* south east */ + "MOV coord.y, south.y;", + "TEX in, coord, texture[%s], %s;", + "MAD color, in, k2.z, color;", + + /* south */ + "TEX in, south, texture[%s], %s;", + "MAD color, in, k2.y, color;", + + /* south west */ + "MOV coord.x, west.x;", + "TEX in, coord, texture[%s], %s;", + "MAD color, in, k2.x, color;", + + /* west */ + "TEX in, west, texture[%s], %s;", + "MAD color, in, k1.x, color;", + + /* IN operation */ + "%s", + + "END", NULL +}; /* - * Simple 3x3 convolution filter (corners are zero). - * Convolution kernel must be normalized. + * Linear gradient using 1D texture as color range. + * Color range in texture unit 2. * - * program.local[0]: Top convolution kernel row - * program.local[1]: Middle convolution kernel row - * program.local[2]: Bottom convolution kernel row + * program.local[0].x = start offset + * program.local[0].y = 1 / length + * program.local[0].z = sin (angle) + * program.local[0].w = cos (angle) + * + * transform: + * [ a | c | tx ] + * [ b | d | ty ] + * [ 0 | 0 | 1 ] + * + * program.local[1].x = a + * program.local[1].y = b + * program.local[1].z = c + * program.local[1].w = d + * program.local[2].x = tx + * program.local[2].y = ty + * program.local[2].z = height * * Author: David Reveman <c99drn@cs.umu.se> */ -static char *_glitz_fragment_program_convolution_simple = -"!!ARBfp1.0\n" -"ATTRIB east = fragment.texcoord[2];\n" -"ATTRIB west = fragment.texcoord[3];\n" -"ATTRIB south = fragment.texcoord[4];\n" -"ATTRIB north = fragment.texcoord[5];\n" -"PARAM k0 = program.local[0];\n" -"PARAM k1 = program.local[1];\n" -"PARAM k2 = program.local[2];\n" -"TEMP color, in, coord;\n" - -/* temporary */ -"%s" - -/* center */ -"TEX in, fragment.texcoord[%d], texture[%d], %s;\n" -"MUL color, in, k1.y;\n" - -/* north */ -"TEX in, north, texture[%d], %s;\n" -"MAD color, in, k0.y, color;\n" - -/* east */ -"TEX in, east, texture[%d], %s;\n" -"MAD color, in, k1.x, color;\n" - -/* south */ -"TEX in, south, texture[%d], %s;\n" -"MAD color, in, k2.y, color;\n" - -/* west */ -"TEX in, west, texture[%d], %s;\n" -"MAD color, in, k1.x, color;\n" - -/* pd operation */ -"%s" - -"END"; - -char *_glitz_fragment_program_programmatic[] = { - /* - * Solid. - * - * fragment.color: color - * - * Author: David Reveman <c99drn@cs.umu.se> - */ - "!!ARBfp1.0\n" - "ATTRIB color = fragment.color;\n" - - /* temporary */ - "%s" - - /* pd operation */ - "%s" - - "END", - - /* - * Linear gradient using 1D texture as color range. - * Color range in texture unit 2. - * - * program.local[0].x = start offset - * program.local[0].y = 1 / length - * program.local[0].z = sin (angle) - * program.local[0].w = cos (angle) - * - * transform: - * [ a | c | tx ] - * [ b | d | ty ] - * [ 0 | 0 | 1 ] - * - * program.local[1].x = a - * program.local[1].y = b - * program.local[1].z = c - * program.local[1].w = d - * program.local[2].x = tx - * program.local[2].y = ty - * program.local[2].z = height - * - * Author: David Reveman <c99drn@cs.umu.se> - */ - - "!!ARBfp1.0\n" - "PARAM gradient = program.local[0];\n" - "PARAM transform = program.local[1];\n" - "PARAM translate = program.local[2];\n" - "ATTRIB pos = fragment.texcoord[%d];\n" - "TEMP color, distance, position;\n" - - /* temporary */ - "%s" - - /* flip Y position */ - "SUB position.y, translate.z, pos.y;\n" +static const char *_glitz_fragment_program_linear[] = { + "!!ARBfp1.0", + "PARAM gradient = program.local[0];", + "PARAM transform = program.local[1];", + "PARAM translate = program.local[2];", + "ATTRIB pos = fragment.texcoord[%s];", + "TEMP color, distance, position;", + + /* extra declerations */ + "%s", + + /* flip Y position (this should be done in advance) */ + "SUB position.y, translate.z, pos.y;", /* transform X position */ - "MUL position.x, transform.x, pos.x;\n" - "MAD position.x, transform.z, position.y, position.x;\n" - "ADD position.x, position.x, translate.x;\n" + "MUL position.x, transform.x, pos.x;", + "MAD position.x, transform.z, position.y, position.x;", + "ADD position.x, position.x, translate.x;", /* transform Y position */ - "MUL position.y, transform.w, position.y;\n" - "MAD position.y, transform.y, pos.x, position.y;\n" - "ADD position.y, position.y, translate.y;\n" + "MUL position.y, transform.w, position.y;", + "MAD position.y, transform.y, pos.x, position.y;", + "ADD position.y, position.y, translate.y;", /* calculate gradient offset */ - "MUL position.x, gradient.z, position.x;\n" - "MAD position.x, gradient.w, position.y, position.x;\n" + "MUL position.x, gradient.z, position.x;", + "MAD position.x, gradient.w, position.y, position.x;", - "SUB distance.x, position.x, gradient.x;\n" - "MUL distance.x, distance.x, gradient.y;\n" + "SUB distance.x, position.x, gradient.x;", + "MUL distance.x, distance.x, gradient.y;", - "TEX color, distance, texture[2], 1D;\n" - - "MUL color, color, fragment.color.a;\n" + "TEX color, distance, texture[2], 1D;", - /* pd operation */ - "%s" + /* IN operation */ + "%s", - "END", - - /* - * Radial gradient using 1D texture as color range. - * Color range in texture unit 2. - * - * param.local[0].x = center point X coordinate - * param.local[0].y = center point Y coordinate - * param.local[0].z = 1 / (radius1 - radius0) - * param.local[0].w = radius0 - * - * transform: - * [ a | c | tx ] - * [ b | d | ty ] - * [ 0 | 0 | 1 ] - * - * program.local[1].x = a - * program.local[1].y = b - * program.local[1].z = c - * program.local[1].w = d - * program.local[2].x = tx - * program.local[2].y = ty - * program.local[2].z = height - * - * Author: David Reveman <c99drn@cs.umu.se> - */ - - "!!ARBfp1.0\n" - "PARAM gradient = program.local[0];\n" - "PARAM transform = program.local[1];\n" - "PARAM translate = program.local[2];\n" - "ATTRIB pos = fragment.texcoord[%d];\n" - "TEMP color, distance, position;\n" - - /* temporary */ - "%s" - - /* flip Y position */ - "SUB position.y, translate.z, pos.y;\n" + "END", NULL +}; +/* + * Radial gradient using 1D texture as color range. + * Color range in texture unit 2. + * + * param.local[0].x = center point X coordinate + * param.local[0].y = center point Y coordinate + * param.local[0].z = 1 / (radius1 - radius0) + * param.local[0].w = radius0 + * + * transform: + * [ a | c | tx ] + * [ b | d | ty ] + * [ 0 | 0 | 1 ] + * + * program.local[1].x = a + * program.local[1].y = b + * program.local[1].z = c + * program.local[1].w = d + * program.local[2].x = tx + * program.local[2].y = ty + * program.local[2].z = height + * + * Author: David Reveman <c99drn@cs.umu.se> + */ +static const char *_glitz_fragment_program_radial[] = { + "!!ARBfp1.0", + "PARAM gradient = program.local[0];", + "PARAM transform = program.local[1];", + "PARAM translate = program.local[2];", + "ATTRIB pos = fragment.texcoord[%s];", + "TEMP color, distance, position;", + + /* extra declerations */ + "%s", + + /* flip Y position (this should be done in advance) */ + "SUB position.y, translate.z, pos.y;", + /* transform X position */ - "MUL position.x, transform.x, pos.x;\n" - "MAD position.x, transform.z, position.y, position.x;\n" - "ADD position.x, position.x, translate.x;\n" + "MUL position.x, transform.x, pos.x;", + "MAD position.x, transform.z, position.y, position.x;", + "ADD position.x, position.x, translate.x;", /* transform Y position */ - "MUL position.y, transform.w, position.y;\n" - "MAD position.y, transform.y, pos.x, position.y;\n" - "ADD position.y, position.y, translate.y;\n" - + "MUL position.y, transform.w, position.y;", + "MAD position.y, transform.y, pos.x, position.y;", + "ADD position.y, position.y, translate.y;", + /* calculate gradient offset */ - "SUB distance, position, gradient;\n" + "SUB distance, position, gradient;", - "DP3 distance.x, distance, distance;\n" - "RSQ distance.w, distance.x;\n" + "DP3 distance.x, distance, distance;", + "RSQ distance.w, distance.x;", - "RCP distance.x, distance.w;\n" - "MUL distance.x, distance.x, distance.x;\n" - "MUL distance.x, distance.x, distance.w;\n" - - "SUB distance.x, distance.x, gradient.w;\n" - "MUL distance.x, distance.x, gradient.z;\n" + "RCP distance.x, distance.w;", + "MUL distance.x, distance.x, distance.x;", + "MUL distance.x, distance.x, distance.w;", - "TEX color, distance, texture[2], 1D;\n" - - "MUL color, color, fragment.color;\n" - - /* pd operation */ - "%s" + "SUB distance.x, distance.x, gradient.w;", + "MUL distance.x, distance.x, gradient.z;", - "END" + "TEX color, distance, texture[2], 1D;", + + /* IN operation */ + "%s", + + "END", NULL }; static glitz_gl_uint_t -glitz_program_compile_vertex_arb (glitz_gl_proc_address_list_t *gl, - char *program_string) +_glitz_compile_arb_vertex_program (glitz_gl_proc_address_list_t *gl, + char *program_string) { glitz_gl_int_t error; glitz_gl_uint_t program; - gl->gen_programs_arb (1, &program); - gl->bind_program_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, program); - gl->program_string_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, - GLITZ_GL_PROGRAM_FORMAT_ASCII_ARB, - strlen (program_string), - program_string); + gl->gen_programs (1, &program); + gl->bind_program (GLITZ_GL_VERTEX_PROGRAM, program); + gl->program_string (GLITZ_GL_VERTEX_PROGRAM, + GLITZ_GL_PROGRAM_FORMAT_ASCII, + strlen (program_string), + program_string); - gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION_ARB, &error); + gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error); if (error != -1) { - gl->delete_programs_arb (1, &program); + gl->delete_programs (1, &program); program = 0; } @@ -471,351 +348,208 @@ glitz_program_compile_vertex_arb (glitz_gl_proc_address_list_t *gl, } static glitz_gl_uint_t -glitz_program_compile_fragment_arb (glitz_gl_proc_address_list_t *gl, - char *program_string) +_glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl, + char *program_string) { glitz_gl_int_t error; glitz_gl_uint_t program; - - gl->gen_programs_arb (1, &program); - gl->bind_program_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, program); - gl->program_string_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - GLITZ_GL_PROGRAM_FORMAT_ASCII_ARB, - strlen (program_string), - program_string); + + gl->gen_programs (1, &program); + 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); - gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION_ARB, &error); + gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error); if (error != -1) { - gl->delete_programs_arb (1, &program); + gl->delete_programs (1, &program); program = 0; } return program; } -static int -_glitz_program_offset (glitz_texture_t *src_texture, - glitz_texture_t *mask_texture) -{ - int offset; - - if (src_texture) { - if (src_texture->target == GLITZ_GL_TEXTURE_2D) { - offset = GLITZ_PROGRAM_2DSRC_NOMASK_OFFSET; - - if (mask_texture) - offset = (mask_texture->target == GLITZ_GL_TEXTURE_2D)? - GLITZ_PROGRAM_2DSRC_2DMASK_OFFSET: - GLITZ_PROGRAM_2DSRC_RECTMASK_OFFSET; - } else { - offset = GLITZ_PROGRAM_RECTSRC_NOMASK_OFFSET; - - if (mask_texture) - offset = (mask_texture->target == GLITZ_GL_TEXTURE_2D)? - GLITZ_PROGRAM_RECTSRC_2DMASK_OFFSET: - GLITZ_PROGRAM_RECTSRC_RECTMASK_OFFSET; - } - } else { - offset = GLITZ_PROGRAM_NOSRC_NOMASK_OFFSET; - - if (mask_texture) - offset = (mask_texture->target == GLITZ_GL_TEXTURE_2D)? - GLITZ_PROGRAM_NOSRC_2DMASK_OFFSET: GLITZ_PROGRAM_NOSRC_RECTMASK_OFFSET; - } - - return offset; -} - -static glitz_gl_uint_t -glitz_program_compile_simple (glitz_gl_proc_address_list_t *gl, - int offset) +static void +_string_array_to_char_array (char *dst, const char *src[]) { - char program_buffer[256]; - const glitz_program_expand_t *expand = &_program_expand_map[offset]; + int i, n; - sprintf (program_buffer, - _glitz_fragment_program_simple, - expand->temporary, - expand->tex, - expand->operation); - - return glitz_program_compile_fragment_arb (gl, program_buffer); + for (i = 0; src[i]; i++) { + n = strlen (src[i]); + memcpy (dst, src[i], n); + dst += n; + } } static glitz_gl_uint_t -glitz_program_compile_vertex_convolution (glitz_gl_proc_address_list_t *gl, - int offset) +_glitz_create_vertex_program (glitz_render_op_t *op, + const glitz_program_expand_t *expand) { - char program_buffer[512]; - int conv_index = (offset)? 1: 0; - int other_index = (offset)? 0: 1; + char program[512], program_buffer[512]; - sprintf (program_buffer, - _glitz_vertex_program_convolution, - conv_index, conv_index, - other_index, other_index); - - return glitz_program_compile_vertex_arb (gl, program_buffer); -} - -static glitz_gl_uint_t -glitz_program_compile_convolution (glitz_gl_proc_address_list_t *gl, - int offset, - int solid_offset, - glitz_convolution_type_t type) -{ - static char *solid_op_table[] = { - "MUL result.color, color, fragment.color.a;\n", - "MUL result.color, fragment.color, color.a;\n", - }; - char program_buffer[1280]; - const glitz_program_expand_t *expand = &_program_expand_map[offset]; - char *temporary, *operation; - - if (solid_offset) { - temporary = ""; - operation = solid_op_table[solid_offset - 1]; - } else { - temporary = expand->temporary; - operation = expand->operation; - } - - switch (type) { - case GLITZ_CONVOLUTION_3X3_GENERAL: - sprintf (program_buffer, - _glitz_fragment_program_convolution, - temporary, - expand->index, expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - operation); + switch (op->type) { + case GLITZ_RENDER_TYPE_ARGBF: + case GLITZ_RENDER_TYPE_ARGBF_SOLID: + _string_array_to_char_array (program, _glitz_vertex_program_convolution); + sprintf (program_buffer, program, + "0", "0", "1", "1"); break; - case GLITZ_CONVOLUTION_3X3_SIMPLE: - sprintf (program_buffer, - _glitz_fragment_program_convolution_simple, - temporary, - expand->index, expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - expand->index, expand->tex, - operation); + case GLITZ_RENDER_TYPE_ARGBF_ARGB: + case GLITZ_RENDER_TYPE_ARGBF_ARGBC: + _string_array_to_char_array (program, _glitz_vertex_program_convolution); + sprintf (program_buffer, program, + "1", "1", "0", "0"); break; + default: + return 0; } - - return glitz_program_compile_fragment_arb (gl, program_buffer); + + return _glitz_compile_arb_vertex_program (op->gl, program_buffer); } static glitz_gl_uint_t -glitz_program_compile_programmatic (glitz_programmatic_surface_type_t type, - glitz_gl_proc_address_list_t *gl, - int offset) +_glitz_create_fragment_program (glitz_render_op_t *op, + const glitz_program_expand_t *expand) { - char program_buffer[1024]; - const glitz_program_expand_t *expand = &_program_expand_map[offset]; - - switch (type) { - case GLITZ_PROGRAMMATIC_SURFACE_SOLID_TYPE: - sprintf (program_buffer, - _glitz_fragment_program_programmatic[type], - expand->temporary, - expand->operation); + char program[2048], program_buffer[2048]; + + switch (op->type) { + case GLITZ_RENDER_TYPE_ARGBF: + case GLITZ_RENDER_TYPE_ARGBF_SOLID: + _string_array_to_char_array (program, _glitz_fragment_program_convolution); + sprintf (program_buffer, program, + expand->declarations, + "0", "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + "0", expand->texture, + expand->in); + break; + case GLITZ_RENDER_TYPE_ARGBF_ARGB: + case GLITZ_RENDER_TYPE_ARGBF_ARGBC: + _string_array_to_char_array (program, _glitz_fragment_program_convolution); + sprintf (program_buffer, program, + expand->declarations, + "1", "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + "1", expand->texture, + expand->in); + break; + case GLITZ_RENDER_TYPE_LGRAD: + case GLITZ_RENDER_TYPE_LGRAD_SOLID: + _string_array_to_char_array (program, _glitz_fragment_program_linear); + sprintf (program_buffer, program, + "0", + expand->declarations, + expand->in); + break; + case GLITZ_RENDER_TYPE_LGRAD_ARGB: + case GLITZ_RENDER_TYPE_LGRAD_ARGBC: + _string_array_to_char_array (program, _glitz_fragment_program_linear); + sprintf (program_buffer, program, + "1", + expand->declarations, + expand->in); + break; + case GLITZ_RENDER_TYPE_RGRAD: + case GLITZ_RENDER_TYPE_RGRAD_SOLID: + _string_array_to_char_array (program, _glitz_fragment_program_radial); + sprintf (program_buffer, program, + "0", + expand->declarations, + expand->in); break; - case GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE: - case GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE: - sprintf (program_buffer, - _glitz_fragment_program_programmatic[type], - expand->index, - expand->temporary, - expand->operation); + case GLITZ_RENDER_TYPE_RGRAD_ARGB: + case GLITZ_RENDER_TYPE_RGRAD_ARGBC: + _string_array_to_char_array (program, _glitz_fragment_program_radial); + sprintf (program_buffer, program, + "1", + expand->declarations, + expand->in); break; + default: + return 0; } - - return glitz_program_compile_fragment_arb (gl, program_buffer); + + return _glitz_compile_arb_fragment_program (op->gl, program_buffer); } +static int +_texture_index (glitz_texture_t *texture) +{ + if (texture) { + if (texture->target == GLITZ_GL_TEXTURE_2D) + return GLITZ_TEXTURE_2D; + else + return GLITZ_TEXTURE_RECT; + } else + return GLITZ_TEXTURE_NONE; +} + void -glitz_program_enable_argb_argb (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture) +glitz_program_map_init (glitz_program_map_t *map) { - int offset; - - offset = _glitz_program_offset (src_texture, mask_texture); - - if (!programs->fragment_simple[offset]) - programs->fragment_simple[offset] = - glitz_program_compile_simple (gl, offset); - - if (programs->fragment_simple[offset]) { - gl->enable (GLITZ_GL_FRAGMENT_PROGRAM_ARB); - gl->bind_program_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - programs->fragment_simple[offset]); - } + memset (map, 0, sizeof (glitz_program_map_t)); } void -glitz_program_enable_convolution (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - int offset, - int solid_offset, - unsigned short opacity) +glitz_program_map_fini (glitz_gl_proc_address_list_t *gl, + glitz_program_map_t *map) { - glitz_texture_t *texture; - glitz_surface_t *surface; - int fragment_offset, vertex_offset = (offset)? 1: 0; - glitz_convolution_type_t type; - - if (offset) { - texture = mask_texture; - surface = mask; - } else { - texture = src_texture; - surface = src; - } - - offset += _glitz_program_offset (src_texture, mask_texture); - - if (surface->convolution->m[0][0] == 0.0 && - surface->convolution->m[0][2] == 0.0 && - surface->convolution->m[2][2] == 0.0 && - surface->convolution->m[2][0] == 0.0) - type = GLITZ_CONVOLUTION_3X3_SIMPLE; - else - type = GLITZ_CONVOLUTION_3X3_GENERAL; - - fragment_offset = GLITZ_FRAGMENT_PROGRAM_TYPES * solid_offset * type + - offset; - - if (!programs->vertex_convolution[vertex_offset]) - programs->vertex_convolution[vertex_offset] = - glitz_program_compile_vertex_convolution (gl, vertex_offset); - - if (!programs->fragment_convolution[fragment_offset]) - programs->fragment_convolution[fragment_offset] = - glitz_program_compile_convolution (gl, offset, solid_offset, type); - - if (programs->fragment_convolution[fragment_offset] && - programs->vertex_convolution[vertex_offset]) { - - gl->enable (GLITZ_GL_VERTEX_PROGRAM_ARB); - gl->bind_program_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, - programs->vertex_convolution[vertex_offset]); - gl->program_local_param_4d_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, 0, - texture->texcoord_width / - (double) texture->width, - 0.000, 0.0, 0.0); - gl->program_local_param_4d_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, 1, - 0.000, - texture->texcoord_height / - (double) texture->height, - 0.0, 0.0); + int i, x, y; - gl->enable (GLITZ_GL_FRAGMENT_PROGRAM_ARB); - gl->bind_program_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - programs->fragment_convolution[fragment_offset]); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 0, - surface->convolution->m[0][0], - surface->convolution->m[0][1], - surface->convolution->m[0][2], - 0.0); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 1, - surface->convolution->m[1][0], - surface->convolution->m[1][1], - surface->convolution->m[1][2], - 0.0); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 2, - surface->convolution->m[2][0], - surface->convolution->m[2][1], - surface->convolution->m[2][2], - 0.0); - - if (solid_offset && mask) { - glitz_color_t *color; - - if (solid_offset == 1) - color = &((glitz_programmatic_surface_t *) mask)->u.solid.color; - else - color = &((glitz_programmatic_surface_t *) src)->u.solid.color; - - gl->color_4us (color->red, color->green, color->blue, color->alpha); - } else - gl->color_4us (opacity, opacity, opacity, opacity); + for (i = 0; i < GLITZ_RENDER_TYPES; i++) { + for (x = 0; x < GLITZ_TEXTURE_LAST; x++) + for (y = 0; y < GLITZ_TEXTURE_LAST; y++) { + if (map->info[i].vertex[x][y]) + gl->delete_programs (1, &map->info[i].vertex[x][y]); + if (map->info[i].fragment[x][y]) + gl->delete_programs (1, &map->info[i].vertex[x][y]); + } } } -void -glitz_program_enable_programmatic (glitz_surface_t *dst, - glitz_programmatic_surface_t *surface, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - int offset, - unsigned short opacity) +glitz_gl_uint_t +glitz_get_vertex_program (glitz_render_op_t *op) { - int type_offset, add_offset; - glitz_programs_t *programs = dst->programs; - - if (offset) - add_offset = _glitz_program_offset (src_texture, NULL); - else - add_offset = _glitz_program_offset (NULL, mask_texture); - - offset += add_offset; - - type_offset = offset + GLITZ_FRAGMENT_PROGRAM_TYPES * surface->type; - - if (dst->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) { - if (!programs->fragment_programmatic[type_offset]) - programs->fragment_programmatic[type_offset] = - glitz_program_compile_programmatic (surface->type, dst->gl, offset); - - if (programs->fragment_programmatic[type_offset]) { - dst->gl->enable (GLITZ_GL_FRAGMENT_PROGRAM_ARB); - dst->gl->bind_program_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, - programs->fragment_programmatic[type_offset]); + glitz_gl_uint_t *program; + int index1 = _texture_index (op->src_texture); + int index2 = _texture_index (op->mask_texture); - glitz_programmatic_surface_bind (dst->gl, surface, dst->feature_mask, - 0xffff); + program = &op->dst->program_map->info[op->type].vertex[index1][index2]; + + if (*program == 0) + *program = + _glitz_create_vertex_program (op, &_program_expand_map[index1][index2]); - dst->gl->color_4us (opacity, opacity, opacity, opacity); - } - } + return *program; } -void -glitz_programs_fini (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs) +glitz_gl_uint_t +glitz_get_fragment_program (glitz_render_op_t *op) { - int i; + glitz_gl_uint_t *program; + int index1 = _texture_index (op->src_texture); + int index2 = _texture_index (op->mask_texture); + + program = &op->dst->program_map->info[op->type].fragment[index1][index2]; - for (i = 0; i < GLITZ_VERTEX_PROGRAM_TYPES; i++) { - if (programs->vertex_convolution[i]) - gl->delete_programs_arb (1, &programs->vertex_convolution[i]); - } - - for (i = 0; i < GLITZ_FRAGMENT_PROGRAM_TYPES; i++) { - if (programs->fragment_simple[i]) - gl->delete_programs_arb (1, &programs->fragment_simple[i]); - } - - for (i = 0; i < (GLITZ_FRAGMENT_PROGRAM_TYPES * 3); i++) { - if (programs->fragment_convolution[i]) - gl->delete_programs_arb (1, &programs->fragment_convolution[i]); - } + if (*program == 0) + *program = + _glitz_create_fragment_program (op, + &_program_expand_map[index1][index2]); - for (i = 0; i < GLITZ_FRAGMENT_PROGRAMMATIC_PROGRAM_TYPES; i++) { - if (programs->fragment_programmatic[i]) - gl->delete_programs_arb (1, &programs->fragment_programmatic[i]); - } + return *program; } diff --git a/src/glitz_programmatic.c b/src/glitz_programmatic.c index cafdd26..7a4ead5 100644 --- a/src/glitz_programmatic.c +++ b/src/glitz_programmatic.c @@ -31,8 +31,6 @@ #include "glitzint.h" -#include <math.h> - static glitz_surface_t * _glitz_programmatic_surface_create_similar (void *abstract_templ, glitz_format_t *format, @@ -49,10 +47,10 @@ _glitz_programmatic_surface_destroy (void *abstract_surface) (glitz_programmatic_surface_t *) abstract_surface; switch (surface->type) { - case GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE: + case GLITZ_PROGRAMMATIC_SURFACE_TYPE_LINEAR: glitz_color_range_destroy (surface->u.linear.color_range); break; - case GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE: + case GLITZ_PROGRAMMATIC_SURFACE_TYPE_RADIAL: glitz_color_range_destroy (surface->u.radial.color_range); default: break; @@ -137,28 +135,16 @@ _glitz_programmatic_surface_create (void) surface->base.texture.target = GLITZ_GL_TEXTURE_2D; surface->base.texture.format = GLITZ_GL_RGBA; surface->base.texture.filter = surface->base.filter; - surface->base.texture.texcoord_width = - surface->base.texture.texcoord_height = 1.0; + surface->base.texture.texcoord_width = surface->base.width = + surface->base.texture.width = MAXSHORT; + surface->base.texture.texcoord_height = surface->base.height = + surface->base.texture.height = MAXSHORT; surface->base.texture.repeatable = surface->base.texture.repeat = 1; surface->matrix = identity; return surface; } -void -glitz_programmatic_surface_setup (glitz_surface_t *abstract_surface, - int width, - int height) -{ - glitz_programmatic_surface_t *surface = - (glitz_programmatic_surface_t *) abstract_surface; - - surface->base.texture.texcoord_width = surface->base.width = - surface->base.texture.width = width; - surface->base.texture.texcoord_height = surface->base.height = - surface->base.texture.height = height; -} - glitz_surface_t * glitz_programmatic_surface_create_solid (glitz_color_t *color) { @@ -168,7 +154,7 @@ glitz_programmatic_surface_create_solid (glitz_color_t *color) if (!surface) return NULL; - surface->type = GLITZ_PROGRAMMATIC_SURFACE_SOLID_TYPE; + surface->type = GLITZ_PROGRAMMATIC_SURFACE_TYPE_SOLID; surface->u.solid.color = *color; return &surface->base; @@ -185,7 +171,7 @@ glitz_programmatic_surface_create_linear (glitz_point_fixed_t *start, if (!surface) return NULL; - surface->type = GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE; + surface->type = GLITZ_PROGRAMMATIC_SURFACE_TYPE_LINEAR; surface->u.linear.start = *start; surface->u.linear.stop = *stop; surface->u.linear.color_range = color_range; @@ -206,7 +192,7 @@ glitz_programmatic_surface_create_radial (glitz_point_fixed_t *start, if (!surface) return NULL; - surface->type = GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE; + surface->type = GLITZ_PROGRAMMATIC_SURFACE_TYPE_RADIAL; surface->u.radial.center = *start; surface->u.radial.radius0 = radius0; surface->u.radial.radius1 = radius1; @@ -231,84 +217,3 @@ glitz_programmatic_surface_set_transform (glitz_surface_t *abstract_surface, surface->matrix.m[1][1] = FIXED_TO_DOUBLE (transform->matrix[1][1]); surface->matrix.m[2][1] = FIXED_TO_DOUBLE (transform->matrix[1][2]); } - -void -glitz_programmatic_surface_bind (glitz_gl_proc_address_list_t *gl, - glitz_programmatic_surface_t *surface, - unsigned long feature_mask, - unsigned short opacity) -{ - switch (surface->type) { - case GLITZ_PROGRAMMATIC_SURFACE_SOLID_TYPE: - if (opacity != 0xffff) { - gl->color_4us (SHORT_MODULATE (surface->u.solid.color.red, opacity), - SHORT_MODULATE (surface->u.solid.color.green, opacity), - SHORT_MODULATE (surface->u.solid.color.blue, opacity), - SHORT_MODULATE (surface->u.solid.color.alpha, opacity)); - } else - gl->color_4us (surface->u.solid.color.red, - surface->u.solid.color.green, - surface->u.solid.color.blue, - surface->u.solid.color.alpha); - break; - case GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE: { - glitz_point_t p1, p2; - double length, angle, start; - - p1.x = FIXED_TO_DOUBLE (surface->u.linear.start.x); - p1.y = FIXED_TO_DOUBLE (surface->u.linear.start.y); - p2.x = FIXED_TO_DOUBLE (surface->u.linear.stop.x); - p2.y = FIXED_TO_DOUBLE (surface->u.linear.stop.y); - - length = sqrt ((p2.x - p1.x) * (p2.x - p1.x) + - (p2.y - p1.y) * (p2.y - p1.y)); - - angle = -atan2 (p2.y - p1.y, p2.x - p1.x); - - start = cos (angle) * p1.x; - start += -sin (angle) * p1.y; - - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 0, - start, - (length)? 1.0 / length: INT_MAX, - cos (angle), - -sin (angle)); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 1, - surface->matrix.m[0][0], - surface->matrix.m[0][1], - surface->matrix.m[1][0], - surface->matrix.m[1][1]); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 2, - surface->matrix.m[2][0], - surface->matrix.m[2][1], - surface->base.height, 0.0); - - gl->active_texture_arb (GLITZ_GL_TEXTURE2_ARB); - glitz_color_range_bind (gl, surface->u.linear.color_range, feature_mask); - gl->active_texture_arb (GLITZ_GL_TEXTURE0_ARB); - } break; - case GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE: - gl->program_local_param_4d_arb - (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 0, - FIXED_TO_DOUBLE (surface->u.radial.center.x), - FIXED_TO_DOUBLE (surface->u.radial.center.y), - 1.0 / (FIXED_TO_DOUBLE (surface->u.radial.radius1) - - FIXED_TO_DOUBLE (surface->u.radial.radius0)), - FIXED_TO_DOUBLE (surface->u.radial.radius0)); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 1, - surface->matrix.m[0][0], - surface->matrix.m[0][1], - surface->matrix.m[1][0], - surface->matrix.m[1][1]); - gl->program_local_param_4d_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 2, - surface->matrix.m[2][0], - surface->matrix.m[2][1], - surface->base.height, 0.0); - - gl->active_texture_arb (GLITZ_GL_TEXTURE2_ARB); - glitz_color_range_bind (gl, surface->u.radial.color_range, feature_mask); - gl->active_texture_arb (GLITZ_GL_TEXTURE0_ARB); - default: - break; - } -} diff --git a/src/glitz_render.c b/src/glitz_render.c index 479e66d..f459b7f 100644 --- a/src/glitz_render.c +++ b/src/glitz_render.c @@ -1,25 +1,24 @@ /* - * Copyright © 2004 David Reveman, Peter Nilsson - * + * Copyright © 2004 David Reveman + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the names of - * David Reveman and Peter Nilsson not be used in advertising or - * publicity pertaining to distribution of the software without - * specific, written prior permission. David Reveman and Peter Nilsson - * makes no representations about the suitability of this software for - * any purpose. It is provided "as is" without express or implied warranty. + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. * - * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND - * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <c99drn@cs.umu.se> */ @@ -30,168 +29,668 @@ #include "glitzint.h" -glitz_render_type_t -glitz_render_type (glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst) +#include <math.h> + +static void +_glitz_render_argb_solid (glitz_render_op_t *op) { - int src_conv, mask_conv; + if (op->alpha_mask.alpha != 0xffff) { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + op->gl->color_4us (op->alpha_mask.alpha, + op->alpha_mask.alpha, + op->alpha_mask.alpha, + op->alpha_mask.alpha); + } else { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + } +} - if (dst->feature_mask & GLITZ_FEATURE_CONVOLUTION_FILTER_MASK) { - src_conv = (src->convolution)? 1: 0; - mask_conv = (mask && mask->convolution)? 1: 0; - } else - src_conv = mask_conv = 0; +static void +_glitz_render_argb_argb (glitz_render_op_t *op) +{ + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_ALPHA); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, + GLITZ_GL_SRC_ALPHA); +} + +static void +_setup_x_argbc (glitz_render_op_t *op) +{ + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_INTERPOLATE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE2_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND2_RGB, + GLITZ_GL_SRC_ALPHA); + + /* we don't care about the alpha channel, so lets do something (simple?) */ + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_REPLACE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); - if (!mask) { - if (SURFACE_SOLID (src)) - return GLITZ_RENDER_TYPE_SOLID; - else if ((!src_conv) && (!SURFACE_PROGRAMMATIC (src))) - return GLITZ_RENDER_TYPE_ARGB; - else if (SURFACE_PROGRAMMATIC (src) && - (dst->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK)) - return GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC; + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_DOT3_RGBA); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); +} + +static void +_glitz_render_argb_argbc (glitz_render_op_t *op) +{ + if (op->count == 0) { + _setup_x_argbc (op); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + } + + if (op->alpha_mask.red) { + op->gl->color_4d (1.0, 0.5, 0.5, 0.5); + } else if (op->alpha_mask.green) { + op->gl->color_4d (0.5, 1.0, 0.5, 0.5); + } else if (op->alpha_mask.blue) { + op->gl->color_4d (0.5, 0.5, 1.0, 0.5); + } else { + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + glitz_texture_unbind (op->gl, op->src_texture); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); } +} - if ((!src_conv) && - mask && (!SURFACE_PROGRAMMATIC (mask)) && (!mask_conv)) { - if ((mask->texture.format == GLITZ_GL_INTENSITY4 || - mask->texture.format == GLITZ_GL_INTENSITY8 || - mask->texture.format == GLITZ_GL_INTENSITY12 || - mask->texture.format == GLITZ_GL_INTENSITY16) && - (dst->feature_mask & GLITZ_FEATURE_ARB_MULTITEXTURE_MASK)) { - if (SURFACE_SOLID (src)) - return GLITZ_RENDER_TYPE_SOLID_A; - else if (!SURFACE_PROGRAMMATIC (src)) - return GLITZ_RENDER_TYPE_ARGB_A; - else if (dst->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) - return GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC; - } else if (dst->feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) { - if (!SURFACE_PROGRAMMATIC (src)) - return GLITZ_RENDER_TYPE_ARGB_ARGB; - else - return GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC; - } + +static void +_glitz_render_solid_solid (glitz_render_op_t *op) +{ + op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), + SHORT_MULT (op->solid->green, op->alpha_mask.alpha), + SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), + SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); +} + +static void +_glitz_render_solid_argb (glitz_render_op_t *op) +{ + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, + GLITZ_GL_SRC_ALPHA); + + op->gl->color_4us (op->solid->red, + op->solid->green, + op->solid->blue, + op->solid->alpha); +} + +static void +_glitz_render_solid_argbc (glitz_render_op_t *op) +{ + if (op->count == 0) { + glitz_gl_float_t color[4]; + + _setup_x_argbc (op); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_CONSTANT); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, + GLITZ_GL_CONSTANT); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, + GLITZ_GL_SRC_ALPHA); + + color[0] = (double) op->solid->red / 65536.0; + color[1] = (double) op->solid->green / 65536.0; + color[2] = (double) op->solid->blue / 65536.0; + color[3] = (double) op->solid->alpha / 65536.0; + + op->gl->tex_env_fv (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_COLOR, + color); + } + + if (op->alpha_mask.red) { + op->gl->color_4d (1.0, 0.5, 0.5, 0.5); + } else if (op->alpha_mask.green) { + op->gl->color_4d (0.5, 1.0, 0.5, 0.5); + } else if (op->alpha_mask.blue) { + op->gl->color_4d (0.5, 0.5, 1.0, 0.5); + } else { + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + op->gl->color_4us (op->solid->red, + op->solid->green, + op->solid->blue, + op->solid->alpha); + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + glitz_texture_unbind (op->gl, op->src_texture); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + glitz_texture_unbind (op->gl, op->src_texture); } +} + +static void +_glitz_render_argbf (glitz_render_op_t *op) +{ + if (op->count == 0) { + glitz_gl_uint_t vertex_program, fragment_program; + + vertex_program = glitz_get_vertex_program (op); + fragment_program = glitz_get_fragment_program (op); - if (src_conv) { - if (mask && SURFACE_SOLID (mask)) { - return GLITZ_RENDER_TYPE_SRC_CONVOLUTION_AND_SOLID_MASK; - } else if ((!mask) || (!SURFACE_PROGRAMMATIC (mask))) - return GLITZ_RENDER_TYPE_SRC_CONVOLUTION; + if (vertex_program && fragment_program) { + glitz_texture_t *texture = op->src_texture; + glitz_surface_t *surface = op->src; + + op->gl->enable (GLITZ_GL_VERTEX_PROGRAM); + op->gl->bind_program (GLITZ_GL_VERTEX_PROGRAM, vertex_program); + op->gl->program_local_param_4d (GLITZ_GL_VERTEX_PROGRAM, 0, + texture->texcoord_width / + (double) texture->width, + 0.000, 0.0, 0.0); + op->gl->program_local_param_4d (GLITZ_GL_VERTEX_PROGRAM, 1, + 0.000, + texture->texcoord_height / + (double) texture->height, + 0.0, 0.0); + + op->gl->enable (GLITZ_GL_FRAGMENT_PROGRAM); + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, fragment_program); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 0, + surface->convolution->m[0][0], + surface->convolution->m[0][1], + surface->convolution->m[0][2], 0.0); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 1, + surface->convolution->m[1][0], + surface->convolution->m[1][1], + surface->convolution->m[1][2], 0.0); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 2, + surface->convolution->m[2][0], + surface->convolution->m[2][1], + surface->convolution->m[2][2], 0.0); + } + + op->gl->color_4us (op->alpha_mask.red, + op->alpha_mask.green, + op->alpha_mask.blue, + op->alpha_mask.alpha); } +} + +static void +_glitz_end_f (glitz_render_op_t *op) +{ + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); + op->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM); + op->gl->bind_program (GLITZ_GL_VERTEX_PROGRAM, 0); + op->gl->disable (GLITZ_GL_VERTEX_PROGRAM); +} + +static void +_glitz_render_lgrad (glitz_render_op_t *op) +{ + if (op->count == 0) { + glitz_gl_uint_t fragment_program; + + fragment_program = glitz_get_fragment_program (op); + + if (fragment_program) { + glitz_programmatic_surface_t *surface = + (glitz_programmatic_surface_t *) op->src; + glitz_point_t p1, p2; + double length, angle, start; - if (mask_conv) { - if (SURFACE_SOLID (src)) { - return GLITZ_RENDER_TYPE_MASK_CONVOLUTION_AND_SOLID_SRC; - } else if (!SURFACE_PROGRAMMATIC (src)) - return GLITZ_RENDER_TYPE_MASK_CONVOLUTION; + op->gl->enable (GLITZ_GL_FRAGMENT_PROGRAM); + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, fragment_program); + + p1.x = FIXED_TO_DOUBLE (surface->u.linear.start.x); + p1.y = FIXED_TO_DOUBLE (surface->u.linear.start.y); + p2.x = FIXED_TO_DOUBLE (surface->u.linear.stop.x); + p2.y = FIXED_TO_DOUBLE (surface->u.linear.stop.y); + + length = sqrt ((p2.x - p1.x) * (p2.x - p1.x) + + (p2.y - p1.y) * (p2.y - p1.y)); + + angle = -atan2 (p2.y - p1.y, p2.x - p1.x); + + start = cos (angle) * p1.x; + start += -sin (angle) * p1.y; + + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 0, start, + (length)? 1.0 / length: INT_MAX, + cos (angle), -sin (angle)); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 1, + surface->matrix.m[0][0], + surface->matrix.m[0][1], + surface->matrix.m[1][0], + surface->matrix.m[1][1]); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 2, + surface->matrix.m[2][0], + surface->matrix.m[2][1], + surface->base.height, 0.0); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + glitz_color_range_bind (op->gl, surface->u.linear.color_range, + op->dst->feature_mask); + op->gl->active_texture (GLITZ_GL_TEXTURE0); + } } + + op->gl->color_4us (op->alpha_mask.red, + op->alpha_mask.green, + op->alpha_mask.blue, + op->alpha_mask.alpha); +} + +static void +_glitz_render_rgrad (glitz_render_op_t *op) +{ + if (op->count == 0) { + glitz_gl_uint_t fragment_program; + + fragment_program = glitz_get_fragment_program (op); - return GLITZ_RENDER_TYPE_NOT_SUPPORTED; + if (fragment_program) { + glitz_programmatic_surface_t *surface = + (glitz_programmatic_surface_t *) op->src; + + op->gl->enable (GLITZ_GL_FRAGMENT_PROGRAM); + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, fragment_program); + + op->gl->program_local_param_4d + (GLITZ_GL_FRAGMENT_PROGRAM, 0, + FIXED_TO_DOUBLE (surface->u.radial.center.x), + FIXED_TO_DOUBLE (surface->u.radial.center.y), + 1.0 / (FIXED_TO_DOUBLE (surface->u.radial.radius1) - + FIXED_TO_DOUBLE (surface->u.radial.radius0)), + FIXED_TO_DOUBLE (surface->u.radial.radius0)); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 1, + surface->matrix.m[0][0], + surface->matrix.m[0][1], + surface->matrix.m[1][0], + surface->matrix.m[1][1]); + op->gl->program_local_param_4d (GLITZ_GL_FRAGMENT_PROGRAM, 2, + surface->matrix.m[2][0], + surface->matrix.m[2][1], + surface->base.height, 0.0); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + glitz_color_range_bind (op->gl, surface->u.radial.color_range, + op->dst->feature_mask); + op->gl->active_texture (GLITZ_GL_TEXTURE0); + } + } + + op->gl->color_4us (op->alpha_mask.red, + op->alpha_mask.green, + op->alpha_mask.blue, + op->alpha_mask.alpha); } -void -glitz_render_enable (glitz_render_type_t type, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - unsigned short opacity) -{ - switch (type) { - case GLITZ_RENDER_TYPE_ARGB: - if (opacity != 0xffff) { - dst->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, - GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - dst->gl->color_4us (opacity, opacity, opacity, opacity); - } else { - dst->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, - GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - dst->gl->color_4us (0x0, 0x0, 0x0, 0xffff); +static void +_glitz_end_grad (glitz_render_op_t *op) +{ + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->bind_texture (GLITZ_GL_TEXTURE_1D, 0); + op->gl->disable (GLITZ_GL_TEXTURE_1D); + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); + op->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM); +} + +static glitz_render_t +_glitz_render_map[GLITZ_SURFACE_TYPES][GLITZ_SURFACE_TYPES] = { + { + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_ARGB, _glitz_render_argb_solid, NULL, 1 }, + { GLITZ_RENDER_TYPE_ARGB_ARGB, _glitz_render_argb_argb, NULL, 2 }, + { GLITZ_RENDER_TYPE_ARGB_ARGBC, _glitz_render_argb_argbc, NULL, 3 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_ARGB_SOLID, _glitz_render_argb_solid, NULL, 1 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_ARGB, _glitz_render_argb_solid, NULL, 1 }, + { GLITZ_RENDER_TYPE_ARGB_ARGB, _glitz_render_argb_argb, NULL, 2 }, + { GLITZ_RENDER_TYPE_ARGB_ARGBC, _glitz_render_argb_argbc, NULL, 3 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_ARGB_SOLID, _glitz_render_argb_solid, NULL, 1 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_ARGBF, _glitz_render_argbf, _glitz_end_f, 1 }, + { GLITZ_RENDER_TYPE_ARGBF_ARGB, _glitz_render_argbf, _glitz_end_f, 2 }, + { GLITZ_RENDER_TYPE_ARGBF_ARGBC, _glitz_render_argbf, _glitz_end_f, 2 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_ARGBF_SOLID, _glitz_render_argbf, _glitz_end_f, 1 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_SOLID, _glitz_render_solid_solid, NULL, 0 }, + { GLITZ_RENDER_TYPE_SOLID_ARGB, _glitz_render_solid_argb, NULL, 1 }, + { GLITZ_RENDER_TYPE_SOLID_ARGBC, _glitz_render_solid_argbc, NULL, 3 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_SOLID_SOLID, _glitz_render_solid_solid, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_LGRAD, _glitz_render_lgrad, _glitz_end_grad, 0 }, + { GLITZ_RENDER_TYPE_LGRAD_ARGB, _glitz_render_lgrad, _glitz_end_grad, 2 }, + { GLITZ_RENDER_TYPE_LGRAD_ARGBC, _glitz_render_lgrad, _glitz_end_grad, 2 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_LGRAD_SOLID, _glitz_render_lgrad, _glitz_end_grad, 1 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + }, { + { GLITZ_RENDER_TYPE_RGRAD, _glitz_render_rgrad, _glitz_end_grad, 0 }, + { GLITZ_RENDER_TYPE_RGRAD_ARGB, _glitz_render_rgrad, _glitz_end_grad, 2 }, + { GLITZ_RENDER_TYPE_RGRAD_ARGBC, _glitz_render_rgrad, _glitz_end_grad, 2 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_RGRAD_SOLID, _glitz_render_rgrad, _glitz_end_grad, 1 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 }, + { GLITZ_RENDER_TYPE_NA, NULL, NULL, 0 } + } +}; + +#define MANUAL_REPEAT(surface) \ + (((surface)->hint_mask & GLITZ_INT_HINT_REPEAT_MASK) && \ + (!(surface)->texture.repeatable)) + +#define ROTATING_TRANSFORM(surface) \ + ((surface)->transform && \ + (((surface)->transform->m[0][1] != 0.0) || \ + ((surface)->transform->m[1][0] != 0.0))) + +#define SIMPLE_SURFACE(surface) \ + ((!MANUAL_REPEAT (surface)) && (!ROTATING_TRANSFORM (surface))) + +#define MULTI_TEXTURE(feature_mask, src, mask) \ + (((feature_mask) & GLITZ_FEATURE_ARB_MULTITEXTURE_MASK) && \ + (SIMPLE_SURFACE (src) && SIMPLE_SURFACE (mask))) + +static glitz_surface_type_t +_glitz_get_surface_type (unsigned long feature_mask, + glitz_surface_t *surface) +{ + if (surface == NULL) + return GLITZ_SURFACE_TYPE_NULL; + + if (SURFACE_PROGRAMMATIC (surface)) { + if (SURFACE_SOLID (surface)) + return GLITZ_SURFACE_TYPE_SOLID; + else if (feature_mask & GLITZ_FEATURE_ARB_FRAGMENT_PROGRAM_MASK) { + if (SURFACE_LINEAR_GRADIENT (surface)) + return GLITZ_SURFACE_TYPE_LGRAD; + else + return GLITZ_SURFACE_TYPE_RGRAD; } - break; - case GLITZ_RENDER_TYPE_ARGB_ARGB: - glitz_program_enable_argb_argb (dst->gl, dst->programs, - src_texture, mask_texture); - break; - case GLITZ_RENDER_TYPE_SOLID_A: - glitz_programmatic_surface_bind (dst->gl, - (glitz_programmatic_surface_t *) src, - dst->feature_mask, - 0xffff); - break; - case GLITZ_RENDER_TYPE_ARGB_A: - break; - case GLITZ_RENDER_TYPE_SOLID: - glitz_programmatic_surface_bind (dst->gl, - (glitz_programmatic_surface_t *) src, - dst->feature_mask, - opacity); - break; - case GLITZ_RENDER_TYPE_SRC_CONVOLUTION: - case GLITZ_RENDER_TYPE_SRC_CONVOLUTION_AND_SOLID_MASK: - glitz_program_enable_convolution (dst->gl, dst->programs, - src, mask, src_texture, mask_texture, - GLITZ_PROGRAM_SRC_OPERATION_OFFSET, 1, - opacity); - break; - case GLITZ_RENDER_TYPE_MASK_CONVOLUTION: - glitz_program_enable_convolution (dst->gl, dst->programs, - src, mask, src_texture, mask_texture, - GLITZ_PROGRAM_MASK_OPERATION_OFFSET, 0, - 0xffff); - break; - case GLITZ_RENDER_TYPE_MASK_CONVOLUTION_AND_SOLID_SRC: - glitz_program_enable_convolution (dst->gl, dst->programs, - src, mask, src_texture, mask_texture, - GLITZ_PROGRAM_MASK_OPERATION_OFFSET, 2, - 0xffff); - break; - case GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC: - glitz_program_enable_programmatic (dst, - (glitz_programmatic_surface_t *) src, - src_texture, mask_texture, - GLITZ_PROGRAM_SRC_OPERATION_OFFSET, - opacity); - break; - case GLITZ_RENDER_TYPE_MASK_PROGRAMMATIC: - glitz_program_enable_programmatic (dst, - (glitz_programmatic_surface_t *) mask, - src_texture, mask_texture, - GLITZ_PROGRAM_MASK_OPERATION_OFFSET, - 0xffff); - break; - case GLITZ_RENDER_TYPE_NOT_SUPPORTED: - break; + } else { + if (!surface->convolution) { + if (SURFACE_COMPONENT_ALPHA (surface)) { + if (feature_mask & GLITZ_FEATURE_COMPONENT_ALPHA_MASK) + return GLITZ_SURFACE_TYPE_ARGBC; + } else + return GLITZ_SURFACE_TYPE_ARGB; + + } else if (feature_mask & GLITZ_FEATURE_CONVOLUTION_FILTER_MASK) + return GLITZ_SURFACE_TYPE_ARGBF; } + + return GLITZ_SURFACE_TYPE_NA; } +static glitz_color_t _default_alpha_mask = { + 0x0000, 0x0000, 0x0000, 0xffff +}; + void -glitz_render_disable (glitz_render_type_t type, - glitz_surface_t *dst) -{ - switch (type) { - case GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC: - case GLITZ_RENDER_TYPE_MASK_PROGRAMMATIC: - dst->gl->active_texture_arb (GLITZ_GL_TEXTURE2_ARB); - dst->gl->bind_texture (GLITZ_GL_TEXTURE_1D, 0); - dst->gl->disable (GLITZ_GL_TEXTURE_1D); - dst->gl->active_texture_arb (GLITZ_GL_TEXTURE0_ARB); - /* fall-through */ - case GLITZ_RENDER_TYPE_SRC_CONVOLUTION: - case GLITZ_RENDER_TYPE_SRC_CONVOLUTION_AND_SOLID_MASK: - case GLITZ_RENDER_TYPE_MASK_CONVOLUTION: - case GLITZ_RENDER_TYPE_MASK_CONVOLUTION_AND_SOLID_SRC: - dst->gl->bind_program_arb (GLITZ_GL_FRAGMENT_PROGRAM_ARB, 0); - dst->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM_ARB); - dst->gl->bind_program_arb (GLITZ_GL_VERTEX_PROGRAM_ARB, 0); - dst->gl->disable (GLITZ_GL_VERTEX_PROGRAM_ARB); - break; - default: - break; +glitz_render_op_init (glitz_render_op_t *op, + glitz_surface_t **src, + glitz_surface_t **mask, + glitz_surface_t *dst, + int *x_src, + int *y_src, + int *x_mask, + int *y_mask) +{ + glitz_surface_type_t src_type; + glitz_surface_type_t mask_type; + glitz_render_t *render; + + op->type = GLITZ_RENDER_TYPE_NA; + op->render = NULL; + op->alpha_mask = _default_alpha_mask; + op->gl = dst->gl; + op->dst = dst; + op->src_texture = op->mask_texture = NULL; + op->count = 0; + op->src = *src; + op->mask = *mask; + op->solid = NULL; + op->component_alpha = GLITZ_COMPONENT_ALPHA_NONE; + + src_type = _glitz_get_surface_type (dst->feature_mask, *src); + if (src_type < 1) + return; + + mask_type = _glitz_get_surface_type (dst->feature_mask, *mask); + if (mask_type < 0) + return; + + render = &_glitz_render_map[src_type][mask_type]; + if (render->type == GLITZ_RENDER_TYPE_NA) { + if (dst->feature_mask & GLITZ_FEATURE_OFFSCREEN_DRAWING_MASK) + op->type = GLITZ_RENDER_TYPE_INTERMEDIATE; + + return; + } + + if (mask_type == GLITZ_SURFACE_TYPE_SOLID) { + op->alpha_mask.alpha = + ((glitz_programmatic_surface_t *) (op->mask))->u.solid.color.alpha; + *mask = NULL; + } + + if (src_type == GLITZ_SURFACE_TYPE_SOLID) { + op->solid = &((glitz_programmatic_surface_t *) (op->src))->u.solid.color; + + /* mask becomes source */ + if (*mask) { + *src = *mask; + *mask = NULL; + *x_src = *x_mask; + *y_src = *y_mask; + } } + + if (mask_type != GLITZ_SURFACE_TYPE_NULL && + mask_type != GLITZ_SURFACE_TYPE_SOLID) { + if (dst->feature_mask & GLITZ_FEATURE_ARB_TEXTURE_ENV_COMBINE_MASK) { + if (mask_type == GLITZ_SURFACE_TYPE_ARGBC) { + if (op->mask->format->alpha_size) + op->component_alpha = GLITZ_COMPONENT_ALPHA_ARGB; + else + op->component_alpha = GLITZ_COMPONENT_ALPHA_RGB; + } + + if (src_type != GLITZ_SURFACE_TYPE_SOLID) { + if (MULTI_TEXTURE (dst->feature_mask, *src, *mask)) + op->render = render; + else if ((dst->feature_mask & GLITZ_FEATURE_OFFSCREEN_DRAWING_MASK) && + (!SURFACE_COMPONENT_ALPHA (*mask))) + op->type = GLITZ_RENDER_TYPE_INTERMEDIATE; + + } else + op->render = render; + } + } else + op->render = render; + + /* update source and mask */ + op->src = *src; + op->mask = *mask; + + if (op->render == render) + op->type = render->type; +} + +void +glitz_render_op_set_textures (glitz_render_op_t *op, + glitz_texture_t *src, + glitz_texture_t *mask) +{ + op->src_texture = src; + op->mask_texture = mask; +} + +void +glitz_render_op_set_alpha_mask (glitz_render_op_t *op, + unsigned short red, + unsigned short green, + unsigned short blue, + unsigned short alpha) +{ + op->alpha_mask.red = red; + op->alpha_mask.green = green; + op->alpha_mask.blue = blue; + op->alpha_mask.alpha = alpha; +} + +void +glitz_render_op_get_alpha_mask (glitz_render_op_t *op, + unsigned short *red, + unsigned short *green, + unsigned short *blue, + unsigned short *alpha) +{ + if (red) *red = op->alpha_mask.red; + if (green) *green = op->alpha_mask.green; + if (blue) *blue = op->alpha_mask.blue; + if (alpha) *alpha = op->alpha_mask.alpha; +} + +void +glitz_render_enable (glitz_render_op_t *op) +{ + op->render->enable (op); + op->count++; +} + +void +glitz_render_disable (glitz_render_op_t *op) +{ + if (op->render->disable) + op->render->disable (op); } diff --git a/src/glitz_surface.c b/src/glitz_surface.c index ed95511..4104d07 100644 --- a/src/glitz_surface.c +++ b/src/glitz_surface.c @@ -43,17 +43,19 @@ glitz_surface_init (glitz_surface_t *surface, int n_formats, int width, int height, - glitz_programs_t *programs, + glitz_program_map_t *program_map, unsigned long texture_mask) { surface->backend = backend; + surface->ref_count = 1; + surface->filter = GLITZ_FILTER_NEAREST; surface->polyedge = GLITZ_POLYEDGE_SMOOTH; surface->polyedge_smooth_hint = GLITZ_POLYEDGE_SMOOTH_HINT_GOOD; surface->polyopacity = 0xffff; - - surface->programs = programs; + + surface->program_map = program_map; surface->format = format; surface->formats = formats; surface->n_formats = n_formats; @@ -221,8 +223,24 @@ glitz_surface_create_radial (glitz_point_fixed_t *center, slim_hidden_def(glitz_surface_create_radial); void +glitz_surface_reference (glitz_surface_t *surface) +{ + if (surface == NULL) + return; + + surface->ref_count++; +} + +void glitz_surface_destroy (glitz_surface_t *surface) { + if (!surface) + return; + + surface->ref_count--; + if (surface->ref_count) + return; + surface->backend->destroy (surface); } @@ -385,6 +403,21 @@ glitz_surface_set_repeat (glitz_surface_t *surface, slim_hidden_def(glitz_surface_set_repeat); void +glitz_surface_set_component_alpha (glitz_surface_t *surface, + glitz_bool_t component_alpha) +{ + if (SURFACE_PROGRAMMATIC (surface)) + return; + + if (component_alpha && surface->format->red_size) + surface->hint_mask |= GLITZ_INT_HINT_COMPONENT_ALPHA_MASK; + else + surface->hint_mask &= ~GLITZ_INT_HINT_COMPONENT_ALPHA_MASK; + +} +slim_hidden_def(glitz_surface_set_component_alpha); + +void glitz_surface_set_filter (glitz_surface_t *surface, glitz_filter_t filter) { diff --git a/src/glitz_texture.c b/src/glitz_texture.c index 8abb308..3136af5 100644 --- a/src/glitz_texture.c +++ b/src/glitz_texture.c @@ -43,7 +43,7 @@ _glitz_texture_find_best_target (unsigned int width, (!glitz_uint_is_power_of_two (width)) || (!glitz_uint_is_power_of_two (height))) { if (target_mask & GLITZ_TEXTURE_TARGET_RECTANGLE_MASK) - *target = GLITZ_GL_TEXTURE_RECTANGLE_EXT; + *target = GLITZ_GL_TEXTURE_RECTANGLE; } } @@ -179,7 +179,7 @@ void glitz_texture_bind (glitz_gl_proc_address_list_t *gl, glitz_texture_t *texture) { - gl->disable (GLITZ_GL_TEXTURE_RECTANGLE_EXT); + gl->disable (GLITZ_GL_TEXTURE_RECTANGLE); gl->disable (GLITZ_GL_TEXTURE_2D); if (!texture->target) diff --git a/src/glitzint.h b/src/glitzint.h index f8decfa..3b8fea3 100644 --- a/src/glitzint.h +++ b/src/glitzint.h @@ -88,8 +88,10 @@ typedef struct _glitz_gl_proc_address_list_t { glitz_gl_vertex_2i_t vertex_2i; glitz_gl_vertex_2d_t vertex_2d; glitz_gl_tex_env_f_t tex_env_f; + glitz_gl_tex_env_fv_t tex_env_fv; glitz_gl_tex_coord_2d_t tex_coord_2d; glitz_gl_color_4us_t color_4us; + glitz_gl_color_4d_t color_4d; glitz_gl_scissor_t scissor; glitz_gl_blend_func_t blend_func; glitz_gl_clear_t clear; @@ -138,71 +140,74 @@ typedef struct _glitz_gl_proc_address_list_t { glitz_gl_end_list_t end_list; glitz_gl_call_list_t call_list; - glitz_gl_active_texture_arb_t active_texture_arb; - glitz_gl_multi_tex_coord_2d_arb_t multi_tex_coord_2d_arb; - glitz_gl_gen_programs_arb_t gen_programs_arb; - glitz_gl_delete_programs_arb_t delete_programs_arb; - glitz_gl_program_string_arb_t program_string_arb; - glitz_gl_bind_program_arb_t bind_program_arb; - glitz_gl_program_local_param_4d_arb_t program_local_param_4d_arb; - glitz_gl_get_program_iv_arb_t get_program_iv_arb; + glitz_gl_active_texture_t active_texture; + glitz_gl_multi_tex_coord_2d_t multi_tex_coord_2d; + glitz_gl_gen_programs_t gen_programs; + glitz_gl_delete_programs_t delete_programs; + glitz_gl_program_string_t program_string; + glitz_gl_bind_program_t bind_program; + glitz_gl_program_local_param_4d_t program_local_param_4d; + glitz_gl_get_program_iv_t get_program_iv; + glitz_gl_gen_buffers_t gen_buffers; + glitz_gl_delete_buffers_t delete_buffers; + glitz_gl_bind_buffer_t bind_buffer; + glitz_gl_buffer_data_t buffer_data; + glitz_gl_map_buffer_t map_buffer; + glitz_gl_unmap_buffer_t unmap_buffer; glitz_bool_t need_lookup; } glitz_gl_proc_address_list_t; -typedef enum { - GLITZ_PROGRAMMATIC_SURFACE_SOLID_TYPE = 0, - GLITZ_PROGRAMMATIC_SURFACE_LINEAR_TYPE, - GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE -} glitz_programmatic_surface_type_t; - -typedef enum { - GLITZ_RENDER_TYPE_NOT_SUPPORTED = 0, - GLITZ_RENDER_TYPE_SOLID, - GLITZ_RENDER_TYPE_SOLID_A, - GLITZ_RENDER_TYPE_ARGB, - GLITZ_RENDER_TYPE_ARGB_A, - GLITZ_RENDER_TYPE_ARGB_ARGB, - GLITZ_RENDER_TYPE_SRC_CONVOLUTION, - GLITZ_RENDER_TYPE_SRC_CONVOLUTION_AND_SOLID_MASK, - GLITZ_RENDER_TYPE_MASK_CONVOLUTION, - GLITZ_RENDER_TYPE_MASK_CONVOLUTION_AND_SOLID_SRC, - GLITZ_RENDER_TYPE_SRC_PROGRAMMATIC, - GLITZ_RENDER_TYPE_MASK_PROGRAMMATIC -} glitz_render_type_t; - -#define GLITZ_PROGRAMMATIC_SURFACE_NUM \ - (GLITZ_PROGRAMMATIC_SURFACE_RADIAL_TYPE + 1) - -#define GLITZ_PROGRAM_2DSRC_2DMASK_OFFSET 0 -#define GLITZ_PROGRAM_RECTSRC_2DMASK_OFFSET 1 -#define GLITZ_PROGRAM_2DSRC_RECTMASK_OFFSET 2 -#define GLITZ_PROGRAM_RECTSRC_RECTMASK_OFFSET 3 -#define GLITZ_PROGRAM_NOSRC_2DMASK_OFFSET 4 -#define GLITZ_PROGRAM_NOSRC_RECTMASK_OFFSET 5 -#define GLITZ_PROGRAM_2DSRC_NOMASK_OFFSET 6 -#define GLITZ_PROGRAM_RECTSRC_NOMASK_OFFSET 7 -#define GLITZ_PROGRAM_NOSRC_NOMASK_OFFSET 8 - -#define GLITZ_PROGRAM_SRC_OPERATION_OFFSET 0 -#define GLITZ_PROGRAM_MASK_OPERATION_OFFSET 9 - -#define GLITZ_VERTEX_PROGRAM_TYPES 2 -#define GLITZ_FRAGMENT_PROGRAM_TYPES 18 - -#define GLITZ_CONVOLUTION_TYPES 2 -#define GLITZ_FRAGMENT_CONVOLUTION_PROGRAM_TYPES \ - (GLITZ_FRAGMENT_PROGRAM_TYPES * GLITZ_CONVOLUTION_TYPES * 3) -#define GLITZ_FRAGMENT_PROGRAMMATIC_PROGRAM_TYPES \ - (GLITZ_FRAGMENT_PROGRAM_TYPES * GLITZ_PROGRAMMATIC_SURFACE_NUM) - -typedef struct _glitz_programs_t { - glitz_gl_uint_t vertex_convolution[GLITZ_VERTEX_PROGRAM_TYPES]; - glitz_gl_uint_t fragment_simple[GLITZ_FRAGMENT_PROGRAM_TYPES]; - glitz_gl_uint_t - fragment_convolution[GLITZ_FRAGMENT_CONVOLUTION_PROGRAM_TYPES]; - glitz_gl_uint_t - fragment_programmatic[GLITZ_FRAGMENT_PROGRAMMATIC_PROGRAM_TYPES]; -} glitz_programs_t; +typedef int glitz_surface_type_t; + +#define GLITZ_SURFACE_TYPE_NA -1 +#define GLITZ_SURFACE_TYPE_NULL 0 +#define GLITZ_SURFACE_TYPE_ARGB 1 +#define GLITZ_SURFACE_TYPE_ARGBC 2 +#define GLITZ_SURFACE_TYPE_ARGBF 3 +#define GLITZ_SURFACE_TYPE_SOLID 4 +#define GLITZ_SURFACE_TYPE_LGRAD 5 +#define GLITZ_SURFACE_TYPE_RGRAD 6 +#define GLITZ_SURFACE_TYPES 7 + +typedef int glitz_render_type_t; + +#define GLITZ_RENDER_TYPE_NA -1 +#define GLITZ_RENDER_TYPE_INTERMEDIATE 0 +#define GLITZ_RENDER_TYPE_ARGB 1 +#define GLITZ_RENDER_TYPE_ARGB_SOLID 2 +#define GLITZ_RENDER_TYPE_ARGB_ARGB 4 +#define GLITZ_RENDER_TYPE_ARGB_ARGBC 5 +#define GLITZ_RENDER_TYPE_ARGBF 6 +#define GLITZ_RENDER_TYPE_ARGBF_SOLID 7 +#define GLITZ_RENDER_TYPE_ARGBF_ARGB 9 +#define GLITZ_RENDER_TYPE_ARGBF_ARGBC 10 +#define GLITZ_RENDER_TYPE_SOLID 11 +#define GLITZ_RENDER_TYPE_SOLID_SOLID 12 +#define GLITZ_RENDER_TYPE_SOLID_ARGB 14 +#define GLITZ_RENDER_TYPE_SOLID_ARGBC 15 +#define GLITZ_RENDER_TYPE_LGRAD 16 +#define GLITZ_RENDER_TYPE_LGRAD_SOLID 17 +#define GLITZ_RENDER_TYPE_LGRAD_ARGB 19 +#define GLITZ_RENDER_TYPE_LGRAD_ARGBC 20 +#define GLITZ_RENDER_TYPE_RGRAD 21 +#define GLITZ_RENDER_TYPE_RGRAD_SOLID 22 +#define GLITZ_RENDER_TYPE_RGRAD_ARGB 24 +#define GLITZ_RENDER_TYPE_RGRAD_ARGBC 25 +#define GLITZ_RENDER_TYPES 26 + +#define GLITZ_TEXTURE_NONE 0 +#define GLITZ_TEXTURE_2D 1 +#define GLITZ_TEXTURE_RECT 2 +#define GLITZ_TEXTURE_LAST 3 + +typedef struct _glitz_program_info_t { + glitz_gl_uint_t vertex[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST]; + glitz_gl_uint_t fragment[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST]; +} glitz_program_info_t; + +typedef struct _glitz_program_map_t { + glitz_program_info_t info[GLITZ_RENDER_TYPES]; +} glitz_program_map_t; typedef enum { GLITZ_CN_NONE, @@ -281,26 +286,37 @@ typedef struct glitz_surface_backend { (*make_current_read) (void *surface); } glitz_surface_backend_t; -#define GLITZ_INT_HINT_REPEAT_MASK (1L << 5) -#define GLITZ_INT_HINT_DIRTY_MASK (1L << 6) -#define GLITZ_INT_HINT_CLEAR_EXTERIOR_MASK (1L << 7) +#define GLITZ_INT_HINT_REPEAT_MASK (1L << 5) +#define GLITZ_INT_HINT_DIRTY_MASK (1L << 6) +#define GLITZ_INT_HINT_CLEAR_EXTERIOR_MASK (1L << 7) +#define GLITZ_INT_HINT_COMPONENT_ALPHA_MASK (1L << 8) #define SURFACE_PROGRAMMATIC(surface) \ - (surface->hint_mask & GLITZ_HINT_PROGRAMMATIC_MASK) + ((surface)->hint_mask & GLITZ_HINT_PROGRAMMATIC_MASK) #define SURFACE_SOLID(surface) \ - ((surface->hint_mask & GLITZ_HINT_PROGRAMMATIC_MASK) && \ - ((glitz_programmatic_surface_t *) surface)->type == \ - GLITZ_PROGRAMMATIC_SURFACE_SOLID_TYPE) + (((glitz_programmatic_surface_t *) (surface))->type == \ + GLITZ_PROGRAMMATIC_SURFACE_TYPE_SOLID) + +#define SURFACE_LINEAR_GRADIENT(surface) \ + (((glitz_programmatic_surface_t *) (surface))->type == \ + GLITZ_PROGRAMMATIC_SURFACE_TYPE_LINEAR) + +#define SURFACE_RADIAL_GRADIENT(surface) \ + (((glitz_programmatic_surface_t *) (surface))->type == \ + GLITZ_PROGRAMMATIC_SURFACE_TYPE_RADIAL) #define SURFACE_REPEAT(surface) \ - (surface->hint_mask & GLITZ_INT_HINT_REPEAT_MASK) + ((surface)->hint_mask & GLITZ_INT_HINT_REPEAT_MASK) #define SURFACE_DIRTY(surface) \ - (surface->hint_mask & GLITZ_INT_HINT_DIRTY_MASK) + ((surface)->hint_mask & GLITZ_INT_HINT_DIRTY_MASK) #define SURFACE_CLEAR_EXTERIOR(surface) \ - (surface->hint_mask & GLITZ_INT_HINT_CLEAR_EXTERIOR_MASK) + ((surface)->hint_mask & GLITZ_INT_HINT_CLEAR_EXTERIOR_MASK) + +#define SURFACE_COMPONENT_ALPHA(surface) \ + ((surface)->hint_mask & GLITZ_INT_HINT_COMPONENT_ALPHA_MASK) typedef struct _glitz_sample_offset { double x; @@ -319,6 +335,7 @@ typedef struct _glitz_multi_sample_info { struct _glitz_surface { const glitz_surface_backend_t *backend; + int ref_count; glitz_format_t *format; glitz_format_t *formats; int n_formats; @@ -333,7 +350,7 @@ struct _glitz_surface { int width, height; glitz_bounding_box_t dirty_box; glitz_gl_proc_address_list_t *gl; - glitz_programs_t *programs; + glitz_program_map_t *program_map; glitz_matrix_t *convolution; unsigned int stencil_masks[GLITZ_N_STENCIL_MASKS]; unsigned int *stencil_mask; @@ -344,21 +361,11 @@ struct _glitz_surface { glitz_multi_sample_info_t *multi_sample; }; -#define GLITZ_COLOR_RANGE_UPDATE_TEXTURE_MASK (1L << 0) -#define GLITZ_COLOR_RANGE_UPDATE_FILTER_MASK (1L << 1) -#define GLITZ_COLOR_RANGE_UPDATE_EXTEND_MASK (1L << 2) -#define GLITZ_COLOR_RANGE_UPDATE_ALL_MASK ((1L << 3) - 1) - -struct _glitz_color_range { - unsigned char *data; - unsigned int size; - glitz_gl_uint_t texture; - glitz_filter_t filter; - glitz_extend_t extend; - unsigned long update_mask; - unsigned int ref_count; - glitz_gl_delete_textures_t delete_textures; -}; +typedef enum { + GLITZ_PROGRAMMATIC_SURFACE_TYPE_SOLID = 0, + GLITZ_PROGRAMMATIC_SURFACE_TYPE_LINEAR, + GLITZ_PROGRAMMATIC_SURFACE_TYPE_RADIAL +} glitz_programmatic_surface_type_t; typedef struct _glitz_programmatic_surface_t { glitz_surface_t base; @@ -384,6 +391,39 @@ typedef struct _glitz_programmatic_surface_t { } u; } glitz_programmatic_surface_t; + +typedef struct _glitz_render_op_t glitz_render_op_t; + +typedef void (*glitz_render_function_t) (glitz_render_op_t *); + +typedef struct _glitz_render_t { + glitz_render_type_t type; + glitz_render_function_t enable; + glitz_render_function_t disable; + int texture_units; +} glitz_render_t; + +typedef enum { + GLITZ_COMPONENT_ALPHA_NONE = 0, + GLITZ_COMPONENT_ALPHA_RGB, + GLITZ_COMPONENT_ALPHA_ARGB +} glitz_component_alpha_type_t; + +struct _glitz_render_op_t { + glitz_render_type_t type; + glitz_render_t *render; + glitz_gl_proc_address_list_t *gl; + glitz_surface_t *src; + glitz_surface_t *mask; + glitz_surface_t *dst; + glitz_texture_t *src_texture; + glitz_texture_t *mask_texture; + glitz_color_t *solid; + glitz_color_t alpha_mask; + glitz_component_alpha_type_t component_alpha; + int count; +}; + typedef struct _glitz_extension_map { char *name; int mask; @@ -514,7 +554,7 @@ glitz_surface_init (glitz_surface_t *surface, int n_formats, int width, int height, - glitz_programs_t *programs, + glitz_program_map_t *program_map, unsigned long texture_mask); void @@ -527,6 +567,9 @@ extern glitz_texture_t *__internal_linkage glitz_surface_get_texture (glitz_surface_t *surface); extern void __internal_linkage +glitz_surface_reference (glitz_surface_t *surface); + +extern void __internal_linkage glitz_surface_destory (glitz_surface_t *surface); glitz_bool_t @@ -600,19 +643,17 @@ glitz_format_get_best_texture_format (glitz_format_t *formats, glitz_format_t *format); void -glitz_programs_fini (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs); +glitz_program_map_init (glitz_program_map_t *map); + +void +glitz_program_map_fini (glitz_gl_proc_address_list_t *gl, + glitz_program_map_t *map); -extern void __internal_linkage -glitz_programmatic_surface_setup (glitz_surface_t *abstract_surface, - int width, - int height); +extern glitz_gl_uint_t __internal_linkage +glitz_get_vertex_program (glitz_render_op_t *op); -extern void __internal_linkage -glitz_programmatic_surface_bind (glitz_gl_proc_address_list_t *proc_address, - glitz_programmatic_surface_t *surface, - unsigned long feature_mask, - unsigned short opacity); +extern glitz_gl_uint_t __internal_linkage +glitz_get_fragment_program (glitz_render_op_t *op); extern glitz_surface_t *__internal_linkage glitz_programmatic_surface_create_solid (glitz_color_t *color); @@ -667,29 +708,10 @@ glitz_int_fill_triangles (glitz_operator_t op, int n_points); extern void __internal_linkage -glitz_program_enable_argb_argb (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture); +glitz_program_enable_convolution (glitz_render_op_t *op); extern void __internal_linkage -glitz_program_enable_convolution (glitz_gl_proc_address_list_t *gl, - glitz_programs_t *programs, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - int offset, - int solid_offset, - unsigned short opacity); - -extern void __internal_linkage -glitz_program_enable_programmatic (glitz_surface_t *dst, - glitz_programmatic_surface_t *surface, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - int offset, - unsigned short opacity); +glitz_program_enable_programmatic (glitz_render_op_t *op); extern void __internal_linkage glitz_stencil_rectangles (glitz_surface_t *dst, @@ -710,23 +732,48 @@ glitz_stencil_triangles (glitz_surface_t *dst, const glitz_point_fixed_t *points, int n_points); -extern glitz_render_type_t __internal_linkage -glitz_render_type (glitz_surface_t *dst, - glitz_surface_t *src, - glitz_surface_t *mask); +extern void __internal_linkage +glitz_render_op_init (glitz_render_op_t *op, + glitz_surface_t **src, + glitz_surface_t **mask, + glitz_surface_t *dst, + int *x_src, + int *y_src, + int *x_mask, + int *y_mask); + +extern void __internal_linkage +glitz_render_op_set_textures (glitz_render_op_t *op, + glitz_texture_t *src, + glitz_texture_t *mask); + +extern void __internal_linkage +glitz_render_op_set_alpha_mask (glitz_render_op_t *op, + unsigned short red, + unsigned short green, + unsigned short blue, + unsigned short alpha); + +extern void __internal_linkage +glitz_render_op_get_alpha_mask (glitz_render_op_t *op, + unsigned short *red, + unsigned short *green, + unsigned short *blue, + unsigned short *alpha); extern void __internal_linkage -glitz_render_enable (glitz_render_type_t type, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst, - glitz_texture_t *src_texture, - glitz_texture_t *mask_texture, - unsigned short opacity); +glitz_render_enable (glitz_render_op_t *op); extern void __internal_linkage -glitz_render_disable (glitz_render_type_t type, - glitz_surface_t *dst); +glitz_render_disable (glitz_render_op_t *op); + +extern char *__internal_linkage +glitz_pixel_buffer_bind (glitz_pixel_buffer_t *buffer, + glitz_gl_enum_t target); + +extern void __internal_linkage +glitz_pixel_buffer_unbind (glitz_pixel_buffer_t *buffer); + #define MAXSHORT SHRT_MAX #define MINSHORT SHRT_MIN @@ -793,8 +840,9 @@ typedef glitz_fixed_16_16 glitz_fixed; #define FIXED_TO_DOUBLE(f) (((double) (f)) / 65536) #define DOUBLE_TO_FIXED(f) ((int) ((f) * 65536)) -#define SHORT_MODULATE(s1, s2) \ - ((unsigned short) (((unsigned int) s1 * s2) / 0xffff)) +#define SHORT_MULT(s1, s2) \ + ((s1 == 0xffff)? s2: ((s2 == 0xffff)? s1: \ + ((unsigned short) (((unsigned int) s1 * s2) / 0xffff)))) typedef void (*glitz_function_pointer_t) (void); @@ -808,6 +856,7 @@ slim_hidden_proto(glitz_surface_create_radial) slim_hidden_proto(glitz_surface_set_transform) slim_hidden_proto(glitz_surface_set_convolution) slim_hidden_proto(glitz_surface_set_repeat) +slim_hidden_proto(glitz_surface_set_component_alpha) slim_hidden_proto(glitz_surface_set_filter) slim_hidden_proto(glitz_surface_set_polyedge) slim_hidden_proto(glitz_surface_set_polyopacity) |