void dfb_state_update_sources( CardState *state, CardStateFlags flags ) { D_DEBUG_AT( Core_GfxState, "%s( %p )\n", __FUNCTION__, state ); D_MAGIC_ASSERT( state, CardState ); DFB_REGION_ASSERT( &state->clip ); if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE )) { CoreSurface *source = state->source; D_ASSERT( source != NULL ); if (direct_serial_update( &state->src_serial, &source->serial )) state->modified |= SMF_SOURCE; } if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE_MASK )) { CoreSurface *source_mask = state->source_mask; D_ASSERT( source_mask != NULL ); if (direct_serial_update( &state->src_mask_serial, &source_mask->serial )) state->modified |= SMF_SOURCE_MASK; } if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE2 )) { CoreSurface *source2 = state->source2; D_ASSERT( source2 != NULL ); if (direct_serial_update( &state->src2_serial, &source2->serial )) state->modified |= SMF_SOURCE2; } }
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]) ); } }
void dfb_state_update_destination( CardState *state ) { CoreSurface *destination; D_DEBUG_AT( Core_GfxState, "%s( %p )\n", __FUNCTION__, state ); D_MAGIC_ASSERT( state, CardState ); DFB_REGION_ASSERT( &state->clip ); destination = state->destination; if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) { D_DEBUG_AT( Core_GfxState, " -> CSF_DESTINATION is set\n" ); D_ASSERT( destination != NULL ); if (direct_serial_update( &state->dst_serial, &destination->serial )) { D_DEBUG_AT( Core_GfxState, " -> serial is updated\n" ); validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); state->modified |= SMF_DESTINATION; } } else if (destination) validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); }
void dfb_gfx_copy_regions_stereo( CoreSurface *source, CoreSurfaceBufferRole from, DFBSurfaceStereoEye source_eye, CoreSurface *destination, CoreSurfaceBufferRole to, DFBSurfaceStereoEye destination_eye, const DFBRegion *regions, unsigned int num, int x, int y ) { unsigned int i, n = 0; DFBRectangle rect = { 0, 0, source->config.size.w, source->config.size.h }; DFBRectangle rects[num]; DFBPoint points[num]; D_ASSERT( !dfb_config->task_manager ); for (i=0; i<num; i++) { DFB_REGION_ASSERT( ®ions[i] ); rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( ®ions[i] ); if (dfb_rectangle_intersect( &rects[n], &rect )) { points[n].x = x + rects[n].x - rect.x; points[n].y = y + rects[n].y - rect.y; n++; } } if (n > 0) { StateClient *client = state_client_tls.Get(); D_FLAGS_SET( client->state.modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO ); client->state.clip.x2 = destination->config.size.w - 1; client->state.clip.y2 = destination->config.size.h - 1; client->state.source = source; client->state.destination = destination; client->state.from = from; client->state.from_eye = source_eye; client->state.to = to; client->state.to_eye = destination_eye; CoreGraphicsStateClient_Blit( &client->client, rects, points, n ); CoreGraphicsStateClient_Flush( &client->client, 0, CGSCFF_NONE ); /* Signal end of sequence. */ dfb_state_stop_drawing( &client->state ); client->state.destination = NULL; client->state.source = NULL; } }
void dfb_gfx_copy_regions( CoreSurface *source, CoreSurfaceBufferRole from, CoreSurface *destination, CoreSurfaceBufferRole to, const DFBRegion *regions, unsigned int num, int x, int y ) { unsigned int i, n = 0; DFBRectangle rect = { 0, 0, source->config.size.w, source->config.size.h }; DFBRectangle rects[num]; DFBPoint points[num]; for (i=0; i<num; i++) { DFB_REGION_ASSERT( ®ions[i] ); rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( ®ions[i] ); if (dfb_rectangle_intersect( &rects[n], &rect )) { points[n].x = x + rects[n].x - rect.x; points[n].y = y + rects[n].y - rect.y; n++; } } if (n > 0) { pthread_mutex_lock( ©_lock ); if (!copy_state_inited) { dfb_state_init( ©_state, NULL ); copy_state_inited = true; } copy_state.modified |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION; copy_state.clip.x2 = destination->config.size.w - 1; copy_state.clip.y2 = destination->config.size.h - 1; copy_state.source = source; copy_state.destination = destination; copy_state.from = from; copy_state.to = to; dfb_gfxcard_batchblit( rects, points, n, ©_state ); /* Signal end of sequence. */ dfb_state_stop_drawing( ©_state ); pthread_mutex_unlock( ©_lock ); } }
void dfb_state_update( CardState *state, bool update_sources ) { CoreSurface *destination; D_MAGIC_ASSERT( state, CardState ); DFB_REGION_ASSERT( &state->clip ); destination = state->destination; if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) { D_ASSERT( destination != NULL ); if (direct_serial_update( &state->dst_serial, &destination->serial )) { validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); state->modified |= SMF_DESTINATION; } } else if (destination) validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) { CoreSurface *source = state->source; D_ASSERT( source != NULL ); if (direct_serial_update( &state->src_serial, &source->serial )) state->modified |= SMF_SOURCE; } if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) { CoreSurface *source_mask = state->source_mask; D_ASSERT( source_mask != NULL ); if (direct_serial_update( &state->src_mask_serial, &source_mask->serial )) state->modified |= SMF_SOURCE_MASK; } if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 )) { CoreSurface *source2 = state->source2; D_ASSERT( source2 != NULL ); if (direct_serial_update( &state->src2_serial, &source2->serial )) state->modified |= SMF_SOURCE2; } }
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 ); if (updates->num_regions == 0) { updates->regions[0] = updates->bounding = *region; updates->num_regions = 1; return; } for (i=0; i<updates->num_regions; i++) { DFBRegion inter = updates->regions[i]; if (dfb_region_region_intersect( &inter, region )) { DFBRegion uni = updates->regions[i]; dfb_region_region_union( &uni, region ); updates->regions[i] = uni; dfb_region_region_union( &updates->bounding, &uni ); return; } } if (updates->num_regions == updates->max_regions) { dfb_region_region_union( &updates->bounding, region ); updates->regions[0] = updates->bounding; updates->num_regions = 1; } else { updates->regions[updates->num_regions++] = *region; dfb_region_region_union( &updates->bounding, region ); } }
static DFBResult dfb_x11_update_screen( DFBX11 *x11, const DFBRegion *region, CoreSurfaceBufferLock *lock ) { int ret; DFBX11Shared *shared = x11->shared; DFB_REGION_ASSERT( region ); D_ASSERT( lock != NULL ); /* FIXME: Just a hot fix! */ while (shared->update.lock) usleep( 10000 ); shared->update.region = *region; shared->update.lock = lock; if (fusion_call_execute( &shared->call, FCEF_NONE, X11_UPDATE_SCREEN, &shared->update, &ret )) return DFB_FUSION; return ret; }
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; }
static DFBResult wm_update_stack( CoreWindowStack *stack, void *wm_data, void *stack_data, const DFBRegion *region, DFBSurfaceFlipFlags flags ) { StackData *data = stack_data; D_ASSERT( stack != NULL ); D_ASSERT( wm_data != NULL ); D_ASSERT( stack_data != NULL ); DFB_REGION_ASSERT( region ); D_MAGIC_ASSERT( data, StackData ); if (!data->context) return DFB_DESTROYED; return unique_context_update( data->context, region, 1, flags ); }
void dfb_gfx_copy_regions_client( CoreSurface *source, CoreSurfaceBufferRole from, DFBSurfaceStereoEye source_eye, CoreSurface *destination, CoreSurfaceBufferRole to, DFBSurfaceStereoEye destination_eye, const DFBRegion *regions, unsigned int num, int x, int y, CoreGraphicsStateClient *_client ) { unsigned int i, n = 0; DFBRectangle rect = { 0, 0, source->config.size.w, source->config.size.h }; DFBRectangle rects[num]; DFBPoint points[num]; CoreGraphicsStateClient *client = _client ? _client : &state_client_tls.Get()->client; CardState *state = client->state; CardState backup; for (i=0; i<num; i++) { DFB_REGION_ASSERT( ®ions[i] ); rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( ®ions[i] ); if (dfb_rectangle_intersect( &rects[n], &rect )) { points[n].x = x + rects[n].x; points[n].y = y + rects[n].y; n++; } } if (n > 0) { backup.clip = state->clip; backup.source = state->source; backup.destination = state->destination; backup.from = state->from; backup.from_eye = state->from_eye; backup.to = state->to; backup.to_eye = state->to_eye; backup.blittingflags = state->blittingflags; D_FLAGS_SET( state->modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS ); state->clip.x1 = 0; state->clip.y1 = 0; state->clip.x2 = destination->config.size.w - 1; state->clip.y2 = destination->config.size.h - 1; state->source = source; state->destination = destination; state->from = from; state->from_eye = source_eye; state->to = to; state->to_eye = destination_eye; state->blittingflags = DSBLIT_NOFX; CoreGraphicsStateClient_Blit( client, rects, points, n ); if (!_client) CoreGraphicsStateClient_Flush( client, 0, CGSCFF_NONE ); D_FLAGS_SET( state->modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS ); state->clip = backup.clip; state->source = backup.source; state->destination = backup.destination; state->from = backup.from; state->from_eye = backup.from_eye; state->to = backup.to; state->to_eye = backup.to_eye; state->blittingflags = backup.blittingflags; } }
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 ); }
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; } }