bool dfb_unsafe_region_intersect( DFBRegion *region, int x1, int y1, int x2, int y2 ) { if (region->x1 > region->x2) { int temp = region->x1; region->x1 = region->x2; region->x2 = temp; } if (region->y1 > region->y2) { int temp = region->y1; region->y1 = region->y2; region->y2 = temp; } return dfb_region_intersect( region, x1, y1, x2, y2 ); }
static void repaint_stack( CoreWindowStack *stack, DFBRegion *region, DFBSurfaceFlipFlags flags ) { DisplayLayer *layer = dfb_layer_at( stack->layer_id ); CoreSurface *surface = dfb_layer_surface( layer ); CardState *state = dfb_layer_state( layer ); if (!dfb_region_intersect( region, 0, 0, surface->width - 1, surface->height - 1 )) return; if (dfb_layer_lease( layer )) return; state->clip = *region; state->modified |= SMF_CLIP; update_region( stack, state, stack->num_windows - 1, region->x1, region->y1, region->x2, region->y2 ); if (surface->caps & DSCAPS_FLIPPING) { if (region->x1 == 0 && region->y1 == 0 && region->x2 == surface->width - 1 && region->y2 == surface->height - 1 && 0) { dfb_layer_flip_buffers( layer, flags ); } else { DFBRectangle rect = { region->x1, region->y1, region->x2 - region->x1 + 1, region->y2 - region->y1 + 1 }; if (flags & DSFLIP_WAITFORSYNC) dfb_fbdev_wait_vsync(); dfb_back_to_front_copy( surface, &rect ); } } dfb_layer_release( layer, false ); }
/* HACK: implementation dumped in here for now, will move into context */ static DFBResult wm_update_cursor( CoreWindowStack *stack, void *wm_data, void *stack_data, CoreCursorUpdateFlags flags ) { DFBResult ret; DFBRegion old_region; WMData *wmdata = wm_data; StackData *data = stack_data; bool restored = false; CoreLayer *layer; CoreLayerRegion *region; CardState *state; CoreSurface *surface; UniqueContext *context; D_ASSERT( stack != NULL ); D_ASSERT( stack->context != NULL ); D_ASSERT( wm_data != NULL ); D_ASSERT( stack_data != NULL ); D_MAGIC_ASSERT( data, StackData ); context = data->context; D_MAGIC_ASSERT( context, UniqueContext ); /* Optimize case of invisible cursor moving. */ if (!(flags & ~(CCUF_POSITION | CCUF_SHAPE)) && (!stack->cursor.opacity || !stack->cursor.enabled)) { context->cursor_bs_valid = false; return DFB_OK; } layer = dfb_layer_at( context->layer_id ); state = &layer->state; region = context->region; surface = context->surface; D_ASSERT( region != NULL ); D_ASSERT( surface != NULL ); if (flags & CCUF_ENABLE) { CoreSurface *cursor_bs; DFBSurfaceCapabilities caps = DSCAPS_NONE; dfb_surface_caps_apply_policy( stack->cursor.policy, &caps ); D_ASSERT( context->cursor_bs == NULL ); /* Create the cursor backing store surface. */ ret = dfb_surface_create_simple( wmdata->core, stack->cursor.size.w, stack->cursor.size.h, region->config.format, region->config.colorspace, caps, CSTF_SHARED | CSTF_CURSOR, 0, /* FIXME: no shared cursor objects, no cursor id */ NULL, &cursor_bs ); if (ret) { D_ERROR( "WM/Default: Failed creating backing store for cursor!\n" ); return ret; } ret = dfb_surface_globalize( cursor_bs ); D_ASSERT( ret == DFB_OK ); /* Ensure valid back buffer for now. * FIXME: Keep a flag to know when back/front have been swapped and need a sync. */ switch (region->config.buffermode) { case DLBM_BACKVIDEO: case DLBM_TRIPLE: dfb_gfx_copy( surface, surface, NULL ); break; default: break; } context->cursor_bs = cursor_bs; } else { D_ASSERT( context->cursor_bs != NULL ); /* restore region under cursor */ if (context->cursor_drawn) { DFBRectangle rect = { 0, 0, context->cursor_region.x2 - context->cursor_region.x1 + 1, context->cursor_region.y2 - context->cursor_region.y1 + 1 }; D_ASSERT( stack->cursor.opacity || (flags & CCUF_OPACITY) ); D_ASSERT( context->cursor_bs_valid ); dfb_gfx_copy_to( context->cursor_bs, surface, &rect, context->cursor_region.x1, context->cursor_region.y1, false ); context->cursor_drawn = false; old_region = context->cursor_region; restored = true; } if (flags & CCUF_SIZE) { ret = dfb_surface_reformat( context->cursor_bs, stack->cursor.size.w, stack->cursor.size.h, context->cursor_bs->config.format ); if (ret) { D_ERROR( "WM/Default: Failed resizing backing store for cursor!\n" ); return ret; } } } if (flags & (CCUF_ENABLE | CCUF_POSITION | CCUF_SIZE | CCUF_OPACITY)) { context->cursor_bs_valid = false; context->cursor_region.x1 = stack->cursor.x - stack->cursor.hot.x; context->cursor_region.y1 = stack->cursor.y - stack->cursor.hot.y; context->cursor_region.x2 = context->cursor_region.x1 + stack->cursor.size.w - 1; context->cursor_region.y2 = context->cursor_region.y1 + stack->cursor.size.h - 1; if (!dfb_region_intersect( &context->cursor_region, 0, 0, stack->width - 1, stack->height - 1 )) { D_BUG( "invalid cursor region" ); return DFB_BUG; } } D_ASSERT( context->cursor_bs != NULL ); if (flags & CCUF_DISABLE) { dfb_surface_unlink( &context->cursor_bs ); } else if (stack->cursor.opacity) { /* backup region under cursor */ if (!context->cursor_bs_valid) { DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &context->cursor_region ); D_ASSERT( !context->cursor_drawn ); /* FIXME: this requires using blitted flipping all the time, but fixing it seems impossible, for now DSFLIP_BLIT is forced in repaint_stack() when the cursor is enabled. */ dfb_gfx_copy_to( surface, context->cursor_bs, &rect, 0, 0, true ); context->cursor_bs_valid = true; } /* Set destination. */ state->destination = surface; state->modified |= SMF_DESTINATION; /* Set clipping region. */ dfb_state_set_clip( state, &context->cursor_region ); /* draw cursor */ unique_draw_cursor( stack, context, state, &context->cursor_region ); /* Reset destination. */ state->destination = NULL; state->modified |= SMF_DESTINATION; context->cursor_drawn = true; if (restored) { if (dfb_region_region_intersects( &old_region, &context->cursor_region )) dfb_region_region_union( &old_region, &context->cursor_region ); else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); } else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); } else if (restored) dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); return DFB_OK; }
static void update_region( CoreWindowStack *stack, CardState *state, int start, int x1, int y1, int x2, int y2 ) { int i = start; DFBRegion region = { x1, y1, x2, y2 }; /* check for empty region */ DFB_ASSERT (x1 <= x2 && y1 <= y2); while (i >= 0) { if (VISIBLE_WINDOW(stack->windows[i])) { int wx2 = stack->windows[i]->x + stack->windows[i]->width - 1; int wy2 = stack->windows[i]->y + stack->windows[i]->height - 1; if (dfb_region_intersect( ®ion, stack->windows[i]->x, stack->windows[i]->y, wx2, wy2 )) break; } i--; } if (i >= 0) { if (TRANSLUCENT_WINDOW(stack->windows[i])) update_region( stack, state, i-1, x1, y1, x2, y2 ); else { /* left */ if (region.x1 != x1) update_region( stack, state, i-1, x1, region.y1, region.x1-1, region.y2 ); /* upper */ if (region.y1 != y1) update_region( stack, state, i-1, x1, y1, x2, region.y1-1 ); /* right */ if (region.x2 != x2) update_region( stack, state, i-1, region.x2+1, region.y1, x2, region.y2 ); /* lower */ if (region.y2 != y2) update_region( stack, state, i-1, x1, region.y2+1, x2, y2 ); } { CoreWindow *window = stack->windows[i]; DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; DFBRectangle srect = { region.x1 - window->x, region.y1 - window->y, region.x2 - region.x1 + 1, region.y2 - region.y1 + 1 }; if (window->options & DWOP_ALPHACHANNEL) flags |= DSBLIT_BLEND_ALPHACHANNEL; if (window->opacity != 0xFF) { flags |= DSBLIT_BLEND_COLORALPHA; if (state->color.a != window->opacity) { state->color.a = window->opacity; state->modified |= SMF_COLOR; } } if (window->options & DWOP_COLORKEYING) { flags |= DSBLIT_SRC_COLORKEY; if (state->src_colorkey != window->color_key) { state->src_colorkey = window->color_key; state->modified |= SMF_SRC_COLORKEY; } } if (state->blittingflags != flags) { state->blittingflags = flags; state->modified |= SMF_BLITTING_FLAGS; } state->source = window->surface; state->modified |= SMF_SOURCE; dfb_gfxcard_blit( &srect, region.x1, region.y1, state ); state->source = NULL; } } else { switch (stack->bg.mode) { case DLBM_COLOR: { DFBRectangle rect = { x1, y1, x2 - x1 + 1, y2 - y1 + 1 }; state->color = stack->bg.color; state->modified |= SMF_COLOR; dfb_gfxcard_fillrectangle( &rect, state ); break; } case DLBM_IMAGE: { DFBRectangle rect = { x1, y1, x2 - x1 + 1, y2 - y1 + 1 }; if (state->blittingflags != DSBLIT_NOFX) { state->blittingflags = DSBLIT_NOFX; state->modified |= SMF_BLITTING_FLAGS; } state->source = stack->bg.image; state->modified |= SMF_SOURCE; dfb_gfxcard_blit( &rect, x1, y1, state ); state->source = NULL; break; } case DLBM_TILE: { DFBRectangle rect = { 0, 0, stack->bg.image->width, stack->bg.image->height }; if (state->blittingflags != DSBLIT_NOFX) { state->blittingflags = DSBLIT_NOFX; state->modified |= SMF_BLITTING_FLAGS; } state->source = stack->bg.image; state->modified |= SMF_SOURCE; dfb_gfxcard_tileblit( &rect, (x1 / rect.w) * rect.w, (y1 / rect.h) * rect.h, (x2 / rect.w + 1) * rect.w, (y2 / rect.h + 1) * rect.h, state ); state->source = NULL; break; } default: ; } } }