static void twin_screen_span_pixmap(twin_screen_t *screen, twin_argb32_t *span, twin_pixmap_t *p, twin_coord_t y, twin_coord_t left, twin_coord_t right, twin_src_op op16, twin_src_op op32) { twin_pointer_t dst; twin_source_u src; twin_coord_t p_left, p_right; /* bounds check in y */ if (y < p->y) return; if (p->y + p->height <= y) return; /* bounds check in x*/ p_left = left; if (p_left < p->x) p_left = p->x; p_right = right; if (p_right > p->x + p->width) p_right = p->x + p->width; if (p_left >= p_right) return; dst.argb32 = span + (p_left - left); src.p = twin_pixmap_pointer (p, p_left - p->x, y - p->y); if (p->format == TWIN_RGB16) op16 (dst, src, p_right - p_left); else op32 (dst, src, p_right - p_left); }
static twin_argb32_t _twin_pixmap_fetch (twin_pixmap_t *pixmap, twin_coord_t x, twin_coord_t y) { twin_pointer_t p = twin_pixmap_pointer (pixmap, x - pixmap->x, y - pixmap->y); // XXX FIX FOR TRANSFORM if (pixmap->x <= x && x < pixmap->x + pixmap->width && pixmap->y <= y && y < pixmap->y + pixmap->height) { switch (pixmap->format) { case TWIN_A8: return *p.a8 << 24; case TWIN_RGB16: return twin_rgb16_to_argb32 (*p.rgb16); case TWIN_ARGB32: return *p.argb32; } } return 0; }
void twin_fill (twin_pixmap_t *dst, twin_argb32_t pixel, twin_operator_t operator, twin_coord_t left, twin_coord_t top, twin_coord_t right, twin_coord_t bottom) { twin_src_op op; twin_source_u src; twin_coord_t iy; /* offset */ left += dst->origin_x; top += dst->origin_y; right += dst->origin_x; bottom += dst->origin_y; /* clip */ if (left < dst->clip.left) left = dst->clip.left; if (right > dst->clip.right) right = dst->clip.right; if (top < dst->clip.top) top = dst->clip.top; if (bottom > dst->clip.bottom) bottom = dst->clip.bottom; if (left >= right || top >= bottom) return; src.c = pixel; op = fill[operator][dst->format]; for (iy = top; iy < bottom; iy++) (*op) (twin_pixmap_pointer (dst, left, iy), src, right - left); twin_pixmap_damage (dst, left, top, right, bottom); }
static void _twin_composite_xform (twin_pixmap_t *dst, twin_coord_t dst_x, twin_coord_t dst_y, twin_operand_t *src, twin_coord_t src_x, twin_coord_t src_y, twin_operand_t *msk, twin_coord_t msk_x, twin_coord_t msk_y, twin_operator_t operator, twin_coord_t width, twin_coord_t height) { twin_coord_t iy; twin_coord_t left, top, right, bottom; twin_xform_t *sxform = NULL, *mxform = NULL; twin_source_u s; dst_x += dst->origin_x; dst_y += dst->origin_y; left = dst_x; top = dst_y; right = dst_x + width; bottom = dst_y + height; /* clip */ if (left < dst->clip.left) left = dst->clip.left; if (top < dst->clip.top) top = dst->clip.top; if (right > dst->clip.right) right = dst->clip.right; if (bottom > dst->clip.bottom) bottom = dst->clip.bottom; if (left >= right || top >= bottom) return; width = right - left; height = bottom - top; if (src->source_kind == TWIN_PIXMAP) { src_x += src->u.pixmap->origin_x; src_y += src->u.pixmap->origin_y; sxform = twin_pixmap_init_xform(src->u.pixmap, left, width, src_x, src_y); if (sxform == NULL) return; s.p = sxform->span; } else s.c = src->u.argb; if (msk) { twin_src_msk_op op; twin_source_u m; if (msk->source_kind == TWIN_PIXMAP) { msk_x += msk->u.pixmap->origin_x; msk_y += msk->u.pixmap->origin_y; mxform = twin_pixmap_init_xform(msk->u.pixmap, left, width, msk_x, msk_y); if (mxform == NULL) return; m.p = mxform->span; } else m.c = msk->u.argb; op = comp3[operator][operand_xindex(src)][operand_xindex(msk)] [dst->format]; for (iy = top; iy < bottom; iy++) { if (src->source_kind == TWIN_PIXMAP) twin_pixmap_read_xform (sxform, iy - top); if (msk->source_kind == TWIN_PIXMAP) twin_pixmap_read_xform (mxform, iy - top); (*op) (twin_pixmap_pointer (dst, left, iy), s, m, right - left); } } else { twin_src_op op; op = comp2[operator][operand_xindex(src)][dst->format]; for (iy = top; iy < bottom; iy++) { if (src->source_kind == TWIN_PIXMAP) twin_pixmap_read_xform (sxform, iy - top); (*op) (twin_pixmap_pointer (dst, left, iy), s, right - left); } } twin_pixmap_damage (dst, left, top, right, bottom); twin_pixmap_free_xform(sxform); twin_pixmap_free_xform(mxform); }
/* XXX Fixme: source clipping is busted */ static void _twin_composite_simple (twin_pixmap_t *dst, twin_coord_t dst_x, twin_coord_t dst_y, twin_operand_t *src, twin_coord_t src_x, twin_coord_t src_y, twin_operand_t *msk, twin_coord_t msk_x, twin_coord_t msk_y, twin_operator_t operator, twin_coord_t width, twin_coord_t height) { twin_coord_t iy; twin_coord_t left, top, right, bottom; twin_coord_t sdx, sdy; twin_source_u s; dst_x += dst->origin_x; dst_y += dst->origin_y; left = dst_x; top = dst_y; right = dst_x + width; bottom = dst_y + height; /* clip */ if (left < dst->clip.left) left = dst->clip.left; if (top < dst->clip.top) top = dst->clip.top; if (right > dst->clip.right) right = dst->clip.right; if (bottom > dst->clip.bottom) bottom = dst->clip.bottom; if (left >= right || top >= bottom) return; if (src->source_kind == TWIN_PIXMAP) { src_x += src->u.pixmap->origin_x; src_y += src->u.pixmap->origin_y; } else s.c = src->u.argb; sdx = src_x - dst_x; sdy = src_y - dst_y; if (msk) { twin_src_msk_op op; twin_source_u m; twin_coord_t mdx, mdy; if (msk->source_kind == TWIN_PIXMAP) { msk_x += msk->u.pixmap->origin_x; msk_y += msk->u.pixmap->origin_y; } else m.c = msk->u.argb; mdx = msk_x - dst_x; mdy = msk_y - dst_y; op = comp3[operator][operand_index(src)][operand_index(msk)][dst->format]; for (iy = top; iy < bottom; iy++) { if (src->source_kind == TWIN_PIXMAP) s.p = twin_pixmap_pointer (src->u.pixmap, left+sdx, iy+sdy); if (msk->source_kind == TWIN_PIXMAP) m.p = twin_pixmap_pointer (msk->u.pixmap, left+mdx, iy+mdy); (*op) (twin_pixmap_pointer (dst, left, iy), s, m, right - left); } } else { twin_src_op op; op = comp2[operator][operand_index(src)][dst->format]; for (iy = top; iy < bottom; iy++) { if (src->source_kind == TWIN_PIXMAP) s.p = twin_pixmap_pointer (src->u.pixmap, left+sdx, iy+sdy); (*op) (twin_pixmap_pointer (dst, left, iy), s, right - left); } } twin_pixmap_damage (dst, left, top, right, bottom); }
void twin_screen_update (twin_screen_t *screen) { twin_coord_t left = screen->damage.left; twin_coord_t top = screen->damage.top; twin_coord_t right = screen->damage.right; twin_coord_t bottom = screen->damage.bottom; twin_src_op pop16, pop32, bop32; pop16 = _twin_rgb16_source_argb32; pop32 = _twin_argb32_over_argb32; bop32 = _twin_argb32_source_argb32; #ifdef HAVE_ALTIVEC if (twin_has_feature(TWIN_FEATURE_ALTIVEC)) { pop32 = _twin_vec_argb32_over_argb32; bop32 = _twin_vec_argb32_source_argb32; } #endif if (right > screen->width) right = screen->width; if (bottom > screen->height) bottom = screen->height; if (!screen->disable && left < right && top < bottom) { twin_argb32_t *span; twin_pixmap_t *p; twin_coord_t y; twin_coord_t width = right - left; screen->damage.left = screen->damage.right = 0; screen->damage.top = screen->damage.bottom = 0; /* XXX what is the maximum number of lines? */ span = malloc (width * sizeof (twin_argb32_t)); if (!span) return; if (screen->put_begin) (*screen->put_begin) (left, top, right, bottom, screen->closure); for (y = top; y < bottom; y++) { if (screen->background) { twin_pointer_t dst; twin_source_u src; twin_coord_t p_left; twin_coord_t m_left; twin_coord_t p_this; twin_coord_t p_width = screen->background->width; twin_coord_t p_y = y % screen->background->height; for (p_left = left; p_left < right; p_left += p_this) { dst.argb32 = span + (p_left - left); m_left = p_left % p_width; p_this = p_width - m_left; if (p_left + p_this > right) p_this = right - p_left; src.p = twin_pixmap_pointer (screen->background, m_left, p_y); bop32 (dst, src, p_this); } } else memset (span, 0xff, width * sizeof (twin_argb32_t)); for (p = screen->bottom; p; p = p->up) twin_screen_span_pixmap(screen, span, p, y, left, right, pop16, pop32); if (screen->cursor) twin_screen_span_pixmap(screen, span, screen->cursor, y, left, right, pop16, pop32); (*screen->put_span) (left, y, right, span, screen->closure); } free (span); } }