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);
}
예제 #2
0
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;
}
예제 #3
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);
}
예제 #4
0
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);
}
예제 #5
0
/* 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);
    }
}