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; }
bool dfb_unsafe_region_rectangle_intersect( DFBRegion *region, const DFBRectangle *rect ) { 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_rectangle_intersect( region, rect ); }
static bool stretch_hvx( CardState *state, DFBRectangle *srect, DFBRectangle *drect ) { GenefxState *gfxs; const StretchFunctionTable *table; StretchHVx stretch; bool down = false; void *dst; void *src; StretchCtx ctx; int idx = STRETCH_NONE; u32 colors[256]; D_ASSERT( state != NULL ); DFB_RECTANGLE_ASSERT( srect ); DFB_RECTANGLE_ASSERT( drect ); gfxs = state->gfxs; if (srect->w > drect->w && srect->h > drect->h) down = true; if (down) { if (!(state->render_options & DSRO_SMOOTH_DOWNSCALE)) return false; } else { if (!(state->render_options & DSRO_SMOOTH_UPSCALE)) return false; } switch (gfxs->dst_format) { case DSPF_NV12: case DSPF_NV21: return stretch_hvx_planar( state, srect, drect, down ); default: break; } if (state->blittingflags & ~(DSBLIT_COLORKEY_PROTECT | DSBLIT_SRC_COLORKEY | DSBLIT_SRC_PREMULTIPLY)) return false; if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY && !DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format )) return false; if (DFB_PIXELFORMAT_INDEX(gfxs->dst_format) >= D_ARRAY_SIZE(stretch_tables)) return false; if (DFB_PIXELFORMAT_INDEX(gfxs->src_format) >= D_ARRAY_SIZE((stretch_tables[0])->f)) return false; table = stretch_tables[DFB_PIXELFORMAT_INDEX(gfxs->dst_format)]; if (!table) return false; if (state->blittingflags & DSBLIT_SRC_COLORKEY) idx |= STRETCH_SRCKEY; if (state->blittingflags & DSBLIT_COLORKEY_PROTECT) idx |= STRETCH_PROTECT; if (down) stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].down[idx]; else stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].up[idx]; if (!stretch) return false; ctx.clip = state->clip; if (!dfb_region_rectangle_intersect( &ctx.clip, drect )) return false; dfb_region_translate( &ctx.clip, - drect->x, - drect->y ); if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format )) { int i; const DFBColor *entries; u16 *colors16 = (void*) colors; D_ASSERT( gfxs->Blut != NULL ); entries = gfxs->Blut->entries; switch (gfxs->dst_format) { case DSPF_ARGB: if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) { for (i=0; i<gfxs->Blut->num_entries; i++) { int alpha = entries[i].a + 1; switch (alpha) { case 0: colors[i] = 0; break; case 255: colors[i] = PIXEL_ARGB( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); break; default: colors[i] = PIXEL_ARGB( entries[i].a, (alpha * entries[i].r) >> 8, (alpha * entries[i].g) >> 8, (alpha * entries[i].b) >> 8 ); } } } else { for (i=0; i<gfxs->Blut->num_entries; i++) colors[i] = PIXEL_ARGB( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); } break; case DSPF_RGB32: for (i=0; i<gfxs->Blut->num_entries; i++) colors[i] = PIXEL_RGB32( entries[i].r, entries[i].g, entries[i].b ); break; case DSPF_RGB16: for (i=0; i<gfxs->Blut->num_entries; i++) colors16[i] = PIXEL_RGB16( entries[i].r, entries[i].g, entries[i].b ); break; case DSPF_ARGB4444: if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) { for (i=0; i<gfxs->Blut->num_entries; i++) { int alpha = entries[i].a + 1; switch (alpha) { case 0: colors16[i] = 0; break; case 255: colors16[i] = PIXEL_ARGB4444( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); break; default: colors16[i] = PIXEL_ARGB4444( entries[i].a, (alpha * entries[i].r) >> 8, (alpha * entries[i].g) >> 8, (alpha * entries[i].b) >> 8 ); } } } else { for (i=0; i<gfxs->Blut->num_entries; i++)
static bool stretch_hvx_planar( CardState *state, DFBRectangle *srect, DFBRectangle *drect, bool down ) { GenefxState *gfxs; void *dst; void *src; DFBRegion clip; D_ASSERT( state != NULL ); DFB_RECTANGLE_ASSERT( srect ); DFB_RECTANGLE_ASSERT( drect ); gfxs = state->gfxs; if (state->blittingflags) return false; if (gfxs->dst_format != gfxs->src_format) return false; clip = state->clip; if (!dfb_region_rectangle_intersect( &clip, drect )) return false; dfb_region_translate( &clip, - drect->x, - drect->y ); dst = gfxs->dst_org[0] + drect->y * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x ); src = gfxs->src_org[0] + srect->y * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x ); switch (gfxs->dst_format) { case DSPF_NV12: case DSPF_NV21: if (down) stretch_hvx_8_down( dst, gfxs->dst_pitch, src, gfxs->src_pitch, srect->w, srect->h, drect->w, drect->h, &clip ); else stretch_hvx_8_up( dst, gfxs->dst_pitch, src, gfxs->src_pitch, srect->w, srect->h, drect->w, drect->h, &clip ); clip.x1 /= 2; clip.x2 /= 2; clip.y1 /= 2; clip.y2 /= 2; dst = gfxs->dst_org[1] + drect->y/2 * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x ); src = gfxs->src_org[1] + srect->y/2 * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x ); if (down) stretch_hvx_88_down( dst, gfxs->dst_pitch, src, gfxs->src_pitch, srect->w/2, srect->h, drect->w/2, drect->h, &clip ); else stretch_hvx_88_up( dst, gfxs->dst_pitch, src, gfxs->src_pitch, srect->w/2, srect->h, drect->w/2, drect->h, &clip ); break; default: break; } return true; }
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 ); }