void dfb_updates_add( DFBUpdates *updates, const DFBRegion *region ) { int i; D_MAGIC_ASSERT( updates, DFBUpdates ); DFB_REGION_ASSERT( region ); D_ASSERT( updates->regions != NULL ); D_ASSERT( updates->num_regions >= 0 ); D_ASSERT( updates->num_regions <= updates->max_regions ); D_DEBUG_AT( DFB_Updates, "%s( %p, %4d,%4d-%4dx%4d )\n", __FUNCTION__, (void*)updates, DFB_RECTANGLE_VALS_FROM_REGION(region) ); if (updates->num_regions == 0) { D_DEBUG_AT( DFB_Updates, " -> added as first\n" ); updates->regions[0] = updates->bounding = *region; updates->num_regions = 1; return; } for (i=0; i<updates->num_regions; i++) { if (dfb_region_region_extends( &updates->regions[i], region ) || dfb_region_region_intersects( &updates->regions[i], region )) { D_DEBUG_AT( DFB_Updates, " -> combined with [%d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); dfb_region_region_union( &updates->regions[i], region ); dfb_region_region_union( &updates->bounding, region ); D_DEBUG_AT( DFB_Updates, " -> resulting in [%d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); return; } } if (updates->num_regions == updates->max_regions) { dfb_region_region_union( &updates->bounding, region ); updates->regions[0] = updates->bounding; updates->num_regions = 1; D_DEBUG_AT( DFB_Updates, " -> collapsing to [0] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[0]) ); } else { updates->regions[updates->num_regions++] = *region; dfb_region_region_union( &updates->bounding, region ); D_DEBUG_AT( DFB_Updates, " -> added as [%d] %4d,%4d-%4dx%4d\n", updates->num_regions - 1, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[updates->num_regions - 1]) ); } }
static void draw_window_color( SaWManWindow *sawwin, CardState *state, DFBRegion *region, bool alpha_channel, bool right_eye ) { SaWMan *sawman; CoreWindow *window; DFBSurfaceDrawingFlags flags = DSDRAW_NOFX; DFBRectangle dst; DFBRegion clip; DFBRegion old_clip; DFBColor color; int offset; 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; /* Modify dst for stereo offset. */ offset = window->config.z; offset *= right_eye ? -1 : 1; dfb_rectangle_translate( &dst, offset, 0 ); /* 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; }
static DFBResult IDirectFBSurface_Layer_Flip( IDirectFBSurface *thiz, const DFBRegion *region, DFBSurfaceFlipFlags flags ) { DFBRegion reg; DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Layer) D_DEBUG_AT( Surface, "%s( %p, %p, 0x%08x )\n", __FUNCTION__, thiz, region, flags ); if (!data->base.surface) return DFB_DESTROYED; if (data->base.locked) return DFB_LOCKED; if (!data->base.area.current.w || !data->base.area.current.h || (region && (region->x1 > region->x2 || region->y1 > region->y2))) return DFB_INVAREA; IDirectFBSurface_StopAll( &data->base ); if (data->base.parent) { IDirectFBSurface_data *parent_data; DIRECT_INTERFACE_GET_DATA_FROM( data->base.parent, parent_data, IDirectFBSurface ); if (parent_data) { /* Signal end of sequence of operations. */ dfb_state_lock( &parent_data->state ); dfb_state_stop_drawing( &parent_data->state ); dfb_state_unlock( &parent_data->state ); } } dfb_region_from_rectangle( ®, &data->base.area.current ); if (region) { DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, data->base.area.wanted.x, data->base.area.wanted.y ); if (!dfb_region_region_intersect( ®, &clip )) return DFB_INVAREA; } D_DEBUG_AT( Surface, " -> FLIP %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( ® ) ); return CoreLayerRegion_FlipUpdate( data->region, ®, flags ); }
static inline void validate_clip( CardState *state, int xmax, int ymax, bool warn ) { D_DEBUG_AT( Core_GfxState, "%s( %p, %d, %d, %d )\n", __FUNCTION__, state, xmax, ymax, warn ); D_MAGIC_ASSERT( state, CardState ); DFB_REGION_ASSERT( &state->clip ); D_ASSERT( xmax >= 0 ); D_ASSERT( ymax >= 0 ); D_ASSERT( state->clip.x1 <= state->clip.x2 ); D_ASSERT( state->clip.y1 <= state->clip.y2 ); if (state->clip.x1 <= xmax && state->clip.y1 <= ymax && state->clip.x2 <= xmax && state->clip.y2 <= ymax) return; if (warn) D_WARN( "Clip %d,%d-%dx%d invalid, adjusting to fit %dx%d", DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax+1, ymax+1 ); if (state->clip.x1 > xmax) state->clip.x1 = xmax; if (state->clip.y1 > ymax) state->clip.y1 = ymax; if (state->clip.x2 > xmax) state->clip.x2 = xmax; if (state->clip.y2 > ymax) state->clip.y2 = ymax; state->modified |= SMF_CLIP; }
void sawman_dispatch_blit( SaWMan *sawman, SaWManWindow *sawwin, bool right_eye, const DFBRectangle *src, const DFBRectangle *dst, const DFBRegion *clip ) { SaWManListenerCallData data; if (clip) { D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d %d,%d-%dx%d %d,%d-%dx%d )\n", __FUNCTION__, sawwin, DFB_RECTANGLE_VALS( src ), DFB_RECTANGLE_VALS( dst ), DFB_RECTANGLE_VALS_FROM_REGION( clip ) ); } else { D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d %d,%d-%dx%d NO CLIP )\n", __FUNCTION__, sawwin, DFB_RECTANGLE_VALS( src ), DFB_RECTANGLE_VALS( dst ) ); } data.call = SWMLC_WINDOW_BLIT; data.stereo_eye = right_eye ? DSSE_RIGHT : DSSE_LEFT; data.window_id = sawwin->window->id; data.resource_id = sawwin->window->resource_id; data.src = *src; data.dst = *dst; if (clip) { if (dfb_clip_blit_precheck( clip, dst->w, dst->h, dst->x, dst->y )) { dfb_clip_stretchblit( clip, &data.src, &data.dst ); fusion_reactor_dispatch( sawman->reactor, &data, true, NULL ); } else D_DEBUG_AT( SaWMan_Draw, " -> CLIPPED!\n" ); } else fusion_reactor_dispatch( sawman->reactor, &data, true, NULL ); }
static DFBResult dfb_sdl_update_screen_handler( const DFBRegion *region ) { DFBRegion update; CoreSurface *surface = dfb_sdl->primary; DFB_REGION_ASSERT_IF( region ); if (region) update = *region; else { update.x1 = 0; update.y1 = 0; update.x2 = surface->config.size.w - 1; update.y2 = surface->config.size.h - 1; } #if 0 pthread_mutex_lock( &dfb_sdl->update.lock ); if (dfb_sdl->update.pending) dfb_region_region_union( &dfb_sdl->update.region, &update ); else { dfb_sdl->update.region = update; dfb_sdl->update.pending = true; } pthread_cond_signal( &dfb_sdl->update.cond ); pthread_mutex_unlock( &dfb_sdl->update.lock ); #else if (surface->config.caps & DSCAPS_FLIPPING) SDL_Flip( dfb_sdl->screen ); else SDL_UpdateRect( dfb_sdl->screen, DFB_RECTANGLE_VALS_FROM_REGION(&update) ); #endif return DFB_OK; }
StretRegion * stret_iteration_next( StretIteration *iteration, const DFBRegion *clip ) { int index; int level; StretRegion *region; D_MAGIC_ASSERT( iteration, StretIteration ); DFB_REGION_ASSERT_IF( clip ); if (clip) D_DEBUG_AT( UniQuE_StReT, "stret_iteration_next( %d, %d - %dx%d )\n", DFB_RECTANGLE_VALS_FROM_REGION( clip ) ); else D_DEBUG_AT( UniQuE_StReT, "stret_iteration_next()\n" ); while (iteration->frame >= 0) { StretIterationStackFrame *frame = &iteration->stack[iteration->frame]; region = frame->region; level = frame->level; index = frame->index--; D_MAGIC_ASSERT( region, StretRegion ); D_DEBUG_AT( UniQuE_StReT, " -> (%d) %p, level [%d/%d], index %d\n", iteration->frame, region, level, region->levels - 1, index ); if (iteration->abort && region == iteration->abort) { D_MAGIC_CLEAR( iteration ); return NULL; } if (index < 0) { level = --frame->level; if (level < 0) { iteration->frame--; iteration->x0 -= region->bounds.x1; iteration->y0 -= region->bounds.y1; if (accept_region( region, iteration->x0, iteration->y0, clip )) return region; } else { frame->index = fusion_vector_size( ®ion->children[level] ) - 1; } } else { region = fusion_vector_at( ®ion->children[level], index ); D_MAGIC_ASSERT( region, StretRegion ); if (iteration->abort && region == iteration->abort) { D_MAGIC_CLEAR( iteration ); return NULL; } if (accept_region( region, iteration->x0, iteration->y0, clip )) { level = region->levels - 1; while (fusion_vector_is_empty( ®ion->children[level] )) { if (level) level--; else return region; } if (check_depth( iteration->frame + 1 )) { frame = &iteration->stack[++iteration->frame]; iteration->x0 += region->bounds.x1; iteration->y0 += region->bounds.y1; frame->region = region; frame->level = level; frame->index = fusion_vector_size( ®ion->children[level] ) - 1; continue; } return region; } } } D_ASSUME( iteration->x0 == 0 ); D_ASSUME( iteration->y0 == 0 ); D_MAGIC_CLEAR( iteration ); return NULL; }
static void foo_update( StretRegion *region, void *region_data, void *update_data, unsigned long arg, int x, int y, const DFBRegion *updates, int num ) { int i; DFBRegion clip; DFBDimension size; bool visible; WMShared *shared; UniqueContext *context; UniqueWindow *window = region_data; CardState *state = update_data; DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; D_ASSERT( region != NULL ); D_ASSERT( region_data != NULL ); D_ASSERT( update_data != NULL ); D_ASSERT( updates != NULL ); D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT( state, CardState ); shared = window->shared; D_MAGIC_ASSERT( shared, WMShared ); D_ASSERT( shared->foo_surface != NULL ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); visible = D_FLAGS_IS_SET( window->flags, UWF_VISIBLE ); D_DEBUG_AT( UniQuE_Foo, "foo_update( region %p, window %p, visible %s, num %d )\n", region, window, visible ? "yes" : "no", num ); #if D_DEBUG_ENABLED for (i=0; i<num; i++) { D_DEBUG_AT( UniQuE_Foo, " (%d) %4d,%4d - %4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION( &updates[i] ) ); } #endif if (!visible) return; stret_region_get_size( region, &size ); /* Use per pixel alpha blending. */ flags |= DSBLIT_BLEND_ALPHACHANNEL; /* Use global alpha blending. */ if (window->opacity != 0xFF) { flags |= DSBLIT_BLEND_COLORALPHA; /* Set opacity as blending factor. */ if (state->color.a != window->opacity) { state->color.a = window->opacity; state->modified |= SMF_COLOR; } } /* Use colorizing if the color is not white. */ if (context->color.r != 0xff || context->color.g != 0xff || context->color.b != 0xff) { flags |= DSBLIT_COLORIZE; state->color.r = context->color.r; state->color.g = context->color.g; state->color.b = context->color.b; state->modified |= SMF_COLOR; } /* Set blitting flags. */ dfb_state_set_blitting_flags( state, flags ); /* Set blitting source. */ state->source = shared->foo_surface; state->modified |= SMF_SOURCE; switch (arg) { case UFI_N: case UFI_E: case UFI_S: case UFI_W: clip = state->clip; /* for (i=0; i<num; i++) { DFBRegion update = DFB_REGION_INIT_TRANSLATED( &updates[i], x, y ); DFBRectangle source = shared->foo_rects[arg]; DFBRectangle dest = { x, y, size.w, size.h }; dfb_state_set_clip( state, &update ); dfb_gfxcard_stretchblit( &source, &dest, state ); }*/ for (i=0; i<num; i++) { DFBRegion update = DFB_REGION_INIT_TRANSLATED( &updates[i], x, y ); DFBRectangle source = shared->foo_rects[arg]; dfb_state_set_clip( state, &update ); dfb_gfxcard_tileblit( &source, x, y, x + size.w - 1, y + size.h - 1, state ); } dfb_state_set_clip( state, &clip ); break; case UFI_NE: case UFI_SE: case UFI_SW: case UFI_NW: for (i=0; i<num; i++) { DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &updates[i] ); dfb_rectangle_translate( &rect, shared->foo_rects[arg].x, shared->foo_rects[arg].y ); dfb_gfxcard_blit( &rect, x + updates[i].x1, y + updates[i].y1, state ); } break; default: D_BUG( "invalid arg" ); } /* Reset blitting source. */ state->source = NULL; state->modified |= SMF_SOURCE; }
DFBResult dfb_layer_region_flip_update( CoreLayerRegion *region, const DFBRegion *update, DFBSurfaceFlipFlags flags ) { DFBResult ret = DFB_OK; CoreLayer *layer; CoreLayerContext *context; CoreSurface *surface; SurfaceBuffer *buffer; DisplayLayerFuncs *funcs; if (update) D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x ) <- [%d, %d - %dx%d]\n", region, update, flags, DFB_RECTANGLE_VALS_FROM_REGION( update ) ); else D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x )\n", region, update, flags ); D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); /* Lock the region. */ if (dfb_layer_region_lock( region )) return DFB_FUSION; D_ASSUME( region->surface != NULL ); /* Check for NULL surface. */ if (!region->surface) { D_DEBUG_AT( Core_Layers, " -> No surface => no update!\n" ); dfb_layer_region_unlock( region ); return DFB_UNSUPPORTED; } context = region->context; surface = region->surface; buffer = surface->back_buffer; layer = dfb_layer_at( context->layer_id ); D_ASSERT( layer->funcs != NULL ); funcs = layer->funcs; /* Depending on the buffer mode... */ switch (region->config.buffermode) { case DLBM_TRIPLE: case DLBM_BACKVIDEO: /* Check if simply swapping the buffers is possible... */ if (!(flags & DSFLIP_BLIT) && (!update || (update->x1 == 0 && update->y1 == 0 && update->x2 == surface->width - 1 && update->y2 == surface->height - 1))) { D_DEBUG_AT( Core_Layers, " -> Going to swap buffers...\n" ); /* Use the driver's routine if the region is realized. */ if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { D_ASSUME( funcs->FlipRegion != NULL ); D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); if (buffer->video.access & VAF_HARDWARE_WRITE) { dfb_gfxcard_wait_serial( &buffer->video.serial ); buffer->video.access &= ~VAF_HARDWARE_WRITE; } D_DEBUG_AT( Core_Layers, " -> Flipping region using driver...\n" ); if (funcs->FlipRegion) ret = funcs->FlipRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, flags ); } else { D_DEBUG_AT( Core_Layers, " -> Flipping region not using driver...\n" ); /* Just do the hardware independent work. */ dfb_surface_flip_buffers( surface, false ); } break; } /* fall through */ case DLBM_BACKSYSTEM: D_DEBUG_AT( Core_Layers, " -> Going to copy portion...\n" ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } D_DEBUG_AT( Core_Layers, " -> Copying content from back to front buffer...\n" ); /* ...or copy updated contents from back to front buffer. */ dfb_back_to_front_copy( surface, update ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } /* fall through */ case DLBM_FRONTONLY: /* Tell the driver about the update if the region is realized. */ if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { D_DEBUG_AT( Core_Layers, " -> Notifying driver about updated content...\n" ); ret = funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, update ); } break; default: D_BUG("unknown buffer mode"); ret = DFB_BUG; } D_DEBUG_AT( Core_Layers, " -> done.\n" ); /* Unlock the region. */ dfb_layer_region_unlock( region ); return ret; }
static void root_update( StretRegion *region, void *region_data, void *update_data, unsigned long arg, int x, int y, const DFBRegion *updates, int num ) { int i; CoreWindowStack *stack; UniqueContext *context = region_data; CardState *state = update_data; D_ASSERT( region != NULL ); D_ASSERT( region_data != NULL ); D_ASSERT( update_data != NULL ); D_ASSERT( updates != NULL ); D_ASSERT( x == 0 ); D_ASSERT( y == 0 ); D_MAGIC_ASSERT( context, UniqueContext ); D_MAGIC_ASSERT( state, CardState ); stack = context->stack; D_ASSERT( stack != NULL ); D_ASSERT( stack->bg.image != NULL || (stack->bg.mode != DLBM_IMAGE && stack->bg.mode != DLBM_TILE) ); D_DEBUG_AT( UniQuE_Root, "root_update( region %p, num %d )\n", region, num ); #if D_DEBUG_ENABLED for (i=0; i<num; i++) { D_DEBUG_AT( UniQuE_Root, " (%d) %4d,%4d - %4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION( &updates[i] ) ); } #endif switch (stack->bg.mode) { case DLBM_COLOR: { CoreSurface *dest = state->destination; DFBColor *color = &stack->bg.color; DFBRectangle rects[num]; /* Set the background color. */ if (DFB_PIXELFORMAT_IS_INDEXED( dest->config.format )) dfb_state_set_color_index( state, dfb_palette_search( dest->palette, color->r, color->g, color->b, color->a ) ); else dfb_state_set_color( state, color ); for (i=0; i<num; i++) dfb_rectangle_from_region( &rects[i], &updates[i] ); /* Simply fill the background. */ dfb_gfxcard_fillrectangles( rects, num, 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) { for (i=0; i<num; i++) { DFBRectangle dst = DFB_RECTANGLE_INIT_FROM_REGION( &updates[i] ); /* Simple blit for 100% fitting background image. */ dfb_gfxcard_blit( &dst, dst.x, dst.y, state ); } } else { DFBRegion clip = state->clip; for (i=0; i<num; i++) { DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h }; DFBRectangle dst = { 0, 0, stack->width, stack->height }; /* Change clipping region. */ dfb_state_set_clip( state, &updates[i] ); /* Stretch blit for non fitting background images. */ dfb_gfxcard_stretchblit( &src, &dst, state ); } /* Restore clipping region. */ dfb_state_set_clip( state, &clip ); } /* Reset blitting source. */ state->source = NULL; state->modified |= SMF_SOURCE; break; } case DLBM_TILE: { CoreSurface *bg = stack->bg.image; DFBRegion clip = state->clip; /* Set blitting source. */ state->source = bg; state->modified |= SMF_SOURCE; /* Set blitting flags. */ dfb_state_set_blitting_flags( state, DSBLIT_NOFX ); for (i=0; i<num; i++) { DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h }; /* Change clipping region. */ dfb_state_set_clip( state, &updates[i] ); /* Tiled blit (aligned). */ dfb_gfxcard_tileblit( &src, 0, 0, stack->width, stack->height, state ); } /* Restore clipping region. */ dfb_state_set_clip( state, &clip ); /* Reset blitting source. */ state->source = NULL; state->modified |= SMF_SOURCE; break; } case DLBM_DONTCARE: break; default: D_BUG( "unknown background mode" ); break; } }
static void draw_window( SaWManTier *tier, SaWManWindow *sawwin, SaWManWindow *sawwin2, CardState *state, DFBRegion *region, bool alpha_channel, bool right_eye ) { SaWMan *sawman; CoreWindow *window; DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; DFBRectangle dst; DFBRectangle src; DFBRegion clip; DFBRegion old_clip; int offset; D_MAGIC_ASSERT( sawwin, SaWManWindow ); D_MAGIC_ASSERT( state, CardState ); DFB_REGION_ASSERT( region ); sawman = sawwin->sawman; 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 ) ); if (window->config.options & DWOP_STEREO_SIDE_BY_SIDE_HALF) { src.x /= 2; src.w /= 2; if (right_eye) src.x += window->surface->config.size.w / 2; } /* Modify dst for stereo offset. */ offset = window->config.z; offset *= right_eye ? -1 : 1; dfb_rectangle_translate( &dst, offset, 0 ); /* Setup clipping region. */ clip = *region; if (!dfb_region_rectangle_intersect( &clip, &dst )) return; sawman_dispatch_blit( sawman, sawwin, right_eye, &sawwin->src, &dst, &clip ); if (sawwin2) sawman_dispatch_blit( sawman, sawwin2, right_eye, &sawwin2->src, &dst, &clip ); /* 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; if (window->surface->config.caps & DSCAPS_PREMULTIPLIED) { /* Need to premultiply source with Ac? */ flags |= DSBLIT_SRC_PREMULTCOLOR; dfb_state_set_src_blend( state, DSBF_ONE ); } else dfb_state_set_src_blend( state, DSBF_SRCALPHA ); /* Set opacity as blending factor. */ if (state->color.a != window->config.opacity) { state->color.a = window->config.opacity; state->modified |= SMF_COLOR; } } /* if we specified some kind of color, we will colorise. no DWCAPS_COLOR here. */ if (window->config.color.a != 0) { DFBColor c; flags |= DSBLIT_COLORIZE; c = window->config.color; c.a = state->color.a; if (! DFB_COLOR_EQUAL( c, state->color )) { state->color = c; 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) 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->from_eye = (right_eye && (sawwin->caps & DWCAPS_STEREO)) ? DSSE_RIGHT : DSSE_LEFT; state->modified |= SMF_SOURCE | SMF_FROM; 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 ) ); #ifndef OLD_COREWINDOWS_STRUCTURE if (sawwin2) { CoreWindow *window2; DFBRectangle *src2; DFBPoint p1,p2,p; D_MAGIC_ASSERT( sawwin2, SaWManWindow ); window2 = sawwin2->window; D_ASSERT( window2 != NULL ); D_ASSERT( window2->surface != NULL ); src2 = &sawwin2->src; state->source2 = window2->surface; state->modified = SMF_SOURCE2; p1.x = src2->x + (sawwin->dst.x - sawwin2->dst.x); p1.y = src2->y + (sawwin->dst.y - sawwin2->dst.y); p2.x = sawwin->dst.x; p2.y = sawwin->dst.y; p.x = p1.x; p.y = p1.y; p1.x = src.x; p1.y = src.y; src.x = p.x; src.y = p.y; CoreGraphicsStateClient_Blit2( state->client, &src, &p2, &p1, 1 ); } else #endif { /* Scale window to the screen clipped by the region being updated. */ CoreGraphicsStateClient_StretchBlit( state->client, &src, &dst, 1 ); } /* Restore clipping region. */ dfb_state_set_clip( state, &old_clip ); }
static void draw_border( SaWManWindow *sawwin, CardState *state, const DFBRegion *region, int thickness, bool right_eye ) { 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; int offset; 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; /* Translate for stereo effect. */ offset = window->config.z; offset *= right_eye ? -1 : 1; dfb_rectangle_translate( &rects[0], offset, 0 ); for (i=1; i<thickness; i++) { rects[i].x = rects[i-1].x + 1; rects[i].y = rects[i-1].y + 1; rects[i].w = rects[i-1].w - 2; rects[i].h = rects[i-1].h - 2; } /* Save clipping region. */ old_clip = state->clip; /* 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; i<thickness; i++) { dfb_state_set_color_or_index( state, &colors[i*num_colors/thickness], indices[i*num_indices/thickness] ); CoreGraphicsStateClient_DrawRectangles( state->client, &rects[i], 1 ); } /* Restore clipping region. */ dfb_state_set_clip( state, &old_clip ); }
void sawman_draw_cursor ( CoreWindowStack *stack, CardState *state, CoreSurface *surface, 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; D_DEBUG_AT( SaWMan_Draw, " -> cursor surface %p\n", stack->cursor.surface ); /* 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; /* Set destination. */ if (surface) { state->destination = surface; state->modified |= SMF_DESTINATION; } /* Use global alpha blending. */ if (stack->cursor.opacity != 0xFF) { flags |= DSBLIT_BLEND_COLORALPHA; if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) { /* Need to premultiply source with Ac? */ flags |= DSBLIT_SRC_PREMULTCOLOR; dfb_state_set_src_blend( state, DSBF_ONE ); } else dfb_state_set_src_blend( state, DSBF_SRCALPHA ); /* 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->from_eye = DSSE_LEFT; state->modified |= SMF_SOURCE | SMF_FROM; /* Set clipping region. */ dfb_state_set_clip( state, region ); /* Blit from the window to the region being updated. */ DFBPoint point = { region->x1, region->y1 }; D_DEBUG_AT( SaWMan_Draw, " -> client %p\n", state->client ); CoreGraphicsStateClient_Blit( state->client, &src, &point, 1 ); /* Reset blitting source. */ state->source = NULL; state->modified |= SMF_SOURCE; /* Reset destination. */ if (surface) { state->destination = NULL; state->modified |= SMF_DESTINATION; } }
static void window_update( StretRegion *region, void *region_data, void *update_data, unsigned long arg, int x, int y, const DFBRegion *updates, int num ) { int i; DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; UniqueWindow *window = region_data; CardState *state = update_data; bool alpha = arg; bool visible; D_ASSERT( updates != NULL ); D_MAGIC_ASSERT( region, StretRegion ); D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT( state, CardState ); D_ASSERT( window->surface != NULL ); visible = D_FLAGS_IS_SET( window->flags, UWF_VISIBLE ); D_DEBUG_AT( UniQuE_Window, "window_update( region %p, window %p, visible %s, num %d )\n", region, window, visible ? "yes" : "no", num ); #if D_DEBUG_ENABLED for (i=0; i<num; i++) { D_DEBUG_AT( UniQuE_Window, " (%d) %4d,%4d - %4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION( &updates[i] ) ); } #endif if (!visible) return; /* Use per pixel alpha blending. */ if (alpha && (window->options & DWOP_ALPHACHANNEL)) flags |= DSBLIT_BLEND_ALPHACHANNEL; /* Use global alpha blending. */ if (window->opacity != 0xFF) { flags |= DSBLIT_BLEND_COLORALPHA; /* Set opacity as blending factor. */ if (state->color.a != window->opacity) { state->color.a = window->opacity; state->modified |= SMF_COLOR; } } /* Use source color keying. */ if (window->options & DWOP_COLORKEYING) { flags |= DSBLIT_SRC_COLORKEY; /* Set window color key. */ dfb_state_set_src_colorkey( state, window->color_key ); } /* Use automatic deinterlacing. */ if (window->surface->config.caps & DSCAPS_INTERLACED) flags |= DSBLIT_DEINTERLACE; /* Set blitting flags. */ dfb_state_set_blitting_flags( state, flags ); /* Set blitting source. */ state->source = window->surface; state->modified |= SMF_SOURCE; for (i=0; i<num; i++) { DFBRectangle src = DFB_RECTANGLE_INIT_FROM_REGION( &updates[i] ); /* Blit from the window to the region being updated. */ dfb_gfxcard_blit( &src, x + src.x, y + src.y, state ); } /* Reset blitting source. */ state->source = NULL; state->modified |= SMF_SOURCE; }
DFBResult dfb_layer_region_flip_update( CoreLayerRegion *region, const DFBRegion *update, DFBSurfaceFlipFlags flags ) { DFBResult ret = DFB_OK; DFBRegion rotated; CoreLayer *layer; CoreLayerContext *context; CoreSurface *surface; const DisplayLayerFuncs *funcs; if (update) D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x ) <- [%d, %d - %dx%d]\n", region, update, flags, DFB_RECTANGLE_VALS_FROM_REGION( update ) ); else D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x )\n", region, update, flags ); D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); /* Lock the region. */ if (dfb_layer_region_lock( region )) return DFB_FUSION; D_ASSUME( region->surface != NULL ); /* Check for NULL surface. */ if (!region->surface) { D_DEBUG_AT( Core_Layers, " -> No surface => no update!\n" ); dfb_layer_region_unlock( region ); return DFB_UNSUPPORTED; } context = region->context; surface = region->surface; layer = dfb_layer_at( context->layer_id ); D_ASSERT( layer->funcs != NULL ); funcs = layer->funcs; /* Unfreeze region? */ if (D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) { D_FLAGS_CLEAR( region->state, CLRSF_FROZEN ); if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { ret = set_region( region, ®ion->config, CLRCF_ALL, surface ); if (ret) D_DERROR( ret, "Core/LayerRegion: set_region() in dfb_layer_region_flip_update() failed!\n" ); } else if (D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) { ret = realize_region( region ); if (ret) D_DERROR( ret, "Core/LayerRegion: realize_region() in dfb_layer_region_flip_update() failed!\n" ); } if (ret) { dfb_layer_region_unlock( region ); return ret; } } /* Depending on the buffer mode... */ switch (region->config.buffermode) { case DLBM_TRIPLE: case DLBM_BACKVIDEO: /* Check if simply swapping the buffers is possible... */ if (!(flags & DSFLIP_BLIT) && !surface->rotation && (!update || (update->x1 == 0 && update->y1 == 0 && update->x2 == surface->config.size.w - 1 && update->y2 == surface->config.size.h - 1))) { D_DEBUG_AT( Core_Layers, " -> Going to swap buffers...\n" ); /* Use the driver's routine if the region is realized. */ if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { D_ASSUME( funcs->FlipRegion != NULL ); ret = region_buffer_lock( region, surface, CSBR_BACK ); if (ret) { dfb_layer_region_unlock( region ); return ret; } D_DEBUG_AT( Core_Layers, " -> Flipping region using driver...\n" ); if (funcs->FlipRegion) ret = funcs->FlipRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, flags, ®ion->surface_lock ); dfb_surface_unlock( surface ); } else { D_DEBUG_AT( Core_Layers, " -> Flipping region not using driver...\n" ); /* Just do the hardware independent work. */ dfb_surface_lock( surface ); dfb_surface_flip( surface, false ); dfb_surface_unlock( surface ); } break; } /* fall through */ case DLBM_BACKSYSTEM: D_DEBUG_AT( Core_Layers, " -> Going to copy portion...\n" ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } D_DEBUG_AT( Core_Layers, " -> Copying content from back to front buffer...\n" ); /* ...or copy updated contents from back to front buffer. */ dfb_back_to_front_copy_rotation( surface, update, surface->rotation ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } /* fall through */ case DLBM_FRONTONLY: /* Tell the driver about the update if the region is realized. */ if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { if (surface) { CoreSurfaceAllocation *allocation; allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ if (!(flags & DSFLIP_PIPELINE)) dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; } dfb_surface_lock( surface ); dfb_surface_allocation_update( allocation, CSAF_READ ); dfb_surface_unlock( surface ); } D_DEBUG_AT( Core_Layers, " -> Notifying driver about updated content...\n" ); dfb_region_from_rotated( &rotated, update, &surface->config.size, surface->rotation ); ret = funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, &rotated, ®ion->surface_lock ); } break; default: D_BUG("unknown buffer mode"); ret = DFB_BUG; } D_DEBUG_AT( Core_Layers, " -> done.\n" ); /* Unlock the region. */ dfb_layer_region_unlock( region ); return ret; }
void GP2DEngine::validate_DEST_CLIP( GP2DTask *mytask, CardState *state ) { __u32 *prep = mytask->start( 18 ); D_DEBUG_AT( GP2D_Engine, "%s( %p [%d] - %4d,%4d-%4dx%4d )\n", __FUNCTION__, state->dst.handle, state->dst.pitch, DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ) ); prep[0] = GP2D_OPCODE_WPR; prep[1] = 0x0d4; prep[2] = GP2D_XY( state->clip.x1, state->clip.y1 ) ; prep[3] = GP2D_OPCODE_WPR; prep[4] = 0x0d8; prep[5] = GP2D_XY( state->clip.x2, state->clip.y2) ; if (mytask->v_flags & DEST) { mytask->submit( 6 ); } else { CoreSurface *surface = state->destination; CoreSurfaceBuffer *buffer = state->dst.buffer; mytask->dst_phys = (unsigned long) state->dst.handle; mytask->dst_pitch = state->dst.pitch; mytask->dst_bpp = DFB_BYTES_PER_PIXEL( buffer->format ); mytask->dst_index = DFB_PIXELFORMAT_INDEX( buffer->format ) % DFB_NUM_PIXELFORMATS; mytask->rclr &= ~0x00140000; switch (buffer->format) { case DSPF_RGB16: mytask->rclr |= 0x00040000; break; case DSPF_ARGB1555: mytask->rclr |= 0x00140000; break; default: D_BUG("Unexpected pixelformat\n"); return; } /* Set destination start address. */ prep[ 6] = GP2D_OPCODE_WPR; prep[ 7] = 0x50; prep[ 8] = mytask->dst_phys; /* Set destination stride. */ prep[ 9] = GP2D_OPCODE_WPR; prep[10] = 0x5c; prep[11] = mytask->dst_pitch / mytask->dst_bpp; /* Set destination pixelformat in rendering control. */ prep[12] = GP2D_OPCODE_WPR; prep[13] = 0xc0; prep[14] = mytask->rclr; /* Set system clipping rectangle. */ prep[15] = GP2D_OPCODE_WPR; prep[16] = 0xd0; prep[17] = GP2D_XY( surface->config.size.w - 1, surface->config.size.h - 1 ); mytask->submit( 18 ); } /* Set the flags. */ GP2D_VALIDATE( DEST_CLIP ); }