From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/SaWMan/src/sawman_draw.c | 677 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 677 insertions(+) create mode 100755 Source/SaWMan/src/sawman_draw.c (limited to 'Source/SaWMan/src/sawman_draw.c') diff --git a/Source/SaWMan/src/sawman_draw.c b/Source/SaWMan/src/sawman_draw.c new file mode 100755 index 0000000..16ce61b --- /dev/null +++ b/Source/SaWMan/src/sawman_draw.c @@ -0,0 +1,677 @@ +/* + (c) Copyright 2001-2007 directfb.org + (c) Copyright 2000-2004 convergence (integrated) media GmbH. + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann and + Ville Syrjälä . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +D_DEBUG_DOMAIN( SaWMan_Draw, "SaWMan/Draw", "SaWMan window manager drawing" ); + +/**********************************************************************************************************************/ + +void +sawman_draw_cursor( CoreWindowStack *stack, CardState *state, DFBRegion *region, int x, int y ) +{ + DFBRectangle src; + DFBRectangle clip; + DFBSurfaceBlittingFlags flags = DSBLIT_BLEND_ALPHACHANNEL; + + D_ASSERT( stack != NULL ); + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( region ); + + D_ASSUME( stack->cursor.opacity > 0 ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, + stack, DFB_RECTANGLE_VALS_FROM_REGION( region ) ); + + /* Initialize source rectangle. */ + src.x = region->x1 - x + stack->cursor.hot.x; + src.y = region->y1 - y + stack->cursor.hot.y; + src.w = region->x2 - region->x1 + 1; + src.h = region->y2 - region->y1 + 1; + + /* Initialize source clipping rectangle */ + clip.x = clip.y = 0; + clip.w = stack->cursor.surface->config.size.w; + clip.h = stack->cursor.surface->config.size.h; + + /* Intersect rectangles */ + if (!dfb_rectangle_intersect( &src, &clip )) + return; + + /* Use global alpha blending. */ + if (stack->cursor.opacity != 0xFF) { + flags |= DSBLIT_BLEND_COLORALPHA; + + /* Set opacity as blending factor. */ + if (state->color.a != stack->cursor.opacity) { + state->color.a = stack->cursor.opacity; + state->modified |= SMF_COLOR; + } + } + + /* Different compositing methods depending on destination format. */ + if (flags & DSBLIT_BLEND_ALPHACHANNEL) { + if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) { + /* + * Always use compliant Porter/Duff SRC_OVER, + * if the destination has an alpha channel. + * + * Cd = destination color (non-premultiplied) + * Ad = destination alpha + * + * Cs = source color (non-premultiplied) + * As = source alpha + * + * Ac = color alpha + * + * cd = Cd * Ad (premultiply destination) + * cs = Cs * As (premultiply source) + * + * The full equation to calculate resulting color and alpha (premultiplied): + * + * cx = cd * (1-As*Ac) + cs * Ac + * ax = Ad * (1-As*Ac) + As * Ac + */ + dfb_state_set_src_blend( state, DSBF_ONE ); + + /* Need to premultiply source with As*Ac or only with Ac? */ + if (! (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED)) + flags |= DSBLIT_SRC_PREMULTIPLY; + else if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + + /* Need to premultiply/demultiply destination? */ +// if (! (state->destination->caps & DSCAPS_PREMULTIPLIED)) +// flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY; + } + else { + /* + * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel + * by using another blending function, which is more likely that it's accelerated + * than premultiplication at this point in time. + * + * This way the resulting alpha (ax) doesn't comply with SRC_OVER, + * but as the destination doesn't have an alpha channel it's no problem. + * + * As the destination's alpha value is always 1.0 there's no need for + * premultiplication. The resulting alpha value will also be 1.0 without + * exceptions, therefore no need for demultiplication. + * + * cx = Cd * (1-As*Ac) + Cs*As * Ac (still same effect as above) + * ax = Ad * (1-As*Ac) + As*As * Ac (wrong, but discarded anyways) + */ + if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) { + /* Need to premultiply source with Ac? */ + if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + + dfb_state_set_src_blend( state, DSBF_ONE ); + } + else + dfb_state_set_src_blend( state, DSBF_SRCALPHA ); + } + } + + /* Set blitting flags. */ + dfb_state_set_blitting_flags( state, flags ); + + /* Set blitting source. */ + state->source = stack->cursor.surface; + state->modified |= SMF_SOURCE; + + /* Blit from the window to the region being updated. */ + dfb_gfxcard_blit( &src, region->x1, region->y1, state ); + + /* Reset blitting source. */ + state->source = NULL; + state->modified |= SMF_SOURCE; +} + +static void +draw_border( SaWManWindow *sawwin, + CardState *state, + const DFBRegion *region, + int thickness ) +{ + int i; + DFBRegion old_clip; + DFBRectangle rects[thickness]; + CoreWindow *window; + const SaWManBorderInit *border; + const DFBColor *colors; + const int *indices; + unsigned int num_colors; + unsigned int num_indices; + + window = sawwin->window; + D_ASSERT( window != NULL ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %p, %d,%d-%dx%d, %d )\n", __FUNCTION__, + sawwin, state, DFB_RECTANGLE_VALS_FROM_REGION( region ), thickness ); + + if (thickness > sawwin->bounds.w / 2) + thickness = sawwin->bounds.w / 2; + + if (thickness > sawwin->bounds.h / 2) + thickness = sawwin->bounds.h / 2; + + /* Check thickness. */ + if (thickness < 1) + return; + + /* Initialize border rectangles. */ + rects[0] = sawwin->bounds; + + for (i=1; iclip; + + /* Change clipping region. */ + dfb_state_set_clip( state, region ); + + border = &sawman_config->borders[sawman_window_priority(sawwin)]; + + if (window->flags & CWF_FOCUSED) { + colors = border->focused; + indices = border->focused_index; + num_colors = D_ARRAY_SIZE(border->focused); + num_indices = D_ARRAY_SIZE(border->focused_index); + } + else { + colors = border->unfocused; + indices = border->unfocused_index; + num_colors = D_ARRAY_SIZE(border->unfocused); + num_indices = D_ARRAY_SIZE(border->unfocused_index); + } + + /* Draw border rectangles. */ + for (i=0; isawman; + window = sawwin->window; + dst = sawwin->dst; + src = sawwin->src; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_ASSERT( window != NULL ); + D_ASSERT( window->surface != NULL ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, + sawwin, DFB_RECTANGLE_VALS_FROM_REGION( region ) ); + + /* Setup clipping region. */ + clip = *region; + + if (!dfb_region_rectangle_intersect( &clip, &dst )) + return; + + /* Backup clipping region. */ + old_clip = state->clip; + + /* Use per pixel alpha blending. */ + if (alpha_channel && (window->config.options & DWOP_ALPHACHANNEL)) + flags |= DSBLIT_BLEND_ALPHACHANNEL; + + /* Use global alpha blending. */ + if (window->config.opacity != 0xFF) { + flags |= DSBLIT_BLEND_COLORALPHA; + + /* Set opacity as blending factor. */ + if (state->color.a != window->config.opacity) { + state->color.a = window->config.opacity; + state->modified |= SMF_COLOR; + } + } + + /* Use source color keying. */ + if (window->config.options & DWOP_COLORKEYING) { + flags |= DSBLIT_SRC_COLORKEY; + + D_DEBUG_AT( SaWMan_Draw, " -> key 0x%08x\n", window->config.color_key ); + + /* Set window color key. */ + dfb_state_set_src_colorkey( state, window->config.color_key ); + } + + /* Use automatic deinterlacing. */ + if (window->surface->config.caps & DSCAPS_INTERLACED) + flags |= DSBLIT_DEINTERLACE; + + /* Different compositing methods depending on destination format. */ + if (flags & DSBLIT_BLEND_ALPHACHANNEL) { + if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) { + /* + * Always use compliant Porter/Duff SRC_OVER, + * if the destination has an alpha channel. + * + * Cd = destination color (non-premultiplied) + * Ad = destination alpha + * + * Cs = source color (non-premultiplied) + * As = source alpha + * + * Ac = color alpha + * + * cd = Cd * Ad (premultiply destination) + * cs = Cs * As (premultiply source) + * + * The full equation to calculate resulting color and alpha (premultiplied): + * + * cx = cd * (1-As*Ac) + cs * Ac + * ax = Ad * (1-As*Ac) + As * Ac + */ + dfb_state_set_src_blend( state, DSBF_ONE ); + + /* Need to premultiply source with As*Ac or only with Ac? */ + if (! (window->surface->config.caps & DSCAPS_PREMULTIPLIED)) + flags |= DSBLIT_SRC_PREMULTIPLY; + else if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + + /* Need to premultiply/demultiply destination? */ +// if (! (state->destination->caps & DSCAPS_PREMULTIPLIED)) +// flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY; + } + else { + /* + * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel + * by using another blending function, which is more likely that it's accelerated + * than premultiplication at this point in time. + * + * This way the resulting alpha (ax) doesn't comply with SRC_OVER, + * but as the destination doesn't have an alpha channel it's no problem. + * + * As the destination's alpha value is always 1.0 there's no need for + * premultiplication. The resulting alpha value will also be 1.0 without + * exceptions, therefore no need for demultiplication. + * + * cx = Cd * (1-As*Ac) + Cs*As * Ac (still same effect as above) + * ax = Ad * (1-As*Ac) + As*As * Ac (wrong, but discarded anyways) + */ + if (window->surface->config.caps & DSCAPS_PREMULTIPLIED) { + /* Need to premultiply source with Ac? */ + if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + + dfb_state_set_src_blend( state, DSBF_ONE ); + } + else + dfb_state_set_src_blend( state, DSBF_SRCALPHA ); + } + } + + /* Use color (key) protection if layer is keyed. */ + if (tier->context->config.options & DLOP_SRC_COLORKEY) { + flags |= DSBLIT_COLORKEY_PROTECT; + + dfb_state_set_colorkey( state, &tier->key ); + } + + /* Set blitting flags. */ + dfb_state_set_blitting_flags( state, flags ); + + /* Set render options. */ + if (sawman->scaling_mode == SWMSM_SMOOTH_SW) + dfb_state_set_render_options( state, DSRO_SMOOTH_DOWNSCALE | DSRO_SMOOTH_UPSCALE ); + else + dfb_state_set_render_options( state, DSRO_NONE ); + + /* Set blitting source. */ + state->source = window->surface; + state->modified |= SMF_SOURCE; + + D_DEBUG_AT( SaWMan_Draw, " [][] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( &clip ) ); + + /* Change clipping region. */ + dfb_state_set_clip( state, &clip ); + + D_DEBUG_AT( SaWMan_Draw, " => %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\n", + DFB_RECTANGLE_VALS( &dst ), DFB_RECTANGLE_VALS( &src ) ); + + /* Scale window to the screen clipped by the region being updated. */ + dfb_gfxcard_stretchblit( &src, &dst, state ); + + /* Restore clipping region. */ + dfb_state_set_clip( state, &old_clip ); +} + +static void +draw_window_color( SaWManWindow *sawwin, + CardState *state, + DFBRegion *region, + bool alpha_channel ) +{ + SaWMan *sawman; + CoreWindow *window; + DFBSurfaceDrawingFlags flags = DSDRAW_NOFX; + DFBRectangle dst; + DFBRegion clip; + DFBRegion old_clip; + DFBColor color; + + + sawman = sawwin->sawman; + window = sawwin->window; + dst = sawwin->dst; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_ASSERT( window != NULL ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, + sawwin, DFB_RECTANGLE_VALS_FROM_REGION( region ) ); + + color = window->config.color; + + /* Setup clipping region. */ + clip = *region; + + if (!dfb_region_rectangle_intersect( &clip, &dst )) + return; + + /* Backup clipping region. */ + old_clip = state->clip; + + /* Use per pixel alpha blending. */ + if (alpha_channel && (window->config.options & DWOP_ALPHACHANNEL)) + flags |= DSDRAW_BLEND; + + /* we assume the passed color is never premultiplied */ + flags |= DSDRAW_SRC_PREMULTIPLY; + + /* when not opaque, we simply adjust the color */ + if (window->config.opacity != 0xFF) { + flags |= DSDRAW_BLEND; + color.a = (color.a * window->config.opacity) >> 8; + } + + dfb_state_set_drawing_flags( state, flags ); + + if (DFB_PIXELFORMAT_IS_INDEXED( state->destination->config.format )) { + unsigned int i = dfb_palette_search( state->destination->palette, + color.r, color.g, color.b, color.a ); + dfb_state_set_color_index( state, i ); + } + else + dfb_state_set_color( state, &color ); + + D_DEBUG_AT( SaWMan_Draw, " [][] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( &clip ) ); + + /* Change clipping region. */ + dfb_state_set_clip( state, &clip ); + + D_DEBUG_AT( SaWMan_Draw, " => %4d,%4d-%4dx%4d\n", + DFB_RECTANGLE_VALS( &dst ) ); + + dfb_gfxcard_fillrectangles( &dst, 1, state ); + + /* Restore clipping region. */ + dfb_state_set_clip( state, &old_clip ); +} + +void +sawman_draw_window( SaWManTier *tier, + SaWManWindow *sawwin, + CardState *state, + DFBRegion *pregion, + bool alpha_channel ) +{ + CoreWindow *window; + DFBRegion xregion = *pregion; + DFBRegion *region = &xregion; + int border; + bool input; + + D_MAGIC_ASSERT( sawwin, SaWManWindow ); + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( region ); + + window = sawwin->window; + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, + sawwin, DFB_RECTANGLE_VALS_FROM_REGION( pregion ) ); + + border = sawman_window_border( sawwin ); + + /* if input only, we only draw the border */ + input = (window->caps & DWCAPS_INPUTONLY) || (window->config.options & DWOP_INPUTONLY); + + + if (!input && + dfb_region_intersect( region, + sawwin->bounds.x + border, + sawwin->bounds.y + border, + sawwin->bounds.x + sawwin->bounds.w - border - 1, + sawwin->bounds.y + sawwin->bounds.h - border - 1 ) && + dfb_region_rectangle_intersect( region, &sawwin->dst ) + ) { + if( window->surface ) + draw_window( tier, sawwin, state, region, alpha_channel ); + else if( window->caps & DWCAPS_COLOR ) + draw_window_color( sawwin, state, region, alpha_channel ); + } + + if (border) + draw_border( sawwin, state, pregion, border ); + + /* Reset blitting source. */ + state->source = NULL; + state->modified |= SMF_SOURCE; +} + +void +sawman_draw_background( SaWManTier *tier, CardState *state, DFBRegion *region ) +{ + DFBRectangle dst; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( tier, SaWManTier ); + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( region ); + + D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, tier, + DFB_RECTANGLE_VALS_FROM_REGION( region ) ); + + stack = tier->stack; + D_ASSERT( stack != NULL ); + + D_ASSERT( stack->bg.image != NULL || (stack->bg.mode != DLBM_IMAGE && + stack->bg.mode != DLBM_TILE) ); + + /* Initialize destination rectangle. */ + dfb_rectangle_from_region( &dst, region ); + + switch (stack->bg.mode) { + case DLBM_COLOR: { + /* Set the background color. */ + dfb_state_set_color_or_index( state, &stack->bg.color, stack->bg.color_index ); + + if (stack->bg.color_index < 0 || !state->destination->palette) + D_DEBUG_AT( SaWMan_Draw, " -> fill %02x %02x %02x %02x [%d]\n", + stack->bg.color.a, stack->bg.color.r, stack->bg.color.g, stack->bg.color.b, + stack->bg.color_index ); + else + D_DEBUG_AT( SaWMan_Draw, " -> fill %02x %02x %02x %02x [%d] -> %02x %02x %02x %02x\n", + stack->bg.color.a, stack->bg.color.r, stack->bg.color.g, stack->bg.color.b, + stack->bg.color_index, + state->destination->palette->entries[stack->bg.color_index].a, + state->destination->palette->entries[stack->bg.color_index].r, + state->destination->palette->entries[stack->bg.color_index].g, + state->destination->palette->entries[stack->bg.color_index].b ); + + /* Simply fill the background. */ + dfb_gfxcard_fillrectangles( &dst, 1, state ); + + break; + } + + case DLBM_IMAGE: { + CoreSurface *bg = stack->bg.image; + + /* Set blitting source. */ + state->source = bg; + state->modified |= SMF_SOURCE; + + /* Set blitting flags. */ + dfb_state_set_blitting_flags( state, DSBLIT_NOFX ); + + /* Check the size of the background image. */ + if (bg->config.size.w == stack->width && bg->config.size.h == stack->height) { + /* Simple blit for 100% fitting background image. */ + dfb_gfxcard_blit( &dst, dst.x, dst.y, state ); + } + else { + DFBRegion old_clip = state->clip; + DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h }; + + /* Change clipping region. */ + dfb_state_set_clip( state, region ); + + /* + * Scale image to fill the whole screen + * clipped to the region being updated. + */ + dst.x = 0; + dst.y = 0; + dst.w = stack->width; + dst.h = stack->height; + + /* Stretch blit for non fitting background images. */ + dfb_gfxcard_stretchblit( &src, &dst, state ); + + /* Restore clipping region. */ + dfb_state_set_clip( state, &old_clip ); + } + + /* Reset blitting source. */ + state->source = NULL; + state->modified |= SMF_SOURCE; + + break; + } + + case DLBM_TILE: { + CoreSurface *bg = stack->bg.image; + DFBRegion old_clip = state->clip; + DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h }; + + /* Set blitting source. */ + state->source = bg; + state->modified |= SMF_SOURCE; + + /* Set blitting flags. */ + dfb_state_set_blitting_flags( state, DSBLIT_NOFX ); + + /* Change clipping region. */ + dfb_state_set_clip( state, region ); + + /* Tiled blit (aligned). */ + dfb_gfxcard_tileblit( &src, + (region->x1 / src.w) * src.w, + (region->y1 / src.h) * src.h, + (region->x2 / src.w + 1) * src.w, + (region->y2 / src.h + 1) * src.h, + state ); + + /* Restore clipping region. */ + dfb_state_set_clip( state, &old_clip ); + + /* Reset blitting source. */ + state->source = NULL; + state->modified |= SMF_SOURCE; + + break; + } + + case DLBM_DONTCARE: + break; + + default: + D_BUG( "unknown background mode" ); + break; + } +} + -- cgit