/* * 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 name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * 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 */ #ifdef HAVE_CONFIG_H # include "../config.h" #endif #include "glitzint.h" static void _glitz_combine_argb_argb (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_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 _glitz_combine_argb_argbc (glitz_composite_op_t *op) { if (op->count == 0) { glitz_set_operator (op->gl, op->render_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 */ 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); 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); 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_4f (1.0f, 0.5f, 0.5f, 0.5f); } else if (op->alpha_mask.green) { op->gl->color_4f (0.5f, 1.0f, 0.5f, 0.5f); } else if (op->alpha_mask.blue) { op->gl->color_4f (0.5f, 0.5f, 1.0f, 0.5f); } 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); } } static void _glitz_combine_argb_argbf (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_op); glitz_filter_enable (op->mask, op); op->gl->color_4us (op->alpha_mask.red, op->alpha_mask.green, op->alpha_mask.blue, op->alpha_mask.alpha); } static void _glitz_combine_argb_solid (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_op); 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); } } static void _glitz_combine_argb_solidc (glitz_composite_op_t *op) { unsigned short alpha; if (op->count == 0) glitz_set_operator (op->gl, op->render_op); if (op->alpha_mask.red) alpha = op->alpha_mask.red; else if (op->alpha_mask.green) alpha = op->alpha_mask.green; else if (op->alpha_mask.blue) alpha = op->alpha_mask.blue; else alpha = op->alpha_mask.alpha; if (alpha != 0xffff) { op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, GLITZ_GL_MODULATE); op->gl->color_4us (alpha, alpha, alpha, 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); } } static void _glitz_combine_argbf_solid (glitz_composite_op_t *op) { if (op->count == 0) { glitz_set_operator (op->gl, op->render_op); glitz_filter_enable (op->src, op); } op->gl->color_4us (0x0, 0x0, 0x0, op->alpha_mask.alpha); } static void _glitz_combine_argbf_argbc (glitz_composite_op_t *op) { if (op->count == 0) { glitz_set_operator (op->gl, op->render_op); glitz_filter_enable (op->src, op); } op->gl->color_4us (op->alpha_mask.red, op->alpha_mask.green, op->alpha_mask.blue, op->alpha_mask.alpha); } static void _glitz_combine_argbf_solidc (glitz_composite_op_t *op) { unsigned short alpha; if (op->count == 0) { glitz_set_operator (op->gl, op->render_op); glitz_filter_enable (op->src, op); } if (op->alpha_mask.red) alpha = op->alpha_mask.red; else if (op->alpha_mask.green) alpha = op->alpha_mask.green; else if (op->alpha_mask.blue) alpha = op->alpha_mask.blue; else alpha = op->alpha_mask.alpha; op->gl->color_4us (0x0, 0x0, 0x0, alpha); } static void _glitz_combine_solid_solid (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_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_combine_solid_argb (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_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 (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)); } /* This only works with the OVER operator. */ static void _glitz_combine_solid_argbc (glitz_composite_op_t *op) { glitz_color_t solid; solid.red = SHORT_MULT (op->solid->red, op->alpha_mask.alpha); solid.green = SHORT_MULT (op->solid->green, op->alpha_mask.alpha); solid.blue = SHORT_MULT (op->solid->blue, op->alpha_mask.alpha); solid.alpha = SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha); op->gl->enable (GLITZ_GL_BLEND); op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); if (solid.alpha > 0) op->gl->blend_color ((glitz_gl_clampf_t) solid.red / solid.alpha, (glitz_gl_clampf_t) solid.green / solid.alpha, (glitz_gl_clampf_t) solid.blue / solid.alpha, 1.0f); else op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, GLITZ_GL_MODULATE); op->gl->color_4us (solid.alpha, solid.alpha, solid.alpha, solid.alpha); } static void _glitz_combine_solid_argbf (glitz_composite_op_t *op) { glitz_set_operator (op->gl, op->render_op); glitz_filter_enable (op->mask, 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)); } /* This only works with the OVER operator. */ static void _glitz_combine_solid_solidc (glitz_composite_op_t *op) { op->gl->enable (GLITZ_GL_BLEND); op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); if (op->solid->alpha > 0) op->gl->blend_color ((glitz_gl_clampf_t) op->solid->red / op->solid->alpha, (glitz_gl_clampf_t) op->solid->green / op->solid->alpha, (glitz_gl_clampf_t) op->solid->blue / op->solid->alpha, 1.0f); else op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); op->gl->color_4us (SHORT_MULT (op->alpha_mask.red, op->solid->alpha), SHORT_MULT (op->alpha_mask.green, op->solid->alpha), SHORT_MULT (op->alpha_mask.blue, op->solid->alpha), SHORT_MULT (op->alpha_mask.alpha, op->solid->alpha)); } static glitz_combine_t _glitz_combine_map[GLITZ_SURFACE_TYPES][GLITZ_SURFACE_TYPES] = { { { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 } }, { { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } }, { { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } }, { { GLITZ_COMBINE_TYPE_ARGBF, _glitz_combine_argbf_solid, 1, 1 }, { GLITZ_COMBINE_TYPE_ARGBF_ARGB, _glitz_combine_argbf_solid, 2, 1 }, { GLITZ_COMBINE_TYPE_ARGBF_ARGBC, _glitz_combine_argbf_argbc, 2, 1 }, { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, { GLITZ_COMBINE_TYPE_ARGBF_SOLID, _glitz_combine_argbf_solid, 1, 1 }, { GLITZ_COMBINE_TYPE_ARGBF_SOLIDC, _glitz_combine_argbf_solidc, 1, 1 } }, { { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } }, { { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } } }; #define SURFACE_WRAP(surface, feature_mask) \ (SURFACE_REPEAT (surface)? \ (TEXTURE_REPEATABLE (&(surface)->texture) && \ ( \ (!SURFACE_MIRRORED (surface)) || \ ((feature_mask) & GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK) \ ) \ ) \ : \ ((SURFACE_PAD (surface))? \ (TEXTURE_PADABLE (&(surface)->texture)) \ : \ (TEXTURE_CLAMPABLE (&(surface)->texture) && \ ((!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \ ((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \ ) \ ) \ ) \ ) static glitz_surface_type_t _glitz_get_surface_type (glitz_surface_t *surface, unsigned long feature_mask) { if (surface == NULL) return GLITZ_SURFACE_TYPE_NULL; if (SURFACE_SOLID (surface) && (SURFACE_REPEAT (surface) || SURFACE_PAD (surface))) { if (SURFACE_COMPONENT_ALPHA (surface)) return GLITZ_SURFACE_TYPE_SOLIDC; else return GLITZ_SURFACE_TYPE_SOLID; } if (SURFACE_WRAP (surface, feature_mask)) { if (SURFACE_FRAGMENT_FILTER (surface)) { if (SURFACE_COMPONENT_ALPHA (surface)) return GLITZ_SURFACE_TYPE_NA; if (feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) return GLITZ_SURFACE_TYPE_ARGBF; } else if (SURFACE_COMPONENT_ALPHA (surface)) { return GLITZ_SURFACE_TYPE_ARGBC; } else return GLITZ_SURFACE_TYPE_ARGB; } return GLITZ_SURFACE_TYPE_NA; } static glitz_color_t _default_alpha_mask = { 0xffff, 0xffff, 0xffff, 0xffff }; void glitz_composite_op_init (glitz_composite_op_t *op, glitz_operator_t render_op, glitz_surface_t *src, glitz_surface_t *mask, glitz_surface_t *dst) { glitz_surface_type_t src_type; glitz_surface_type_t mask_type; glitz_combine_t *combine; unsigned long feature_mask; op->render_op = render_op; op->type = GLITZ_COMBINE_TYPE_NA; op->combine = NULL; op->alpha_mask = _default_alpha_mask; op->src = src; op->mask = mask; op->dst = dst; op->count = 0; op->solid = NULL; op->per_component = 0; op->fp = 0; if (dst->attached) { op->gl = dst->attached->backend->gl; feature_mask = dst->attached->backend->feature_mask; } else { op->gl = dst->drawable->backend->gl; feature_mask = dst->drawable->backend->feature_mask; } src_type = _glitz_get_surface_type (src, feature_mask); if (src_type < 1) return; mask_type = _glitz_get_surface_type (mask, feature_mask); if (mask_type < 0) return; if (src_type == GLITZ_SURFACE_TYPE_SOLIDC) src_type = GLITZ_SURFACE_TYPE_SOLID; /* We can't do solid IN argbc OP dest, unless OP is OVER. But we can do argb IN argbc OP dest, so lets just not use the source as a solid color if this is the case. I need to figure out a better way to handle special cases like this. */ if (src_type == GLITZ_SURFACE_TYPE_SOLID && (mask_type == GLITZ_SURFACE_TYPE_SOLIDC || mask_type == GLITZ_SURFACE_TYPE_ARGBC) && render_op != GLITZ_OPERATOR_OVER) src_type = GLITZ_SURFACE_TYPE_ARGB; combine = &_glitz_combine_map[src_type][mask_type]; if (!combine->type) return; if (dst->geometry.type == GLITZ_GEOMETRY_TYPE_BITMAP) { /* We can't do anything but solid colors with bitmaps yet. */ if (src_type != GLITZ_SURFACE_TYPE_SOLID || (mask_type != GLITZ_SURFACE_TYPE_NULL && mask_type != GLITZ_SURFACE_TYPE_SOLID)) return; } if (src_type == GLITZ_SURFACE_TYPE_SOLID) { if (SURFACE_SOLID_DAMAGE (src)) { glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); glitz_surface_sync_solid (src); glitz_surface_pop_current (dst); } op->solid = &src->solid; op->src = NULL; } if (mask_type == GLITZ_SURFACE_TYPE_SOLID) { if (SURFACE_SOLID_DAMAGE (mask)) { glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); glitz_surface_sync_solid (mask); glitz_surface_pop_current (dst); } op->alpha_mask = mask->solid; op->mask = NULL; op->combine = combine; } else if (mask_type == GLITZ_SURFACE_TYPE_SOLIDC) { if (SURFACE_SOLID_DAMAGE (mask)) { glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); glitz_surface_sync_solid (mask); glitz_surface_pop_current (dst); } op->alpha_mask = mask->solid; op->mask = NULL; if (op->src) { op->per_component = 4; op->combine = combine; } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) op->combine = combine; } else if (mask_type != GLITZ_SURFACE_TYPE_NULL) { if (mask_type == GLITZ_SURFACE_TYPE_ARGBC) { if (op->src) { /* we can't do component alpha with alpha only surfaces */ if (op->src->format->color.red_size) { op->per_component = 4; if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) op->combine = combine; } } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) op->combine = combine; } else if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) op->combine = combine; } else op->combine = combine; if (!(feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK)) { if (op->src && op->mask) op->combine = NULL; } if (op->per_component && (!(feature_mask & GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK))) op->combine = NULL; if (op->combine == combine) { op->type = combine->type; if (combine->source_shader) { if (combine->source_shader == 1) op->fp = glitz_filter_get_fragment_program (src, op); else op->fp = glitz_filter_get_fragment_program (mask, op); if (op->fp == 0) op->type = GLITZ_COMBINE_TYPE_NA; } } } void glitz_composite_enable (glitz_composite_op_t *op) { op->combine->enable (op); op->count++; } void glitz_composite_disable (glitz_composite_op_t *op) { if (op->fp) { op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); op->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM); } }