static DFBResult x11Write( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceAllocation *allocation, void *alloc_data, const void *source, int pitch, const DFBRectangle *rect ) { XImage *image; x11PoolLocalData *local = pool_local; x11AllocationData *alloc = alloc_data; DFBX11 *x11 = local->x11; D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); D_DEBUG_AT( X11_Surfaces, " -> allocation: %s\n", ToString_CoreSurfaceAllocation( allocation ) ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); D_ASSERT( source != NULL ); D_ASSERT( pitch >= 0 ); DFB_RECTANGLE_ASSERT( rect ); D_DEBUG_AT( X11_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); XLockDisplay( x11->display ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); image = XCreateImage( x11->display, alloc->visual, alloc->depth, ZPixmap, 0, (void*) source, rect->w, rect->h, 32, pitch ); if (!image) { D_ERROR( "X11/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth ); XUnlockDisplay( x11->display ); return DFB_FAILURE; } x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); // dfb_surface_buffer_dump_type_locked2( allocation->buffer, ".", "x11Write", false, image->data, image->bytes_per_line ); XPutImage( x11->display, alloc->xid, alloc->gc, image, 0, 0, rect->x, rect->y, rect->w, rect->h ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */ image->data = NULL; XDestroyImage( image ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); XUnlockDisplay( x11->display ); return DFB_OK; }
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 DFBResult x11Read( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceAllocation *allocation, void *alloc_data, void *destination, int pitch, const DFBRectangle *rect ) { XImage *image; XImage *sub; x11PoolLocalData *local = pool_local; x11AllocationData *alloc = alloc_data; DFBX11 *x11 = local->x11; D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); D_DEBUG_AT( X11_Surfaces, " -> allocation: %s\n", ToString_CoreSurfaceAllocation( allocation ) ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); D_ASSERT( destination != NULL ); D_ASSERT( pitch >= 0 ); DFB_RECTANGLE_ASSERT( rect ); D_DEBUG_AT( X11_Surfaces, " => %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); XLockDisplay( x11->display ); #if 1 image = XCreateImage( x11->display, alloc->visual, alloc->depth, ZPixmap, 0, destination, rect->w, rect->h, 32, pitch ); if (!image) { D_ERROR( "X11/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth ); XUnlockDisplay( x11->display ); return DFB_FAILURE; } sub = XGetSubImage( x11->display, alloc->xid, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap, image, 0, 0 ); #else image = XGetImage( x11->display, alloc->window ? alloc->window : alloc->xid, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap ); #endif if (image) { // dfb_surface_buffer_dump_type_locked2( allocation->buffer, ".", "x11Read", false, image->data, image->bytes_per_line ); /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */ image->data = NULL; XDestroyImage( image ); } XUnlockDisplay( x11->display ); #if 1 if (!sub) { D_ERROR( "X11/Surfaces: XGetSubImage( %d,%d-%dx%d ) failed!\n", DFB_RECTANGLE_VALS(rect) ); return DFB_FAILURE; } #endif return DFB_OK; }
static DFBResult update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *lock, XWindow *xw ) { void *dst; void *src; unsigned int offset = 0; XImage *ximage; CoreSurface *surface; CoreSurfaceAllocation *allocation; DFBX11Shared *shared; DFBRectangle rect; bool direct = false; D_ASSERT( x11 != NULL ); DFB_RECTANGLE_ASSERT( clip ); D_DEBUG_AT( X11_Update, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( clip ) ); CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); shared = x11->shared; D_ASSERT( shared != NULL ); XLockDisplay( x11->display ); if (!xw) { XUnlockDisplay( x11->display ); return DFB_OK; } allocation = lock->allocation; CORE_SURFACE_ALLOCATION_ASSERT( allocation ); surface = allocation->surface; D_ASSERT( surface != NULL ); rect.x = rect.y = 0; rect.w = xw->width; rect.h = xw->height; if (!dfb_rectangle_intersect( &rect, clip )) { XUnlockDisplay( x11->display ); return DFB_OK; } D_DEBUG_AT( X11_Update, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( &rect ) ); #ifdef USE_GLX /* Check for GLX allocation... */ if (allocation->pool == shared->glx_pool && lock->handle) { LocalPixmap *pixmap = lock->handle; D_MAGIC_ASSERT( pixmap, LocalPixmap ); /* ...and just call SwapBuffers... */ //D_DEBUG_AT( X11_Update, " -> Calling glXSwapBuffers( 0x%lx )...\n", alloc->drawable ); //glXSwapBuffers( x11->display, alloc->drawable ); D_DEBUG_AT( X11_Update, " -> Copying from GLXPixmap...\n" ); glXWaitGL(); XCopyArea( x11->display, pixmap->pixmap, xw->window, xw->gc, rect.x, rect.y, rect.w, rect.h, rect.x, rect.y ); glXWaitX(); XUnlockDisplay( x11->display ); return DFB_OK; } #endif /* Check for our special native allocation... */ if (allocation->pool == shared->x11image_pool && lock->handle) { x11Image *image = lock->handle; D_MAGIC_ASSERT( image, x11Image ); /* ...and directly XShmPutImage from that. */ ximage = image->ximage; direct = true; } else { /* ...or copy or convert into XShmImage or XImage allocated with the XWindow. */ ximage = xw->ximage; offset = xw->ximage_offset; xw->ximage_offset = (offset ? 0 : ximage->height / 2); /* make sure the 16-bit input formats are properly 2-pixel-clipped */ switch (surface->config.format) { case DSPF_I420: case DSPF_YV12: case DSPF_NV12: case DSPF_NV21: if (rect.y & 1) { rect.y--; rect.h++; } /* fall through */ case DSPF_YUY2: case DSPF_UYVY: case DSPF_NV16: if (rect.x & 1) { rect.x--; rect.w++; } default: /* no action */ break; } dst = xw->virtualscreen + rect.x * xw->bpp + (rect.y + offset) * ximage->bytes_per_line; src = lock->addr + DFB_BYTES_PER_LINE( surface->config.format, rect.x ) + rect.y * lock->pitch; switch (xw->depth) { case 32: dfb_convert_to_argb( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; case 24: dfb_convert_to_rgb32( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; case 16: if (surface->config.format == DSPF_LUT8) { int width = rect.w; int height = rect.h; const u8 *src8 = src; u16 *dst16 = dst; CorePalette *palette = surface->palette; int x; while (height--) { for (x=0; x<width; x++) { DFBColor color = palette->entries[src8[x]]; dst16[x] = PIXEL_RGB16( color.r, color.g, color.b ); } src8 += lock->pitch; dst16 += ximage->bytes_per_line / 2; } } else { dfb_convert_to_rgb16( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); } break; case 15: dfb_convert_to_rgb555( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; default: D_ONCE( "unsupported depth %d", xw->depth ); } } D_ASSERT( ximage != NULL ); /* Wait for previous data to be processed... */ XSync( x11->display, False ); /* ...and immediately queue or send the next! */ if (x11->use_shm) { /* Just queue the command, it's XShm :) */ XShmPutImage( xw->display, xw->window, xw->gc, ximage, rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h, False ); /* Make sure the queue has really happened! */ XFlush( x11->display ); } else /* Initiate transfer of buffer... */ XPutImage( xw->display, xw->window, xw->gc, ximage, rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h ); /* Wait for display if single buffered and not converted... */ if (direct && !(surface->config.caps & DSCAPS_FLIPPING)) XSync( x11->display, False ); XUnlockDisplay( x11->display ); return DFB_OK; }