summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/glitz_pixel.c451
1 files changed, 258 insertions, 193 deletions
diff --git a/src/glitz_pixel.c b/src/glitz_pixel.c
index 0c04572..946bfdd 100644
--- a/src/glitz_pixel.c
+++ b/src/glitz_pixel.c
@@ -590,214 +590,279 @@ glitz_set_pixels (glitz_surface_t *dst,
glitz_pixel_format_t *format,
glitz_buffer_t *buffer)
{
- glitz_texture_t *texture;
- char *pixels, *data = NULL;
- glitz_gl_pixel_format_t *gl_format = NULL;
- unsigned long transform = 0;
- int xoffset, bytes_per_line, bpp;
- glitz_box_t box;
-
- GLITZ_GL_SURFACE (dst);
-
- if (x_dst < 0 || x_dst > (dst->box.x2 - width) ||
- y_dst < 0 || y_dst > (dst->box.y2 - height)) {
- glitz_surface_status_add (dst, GLITZ_STATUS_BAD_COORDINATE_MASK);
- return;
- }
-
- box.x1 = x_dst;
- box.y1 = y_dst;
- box.x2 = box.x1 + width;
- box.y2 = box.y1 + height;
-
- if (SURFACE_SOLID (dst)) {
- glitz_image_t src_image, dst_image;
- glitz_color_t old = dst->solid;
-
- dst_image.width = dst_image.height = 1;
-
- src_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY);
- src_image.data += format->skip_lines * format->bytes_per_line;
- src_image.format = format;
- src_image.width = src_image.height = 1;
-
- if (format->masks.alpha_mask && dst->format->color.alpha_size) {
- dst_image.data = (void *) &dst->solid.alpha;
- dst_image.format = &_solid_format[SOLID_ALPHA];
-
- _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
- &src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
- } else
- dst->solid.alpha = 0xffff;
-
- if (format->masks.red_mask && dst->format->color.red_size) {
- dst_image.data = (void *) &dst->solid.red;
- dst_image.format = &_solid_format[SOLID_RED];
-
- _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
- &src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
- } else
- dst->solid.red = 0;
-
- if (format->masks.green_mask && dst->format->color.green_size) {
- dst_image.data = (void *) &dst->solid.green;
- dst_image.format = &_solid_format[SOLID_GREEN];
-
- _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
- &src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
- } else
- dst->solid.green = 0;
-
- if (format->masks.blue_mask && dst->format->color.blue_size) {
- dst_image.data = (void *) &dst->solid.blue;
- dst_image.format = &_solid_format[SOLID_BLUE];
-
- _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
- &src_image, &dst_image,
- format->xoffset, 0, 0, 0, 1, 1);
- } else
- dst->solid.blue = 0;
-
- glitz_buffer_unmap (buffer);
+ glitz_box_t *clip = dst->clip;
+ int n_clip = dst->n_clip;
+ glitz_texture_t *texture;
+ char *pixels = NULL;
+ char *ptr = NULL;
+ char *data = NULL;
+ glitz_gl_pixel_format_t *gl_format = NULL;
+ unsigned long transform = 0;
+ glitz_bool_t bound = 0;
+ int bytes_per_line = 0, bytes_per_pixel = 0;
+ glitz_image_t src_image, dst_image;
+ glitz_box_t box;
+
+ GLITZ_GL_SURFACE (dst);
+
+ if (x_dst < 0 || x_dst > (dst->box.x2 - width) ||
+ y_dst < 0 || y_dst > (dst->box.y2 - height)) {
+ glitz_surface_status_add (dst, GLITZ_STATUS_BAD_COORDINATE_MASK);
+ return;
+ }
- if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK)
+ if (SURFACE_SOLID (dst))
{
- dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK;
- glitz_surface_damage (dst, &box,
- GLITZ_DAMAGE_TEXTURE_MASK |
- GLITZ_DAMAGE_DRAWABLE_MASK);
+ glitz_color_t old = dst->solid;
+
+ 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 (x_dst > box.x1)
+ box.x1 = x_dst;
+ if (y_dst > box.y1)
+ box.y1 = y_dst;
+ if (x_dst + width < box.x2)
+ box.x2 = x_dst + width;
+ if (y_dst + height < box.y2)
+ box.y2 = y_dst + height;
+
+ if (box.x1 < box.x2 && box.y1 < box.y2)
+ {
+ dst_image.width = dst_image.height = 1;
+
+ src_image.data =
+ glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY);
+ src_image.data += format->skip_lines * format->bytes_per_line;
+ src_image.format = format;
+ src_image.width = src_image.height = 1;
+
+ if (format->masks.alpha_mask && dst->format->color.alpha_size)
+ {
+ dst_image.data = (void *) &dst->solid.alpha;
+ dst_image.format = &_solid_format[SOLID_ALPHA];
+
+ _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
+ &src_image, &dst_image,
+ format->xoffset, 0, 0, 0, 1, 1);
+ } else
+ dst->solid.alpha = 0xffff;
+
+ if (format->masks.red_mask && dst->format->color.red_size)
+ {
+ dst_image.data = (void *) &dst->solid.red;
+ dst_image.format = &_solid_format[SOLID_RED];
+
+ _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
+ &src_image, &dst_image,
+ format->xoffset, 0, 0, 0, 1, 1);
+ } else
+ dst->solid.red = 0;
+
+ if (format->masks.green_mask && dst->format->color.green_size)
+ {
+ dst_image.data = (void *) &dst->solid.green;
+ dst_image.format = &_solid_format[SOLID_GREEN];
+
+ _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
+ &src_image, &dst_image,
+ format->xoffset, 0, 0, 0, 1, 1);
+ } else
+ dst->solid.green = 0;
+
+ if (format->masks.blue_mask && dst->format->color.blue_size)
+ {
+ dst_image.data = (void *) &dst->solid.blue;
+ dst_image.format = &_solid_format[SOLID_BLUE];
+
+ _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
+ &src_image, &dst_image,
+ format->xoffset, 0, 0, 0, 1, 1);
+ } else
+ dst->solid.blue = 0;
+
+ glitz_buffer_unmap (buffer);
+
+ if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK)
+ {
+ dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK;
+ glitz_surface_damage (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, &box,
+ GLITZ_DAMAGE_TEXTURE_MASK |
+ GLITZ_DAMAGE_DRAWABLE_MASK);
+ }
+ break;
+ }
+ }
+ return;
}
- else
+
+ /* find direct format */
+ gl_format =
+ _glitz_find_gl_pixel_format (format,
+ &dst->format->color,
+ dst->drawable->backend->feature_mask);
+ if (gl_format == NULL)
{
- 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, &box,
- GLITZ_DAMAGE_TEXTURE_MASK |
- GLITZ_DAMAGE_DRAWABLE_MASK);
+ unsigned long feature_mask;
+
+ feature_mask = dst->drawable->backend->feature_mask;
+ transform |= GLITZ_TRANSFORM_PIXELS_MASK;
+ gl_format =
+ _glitz_find_best_gl_pixel_format (format,
+ &dst->format->color,
+ feature_mask);
}
- return;
- }
-
- /* find direct format */
- gl_format =
- _glitz_find_gl_pixel_format (format,
- &dst->format->color,
- dst->drawable->backend->feature_mask);
- if (gl_format == NULL) {
- transform |= GLITZ_TRANSFORM_PIXELS_MASK;
- gl_format =
- _glitz_find_best_gl_pixel_format (format,
- &dst->format->color,
- dst->drawable->backend->feature_mask);
- }
-
- /* should not happen */
- if (gl_format == NULL)
- return;
- glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT);
+ glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT);
- texture = glitz_surface_get_texture (dst, 1);
- if (!texture) {
- glitz_surface_pop_current (dst);
- return;
- }
-
- if (height > 1) {
- if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
- transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK;
- }
-
- glitz_texture_bind (gl, texture);
-
- if (transform) {
- glitz_image_t src_image, dst_image;
- int stride;
-
- stride = (((width * gl_format->pixel.masks.bpp) / 8) + 3) & -4;
-
- data = malloc (stride * height);
- if (!data) {
- glitz_texture_unbind (gl, texture);
- glitz_surface_pop_current (dst);
- glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK);
- return;
+ texture = glitz_surface_get_texture (dst, 1);
+ if (!texture) {
+ glitz_surface_pop_current (dst);
+ return;
}
- dst_image.data = data;
- dst_image.format = &gl_format->pixel;
- dst_image.width = width;
- dst_image.height = height;
-
- src_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY);
- src_image.data += format->skip_lines * format->bytes_per_line;
- src_image.format = format;
- src_image.width = width;
- src_image.height = height;
-
- _glitz_pixel_transform (transform,
- &src_image,
- &dst_image,
- format->xoffset, 0,
- 0, 0,
- width, height);
-
- glitz_buffer_unmap (buffer);
-
- pixels = data;
- xoffset = 0;
- bytes_per_line = stride;
- bpp = dst_image.format->masks.bpp;
- } else {
- xoffset = format->xoffset;
- bytes_per_line = format->bytes_per_line;
- bpp = format->masks.bpp;
- pixels = glitz_buffer_bind (buffer, GLITZ_GL_PIXEL_UNPACK_BUFFER);
- pixels += format->skip_lines * bytes_per_line;
- }
+ if (height > 1) {
+ if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
+ transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK;
+ }
- if (bytes_per_line) {
- if ((bytes_per_line % 4) == 0)
- gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
- else if ((bytes_per_line % 2) == 0)
- gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2);
- else
- gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
+ glitz_texture_bind (gl, texture);
- gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, bytes_per_line / (bpp / 8));
- } else {
- gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
- gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
- }
+ gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0);
- gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0);
- gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, xoffset);
+ 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 (x_dst > box.x1)
+ box.x1 = x_dst;
+ if (y_dst > box.y1)
+ box.y1 = y_dst;
+ if (x_dst + width < box.x2)
+ box.x2 = x_dst + width;
+ if (y_dst + height < box.y2)
+ box.y2 = y_dst + height;
+
+ if (box.x1 < box.x2 && box.y1 < box.y2)
+ {
+ if (transform)
+ {
+ if (!data)
+ {
+ int stride, bpp;
+
+ bpp = gl_format->pixel.masks.bpp;
+ stride = (((width * bpp) / 8) + 3) & -4;
+ data = malloc (stride * height);
+ if (!data)
+ {
+ glitz_surface_status_add (dst,
+ GLITZ_STATUS_NO_MEMORY_MASK);
+ goto BAIL;
+ }
+
+ dst_image.data = pixels = data;
+ dst_image.format = &gl_format->pixel;
+
+ src_image.data =
+ glitz_buffer_map (buffer,
+ GLITZ_BUFFER_ACCESS_READ_ONLY);
+ src_image.data +=
+ format->skip_lines * format->bytes_per_line;
+ src_image.format = format;
+
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
+ }
+
+ dst_image.width = box.x2 - box.x1;
+ dst_image.height = box.y2 - box.y1;
+
+ src_image.width = box.x2 - box.x1;
+ src_image.height = box.y2 - box.y1;
+
+ _glitz_pixel_transform (transform,
+ &src_image,
+ &dst_image,
+ format->xoffset + box.x1 - x_dst,
+ box.y1 - y_dst,
+ 0, 0,
+ box.x2 - box.x1, box.y2 - box.y1);
+ }
+ else
+ {
+ if (!bound)
+ {
+ ptr = glitz_buffer_bind (buffer,
+ GLITZ_GL_PIXEL_UNPACK_BUFFER);
+
+ bytes_per_line = format->bytes_per_line;
+ bytes_per_pixel = format->masks.bpp / 8;
+ if (bytes_per_line)
+ {
+ if ((bytes_per_line % 4) == 0)
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
+ else if ((bytes_per_line % 2) == 0)
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2);
+ else
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
+
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
+ bytes_per_line / bytes_per_pixel);
+ }
+ else
+ {
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
+ gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, width);
+ bytes_per_line = width * bytes_per_pixel;
+ }
+ bound = 1;
+ }
+
+ pixels = ptr +
+ ((format->skip_lines + box.y1 - y_dst) * bytes_per_line) +
+ ((format->xoffset + box.x1 - x_dst) * bytes_per_pixel);
+ }
+
+ gl->tex_sub_image_2d (texture->target, 0,
+ texture->box.x1 + box.x1,
+ texture->box.y2 - box.y2,
+ box.x2 - box.x1, box.y2 - box.y1,
+ gl_format->format, gl_format->type,
+ pixels);
- gl->tex_sub_image_2d (texture->target, 0,
- texture->box.x1 + x_dst,
- texture->box.y2 - y_dst - height,
- width, height,
- gl_format->format, gl_format->type,
- pixels);
+ glitz_surface_damage (dst, &box,
+ GLITZ_DAMAGE_DRAWABLE_MASK |
+ GLITZ_DAMAGE_SOLID_MASK);
+ }
+ }
- if (transform == 0)
- glitz_buffer_unbind (buffer);
-
- glitz_texture_unbind (gl, texture);
+ if (transform)
+ {
+ free (data);
+ glitz_buffer_unmap (buffer);
+ } else
+ glitz_buffer_unbind (buffer);
- glitz_surface_damage (dst, &box,
- GLITZ_DAMAGE_DRAWABLE_MASK |
- GLITZ_DAMAGE_SOLID_MASK);
-
- glitz_surface_pop_current (dst);
-
- if (data)
- free (data);
+ BAIL:
+ glitz_texture_unbind (gl, texture);
+ glitz_surface_pop_current (dst);
}
void