/* * 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" #define STORE_16(dst, size, src) \ dst = ((size) ? \ ((((((1L << (size)) - 1L) * (src)) / 0xffff) * 0xffff) / \ ((1L << (size)) - 1L)) : \ dst) static glitz_buffer_t * _glitz_minimum_buffer (glitz_surface_t *surface, const glitz_rectangle_t *rects, int n_rects, unsigned int pixel) { glitz_buffer_t *buffer; int i, size = 0; unsigned int *data; while (n_rects--) { i = rects->width * rects->height; if (i > size) size = i; rects++; } buffer = glitz_pixel_buffer_create (surface->drawable, NULL, size * sizeof (unsigned int), GLITZ_BUFFER_HINT_STATIC_DRAW); if (!buffer) return NULL; data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); while (size--) *data++ = pixel; glitz_buffer_unmap (buffer); return buffer; } void glitz_set_rectangles (glitz_surface_t *dst, const glitz_color_t *color, const glitz_rectangle_t *rects, int n_rects) { GLITZ_GL_SURFACE (dst); if (n_rects < 1) return; if (SURFACE_SOLID (dst)) { glitz_color_t old = dst->solid; glitz_box_t *clip = dst->clip; int n_clip = dst->n_clip; for (; n_clip; clip++, n_clip--) { if (clip->x1 > 0 || clip->y1 > 0 || clip->x2 < 1 || clip->y2 < 1) continue; for (; n_rects; rects++, n_rects--) { if (rects->x > 0 || rects->y > 0 || (rects->x + rects->width) < 1 || (rects->y + rects->height) < 1) continue; STORE_16 (dst->solid.red, dst->format->color.red_size, color->red); STORE_16 (dst->solid.green, dst->format->color.green_size, color->green); STORE_16 (dst->solid.blue, dst->format->color.blue_size, color->blue); STORE_16 (dst->solid.alpha, dst->format->color.alpha_size, color->alpha); if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK) { dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; glitz_surface_damage (dst, &dst->box, GLITZ_DAMAGE_TEXTURE_MASK | GLITZ_DAMAGE_DRAWABLE_MASK); } else { if (dst->solid.red != old.red || dst->solid.green != old.green || dst->solid.blue != old.blue || dst->solid.alpha != old.alpha) glitz_surface_damage (dst, &dst->box, GLITZ_DAMAGE_TEXTURE_MASK | GLITZ_DAMAGE_DRAWABLE_MASK); } break; } break; } } else { static glitz_pixel_format_t pf = { { 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }, 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }; glitz_buffer_t *buffer = NULL; glitz_box_t box; glitz_bool_t drawable; drawable = glitz_surface_push_current (dst, GLITZ_DRAWABLE_CURRENT); if (drawable) { gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff, color->green / (glitz_gl_clampf_t) 0xffff, color->blue / (glitz_gl_clampf_t) 0xffff, color->alpha / (glitz_gl_clampf_t) 0xffff); } else { unsigned int pixel = ((((unsigned int) color->alpha * 0xff) / 0xffff) << 24) | ((((unsigned int) color->red * 0xff) / 0xffff) << 16) | ((((unsigned int) color->green * 0xff) / 0xffff) << 8) | ((((unsigned int) color->blue * 0xff) / 0xffff)); buffer = _glitz_minimum_buffer (dst, rects, n_rects, pixel); if (!buffer) { glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); return; } } while (n_rects--) { glitz_box_t *clip = dst->clip; int n_clip = dst->n_clip; while (n_clip--) { box.x1 = clip->x1 + dst->x_clip; box.y1 = clip->y1 + dst->y_clip; box.x2 = clip->x2 + dst->x_clip; box.y2 = clip->y2 + dst->y_clip; if (dst->box.x1 > box.x1) box.x1 = dst->box.x1; if (dst->box.y1 > box.y1) box.y1 = dst->box.y1; if (dst->box.x2 < box.x2) box.x2 = dst->box.x2; if (dst->box.y2 < box.y2) box.y2 = dst->box.y2; if (rects->x > box.x1) box.x1 = rects->x; if (rects->y > box.y1) box.y1 = rects->y; if (rects->x + rects->width < box.x2) box.x2 = rects->x + rects->width; if (rects->y + rects->height < box.y2) box.y2 = rects->y + rects->height; if (box.x1 < box.x2 && box.y1 < box.y2) { if (drawable) { gl->scissor (box.x1, dst->attached->height - dst->y - box.y2, box.x2 - box.x1, box.y2 - box.y1); gl->clear (GLITZ_GL_COLOR_BUFFER_BIT); glitz_surface_damage (dst, &box, GLITZ_DAMAGE_TEXTURE_MASK | GLITZ_DAMAGE_SOLID_MASK); } else { glitz_set_pixels (dst, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1, &pf, buffer); } } clip++; } rects++; } if (buffer) glitz_buffer_destroy (buffer); glitz_surface_pop_current (dst); } } slim_hidden_def(glitz_set_rectangles); void glitz_set_rectangle (glitz_surface_t *dst, const glitz_color_t *color, int x, int y, unsigned int width, unsigned int height) { glitz_rectangle_t rect; rect.x = x; rect.y = y; rect.width = width; rect.height = height; glitz_set_rectangles (dst, color, &rect, 1); } slim_hidden_def(glitz_set_rectangle);