static bool ep9xBlit( void *drv, void *dev, DFBRectangle *rect, int dx, int dy ) { EP9XDriverData *ep9xdrv = (EP9XDriverData *) drv; EP9XDeviceData *ep9xdev = (EP9XDeviceData *) dev; struct fb_image image; D_DEBUG_AT(ep9x,"%s:enter\n",__FUNCTION__); if (!(ep9xdev->clip.x1 <= dx) || !(ep9xdev->clip.y1 <= dy) || !( ep9xdev->clip.x2 >= (dx + rect->w - 1) ) || !( ep9xdev->clip.y2 >= (dy + rect->h - 1) )) { D_ERROR("the blit region is not vaild\n"); return false; } image.dx = ep9xdev->destaddr + dx; image.dy = dy; image.width = rect->w; image.height = rect->h; image.depth = ep9xdev->pixeldepth; if ( ep9xdev->fb_store == true ) image.data = (void*)ep9xdev->fb_addr + ep9xdev->srcaddr + DFB_BYTES_PER_LINE( ep9xdev->pixelformat,rect->x ) + (rect->y * ep9xdev->srcpitch ); else image.data = (void*)ep9xdev->srcaddr + DFB_BYTES_PER_LINE( ep9xdev->pixelformat, rect->x ) + (rect->y * ep9xdev->srcpitch ); ioctl(ep9xdrv->dfb_fbdev->fd,FBIO_EP9X_BLIT,&image); D_DEBUG_AT(ep9x,"%s:exit\n",__FUNCTION__); return true; }
void Genefx_Aop_xy( GenefxState *gfxs, int x, int y ) { int pitch = gfxs->dst_pitch; gfxs->Aop[0] = gfxs->dst_org[0]; gfxs->AopY = y; if (gfxs->dst_caps & DSCAPS_SEPARATED) { gfxs->Aop_field = y & 1; if (gfxs->Aop_field) gfxs->Aop[0] += gfxs->dst_field_offset; y /= 2; } D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT(gfxs->dst_format)) ); gfxs->Aop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, x ); if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) { int dst_field_offset = gfxs->dst_field_offset; switch (gfxs->dst_format) { case DSPF_YV12: case DSPF_I420: dst_field_offset /= 4; pitch /= 2; y /= 2; x /= 2; break; case DSPF_YV16: dst_field_offset /= 2; pitch /= 2; x /= 2; break; case DSPF_NV12: case DSPF_NV21: dst_field_offset /= 2; y /= 2; case DSPF_NV16: x &= ~1; break; case DSPF_YUV444P: /* nothing to adjust */ default: break; } gfxs->Aop[1] = gfxs->dst_org[1]; gfxs->Aop[2] = gfxs->dst_org[2]; if (gfxs->dst_caps & DSCAPS_SEPARATED && gfxs->Aop_field) { gfxs->Aop[1] += dst_field_offset; gfxs->Aop[2] += dst_field_offset; } gfxs->Aop[1] += y * pitch + x; gfxs->Aop[2] += y * pitch + x; } }
int main( int argc, char *argv[] ) { DirectResult ret; SH7722_JPEG_context info; DFBSurfacePixelFormat format; int pitch; DirectStream *stream = NULL; if (argc != 2) { fprintf( stderr, "Usage: %s <filename>\n", argv[0] ); return -1; } #ifndef STANDALONE direct_initialize(); direct_config->debug = true; #endif ret = SH7722_JPEG_Initialize(); if (ret) return ret; ret = direct_stream_create( argv[1], &stream ); if (ret) goto out; ret = SH7722_JPEG_Open( stream, &info ); if (ret) goto out; D_INFO( "SH7722/JPEGTool: Opened %dx%d image (4:%s)\n", info.width, info.height, info.mode420 ? "2:0" : info.mode444 ? "4:4" : "2:2?" ); format = DSPF_RGB24;// info.mode444 ? DSPF_NV16 : DSPF_NV12; pitch = (DFB_BYTES_PER_LINE( format, info.width ) + 31) & ~31; ret = SH7722_JPEG_Decode( &info, NULL, NULL, format, 0x0f800000, NULL, pitch, info.width, info.height ); if (ret) goto out; // Use RGB24 format for this // write_ppm( "test.ppm", 0x0f800000, pitch, info.width, info.height ); ret = SH7722_JPEG_Encode( "test.jpg", NULL, format, 0x0f800000, pitch, info.width, info.height, 0 ); if (ret) goto out; out: if (stream) direct_stream_destroy( stream ); SH7722_JPEG_Shutdown(); return ret; }
/* * Render a filled rectangle using the current hardware state. */ bool vmwareBlit( void *drv, void *dev, DFBRectangle *srect, int dx, int dy ) { VMWareDeviceData *vdev = (VMWareDeviceData*) dev; void *dst = vdev->dst_addr + dy * vdev->dst_pitch + DFB_BYTES_PER_LINE(vdev->dst_format, dx); void *src = vdev->src_addr + srect->y * vdev->src_pitch + DFB_BYTES_PER_LINE(vdev->src_format, srect->x); D_DEBUG_AT( VMWare_2D, "%s( %d,%d-%dx%d -> %d, %d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( srect ), dx, dy ); while (srect->h--) { direct_memcpy( dst, src, srect->w * vdev->dst_bpp ); dst += vdev->dst_pitch; src += vdev->src_pitch; } return true; }
/* * Render a filled rectangle using the current hardware state. */ bool vmwareFillRectangle( void *drv, void *dev, DFBRectangle *rect ) { VMWareDeviceData *vdev = (VMWareDeviceData*) dev; void *addr = vdev->dst_addr + rect->y * vdev->dst_pitch + DFB_BYTES_PER_LINE(vdev->dst_format, rect->x); D_DEBUG_AT( VMWare_2D, "%s( %d,%d-%dx%d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( rect ) ); switch (vdev->dst_bpp) { case 4: while (rect->h--) { int w = rect->w; u32 *dst = addr; while (w--) *dst++ = vdev->color_pixel; addr += vdev->dst_pitch; } break; case 2: while (rect->h--) { int w = rect->w; u16 *dst = addr; while (w--) *dst++ = vdev->color_pixel; addr += vdev->dst_pitch; } break; case 1: while (rect->h--) { int w = rect->w; u8 *dst = addr; while (w--) *dst++ = vdev->color_pixel; addr += vdev->dst_pitch; } break; } return true; }
static DFBResult preallocAllocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { int index; CoreSurface *surface; PreallocAllocationData *alloc = alloc_data; D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); surface = buffer->surface; D_MAGIC_ASSERT( surface, CoreSurface ); for (index=0; index<MAX_SURFACE_BUFFERS; index++) { if (surface->buffers[index] == buffer) break; } if (index == MAX_SURFACE_BUFFERS) return DFB_BUG; if (!(surface->config.flags & CSCONF_PREALLOCATED)) return DFB_BUG; if (!surface->config.preallocated[index].addr || surface->config.preallocated[index].pitch < DFB_BYTES_PER_LINE(surface->config.format, surface->config.size.w)) return DFB_INVARG; alloc->addr = surface->config.preallocated[index].addr; alloc->pitch = surface->config.preallocated[index].pitch; allocation->flags = CSALF_PREALLOCATED | CSALF_VOLATILE; allocation->size = surface->config.preallocated[index].pitch * DFB_PLANE_MULTIPLY( surface->config.format, surface->config.size.h ); return DFB_OK; }
DFBResult dfb_surfacemanager_allocate( SurfaceManager *manager, SurfaceBuffer *buffer ) { int pitch; int length; Chunk *c; Chunk *best_free = NULL; Chunk *best_occupied = NULL; CoreSurface *surface = buffer->surface; D_MAGIC_ASSERT( manager, SurfaceManager ); if (!manager->length || manager->suspended) return DFB_NOVIDEOMEMORY; /* calculate the required length depending on limitations */ pitch = MAX( surface->width, surface->min_width ); if (pitch < manager->max_power_of_two_pixelpitch && surface->height < manager->max_power_of_two_height) pitch = 1 << direct_log2( pitch ); if (manager->pixelpitch_align > 1) { pitch += manager->pixelpitch_align - 1; pitch -= pitch % manager->pixelpitch_align; } pitch = DFB_BYTES_PER_LINE( buffer->format, pitch ); if (pitch < manager->max_power_of_two_bytepitch && surface->height < manager->max_power_of_two_height) pitch = 1 << direct_log2( pitch ); if (manager->bytepitch_align > 1) { pitch += manager->bytepitch_align - 1; pitch -= pitch % manager->bytepitch_align; } length = DFB_PLANE_MULTIPLY( buffer->format, MAX( surface->height, surface->min_height ) * pitch ); if (manager->byteoffset_align > 1) { length += manager->byteoffset_align - 1; length -= length % manager->byteoffset_align; } /* Do a pre check before iterating through all chunks. */ if (length > manager->available - manager->heap_offset) return DFB_NOVIDEOMEMORY; buffer->video.pitch = pitch; /* examine chunks */ c = manager->chunks; while (c) { if (c->length >= length) { if (c->buffer) { c->tolerations++; if (c->tolerations > 0xff) c->tolerations = 0xff; if (!c->buffer->video.locked && c->buffer->policy <= buffer->policy && c->buffer->policy != CSP_VIDEOONLY && ((buffer->policy > c->buffer->policy) || (c->tolerations > manager->min_toleration/8 + 2))) { /* found a nice place to chill */ if (!best_occupied || best_occupied->length > c->length || best_occupied->tolerations < c->tolerations) /* first found or better one? */ best_occupied = c; } } else { /* found a nice place to chill */ if (!best_free || best_free->length > c->length) /* first found or better one? */ best_free = c; } } c = c->next; } /* if we found a place */ if (best_free) { occupy_chunk( manager, best_free, buffer, length ); return DFB_OK; } if (best_occupied) { CoreSurface *kicked = best_occupied->buffer->surface; D_DEBUG_AT( Core_SM, "Kicking out buffer at %d (%d) with tolerations %d...\n", best_occupied->offset, best_occupied->length, best_occupied->tolerations ); dfb_surfacemanager_assure_system( manager, best_occupied->buffer ); best_occupied->buffer->video.health = CSH_INVALID; dfb_surface_notify_listeners( kicked, CSNF_VIDEO ); best_occupied = free_chunk( manager, best_occupied ); dfb_gfxcard_sync(); occupy_chunk( manager, best_occupied, buffer, length ); return DFB_OK; } D_DEBUG_AT( Core_SM, "Couldn't allocate enough heap space for video memory surface!\n" ); /* no luck */ return DFB_NOVIDEOMEMORY; }
static DFBResult prealloc_transfer_readwrite( CoreSurface *surface, CoreSurfacePoolTransfer *transfer, CoreSurfaceAllocation *alloc, CoreSurfaceAccessFlags flags, CoreSlave *slave ) { DFBResult ret = DFB_OK; int index; int i, y; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( transfer != NULL ); CORE_SURFACE_ALLOCATION_ASSERT( alloc ); index = dfb_surface_buffer_index( alloc->buffer ); D_DEBUG_AT( PreAlloc_Bridge, "%s()\n", __FUNCTION__ ); D_DEBUG_AT( PreAlloc_Bridge, " ->Transfer read/write %s Fusion ID %lu (index %d)\n", (flags & CSAF_WRITE) ? "from" : "to", surface->object.identity, index ); for (i=0; i<transfer->num_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; int offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x ); int length = DFB_BYTES_PER_LINE( surface->config.format, rect->w ); u8 *temp = alloca( length ); // FIXME for (y=0; y<rect->h; y++) { DFBRectangle lrect = { rect->x, rect->y + y, rect->w, 1 }; if (flags & CSAF_WRITE) { ret = CoreSlave_GetData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, temp ); if (ret) break; ret = dfb_surface_pool_write( alloc->pool, alloc, temp, length, &lrect ); } else { ret = dfb_surface_pool_read( alloc->pool, alloc, temp, length, &lrect ); if (ret) break; ret = CoreSlave_PutData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, temp ); } if (ret) break; } if (ret) break; } return ret; }
static DFBResult prealloc_transfer_locked( CoreSurface *surface, CoreSurfacePoolTransfer *transfer, CoreSurfaceAllocation *locked, CoreSurfaceAccessFlags flags, CoreSlave *slave ) { DFBResult ret; CoreSurfaceBufferLock lock; int index; int i, y; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( transfer != NULL ); CORE_SURFACE_ALLOCATION_ASSERT( locked ); index = dfb_surface_buffer_index( locked->buffer ); D_DEBUG_AT( PreAlloc_Bridge, "%s()\n", __FUNCTION__ ); D_DEBUG_AT( PreAlloc_Bridge, " -> Transfer locked %s Fusion ID %lu (index %d)\n", (flags & CSAF_WRITE) ? "from" : "to", surface->object.identity, index ); dfb_surface_buffer_lock_init( &lock, CSAID_CPU, flags ); ret = dfb_surface_pool_lock( locked->pool, locked, &lock ); if (ret) { dfb_surface_buffer_lock_deinit( &lock ); return ret; } for (i=0; i<transfer->num_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; int offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x ); int length = DFB_BYTES_PER_LINE( surface->config.format, rect->w ); for (y=0; y<rect->h; y++) { if (flags & CSAF_WRITE) ret = CoreSlave_GetData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, lock.addr + (rect->y + y) * lock.pitch + offset ); else ret = CoreSlave_PutData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, lock.addr + (rect->y + y) * lock.pitch + offset ); if (ret) break; } if (ret) break; } dfb_surface_pool_unlock( locked->pool, locked, &lock ); dfb_surface_buffer_lock_deinit( &lock ); return ret; }
static DFBResult driver_init_device( CoreGraphicsDevice *device, GraphicsDeviceInfo *device_info, void *driver_data, void *device_data ) { SH7722DriverData *sdrv = driver_data; SH7722DeviceData *sdev = device_data; D_DEBUG_AT( SH7722_Driver, "%s()\n", __FUNCTION__ ); /* FIXME: Add a runtime option / config file. */ sdev->lcd_format = DSPF_RGB16; /* Check format of LCD buffer. */ switch (sdev->lcd_format) { case DSPF_RGB16: case DSPF_NV16: break; default: return DFB_UNSUPPORTED; } /* * Setup LCD buffer. */ sdev->lcd_width = SH7722_LCD_WIDTH; sdev->lcd_height = SH7722_LCD_HEIGHT; sdev->lcd_pitch = (DFB_BYTES_PER_LINE( sdev->lcd_format, sdev->lcd_width ) + 0xf) & ~0xf; sdev->lcd_size = DFB_PLANE_MULTIPLY( sdev->lcd_format, sdev->lcd_height ) * sdev->lcd_pitch; sdev->lcd_offset = dfb_gfxcard_reserve_memory( device, sdev->lcd_size ); if (sdev->lcd_offset < 0) { D_ERROR( "SH7722/Driver: Allocating %d bytes for the LCD buffer failed!\n", sdev->lcd_size ); return DFB_FAILURE; } sdev->lcd_phys = dfb_gfxcard_memory_physical( device, sdev->lcd_offset ); /* Get virtual addresses for JPEG reload buffers in master here, slaves do it in driver_init_driver(). */ sdrv->lcd_virt = dfb_gfxcard_memory_virtual( device, sdev->lcd_offset ); D_INFO( "SH7722/LCD: Allocated %dx%d %s Buffer (%d bytes) at 0x%08lx (%p)\n", sdev->lcd_width, sdev->lcd_height, dfb_pixelformat_name(sdev->lcd_format), sdev->lcd_size, sdev->lcd_phys, sdrv->lcd_virt ); D_ASSERT( ! (sdev->lcd_pitch & 0xf) ); D_ASSERT( ! (sdev->lcd_phys & 0xf) ); /* * Setup JPEG reload buffers. */ sdev->jpeg_size = SH7722GFX_JPEG_RELOAD_SIZE * 2 + SH7722GFX_JPEG_LINEBUFFER_SIZE * 2; sdev->jpeg_offset = dfb_gfxcard_reserve_memory( device, sdev->jpeg_size ); if (sdev->jpeg_offset < 0) { D_ERROR( "SH7722/Driver: Allocating %d bytes for the JPEG reload and line buffers failed!\n", sdev->jpeg_size ); return DFB_FAILURE; } sdev->jpeg_phys = dfb_gfxcard_memory_physical( device, sdev->jpeg_offset ); sdev->jpeg_lb1 = sdev->jpeg_phys + SH7722GFX_JPEG_RELOAD_SIZE * 2; sdev->jpeg_lb2 = sdev->jpeg_lb1 + SH7722GFX_JPEG_LINEBUFFER_SIZE; /* Get virtual addresses for JPEG reload buffers in master here, slaves do it in driver_init_driver(). */ sdrv->jpeg_virt = dfb_gfxcard_memory_virtual( device, sdev->jpeg_offset ); D_INFO( "SH7722/JPEG: Allocated reload and line buffers (%d bytes) at 0x%08lx (%p)\n", sdev->jpeg_size, sdev->jpeg_phys, sdrv->jpeg_virt ); D_ASSERT( ! (sdev->jpeg_size & 0xff) ); D_ASSERT( ! (sdev->jpeg_phys & 0xf) ); /* Fill in the device info. */ snprintf( device_info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "SH7722" ); snprintf( device_info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "Renesas" ); /* Set device limitations. */ device_info->limits.surface_byteoffset_alignment = 16; device_info->limits.surface_bytepitch_alignment = 8; /* Set device capabilities. */ device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS; device_info->caps.accel = SH7722_SUPPORTED_DRAWINGFUNCTIONS | SH7722_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = SH7722_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = SH7722_SUPPORTED_BLITTINGFLAGS; /* Change font format for acceleration. */ if (!dfb_config->software_only) { dfb_config->font_format = DSPF_ARGB; dfb_config->font_premult = false; } /* * Initialize hardware. */ /* Reset the drawing engine. */ sh7722EngineReset( sdrv, sdev ); /* Wait for idle BEU. */ while (SH7722_GETREG32( sdrv, BSTAR ) & 1); /* Disable all inputs. */ SH7722_SETREG32( sdrv, BESTR, 0 ); /* Disable all multi windows. */ SH7722_SETREG32( sdrv, BMWCR0, SH7722_GETREG32( sdrv, BMWCR0 ) & ~0xf ); /* Clear LCD buffer. */ switch (sdev->lcd_format) { case DSPF_RGB16: memset( (void*) sdrv->lcd_virt, 0x00, sdev->lcd_height * sdev->lcd_pitch ); break; case DSPF_NV16: memset( (void*) sdrv->lcd_virt, 0x10, sdev->lcd_height * sdev->lcd_pitch ); memset( (void*) sdrv->lcd_virt + sdev->lcd_height * sdev->lcd_pitch, 0x80, sdev->lcd_height * sdev->lcd_pitch ); break; default: D_BUG( "unsupported format" ); return DFB_BUG; } /* * TODO: Make LCD Buffer format and primary BEU format runtime configurable. */ /* Set output pixel format of the BEU. */ switch (sdev->lcd_format) { case DSPF_RGB16: SH7722_SETREG32( sdrv, BPKFR, BPKFR_RY_RGB | WPCK_RGB16 ); break; case DSPF_NV16: SH7722_SETREG32( sdrv, BPKFR, BPKFR_RY_RGB | BPKFR_TE_ENABLED | CHDS_YCBCR422 ); SH7722_SETREG32( sdrv, BDACR, sdev->lcd_phys + sdev->lcd_height * sdev->lcd_pitch ); break; default: D_BUG( "unsupported format" ); return DFB_BUG; } SH7722_SETREG32( sdrv, BPROCR, 0x00000000 ); /* Have BEU render into LCD buffer. */ SH7722_SETREG32( sdrv, BBLCR1, MT_MEMORY ); SH7722_SETREG32( sdrv, BDAYR, sdev->lcd_phys & 0xfffffffc ); SH7722_SETREG32( sdrv, BDMWR, sdev->lcd_pitch & 0x0003fffc ); /* Setup LCD controller to show the buffer. */ sh7722_lcd_setup( sdrv, sdev->lcd_width, sdev->lcd_height, sdev->lcd_phys, sdev->lcd_pitch, sdev->lcd_format, false ); /* Initialize BEU lock. */ fusion_skirmish_init( &sdev->beu_lock, "BEU", dfb_core_world(sdrv->core) ); /* Initialize JPEG lock. */ fusion_skirmish_init( &sdev->jpeg_lock, "JPEG", dfb_core_world(sdrv->core) ); return DFB_OK; }
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 int do_face( const Face *face ) { int i, ret; int align = DFB_PIXELFORMAT_ALIGNMENT( m_format ); int num_glyphs = 0; int num_rows = 1; int row_index = 0; int row_offset = 0; int next_face = sizeof(DGIFFFaceHeader); int total_height = 0; Entity::vector glyph_vector; unsigned int glyph_count = 0; DGIFFFaceHeader header; DGIFFGlyphInfo *glyphs; DGIFFGlyphRow *rows; void **row_data; DFBSurfaceDescription *descs; D_DEBUG_AT( mkdgiff, "%s( %p )\n", __FUNCTION__, face ); get_entities( face->buf, face->length, glyph_vector ); glyph_count = glyph_vector.size(); /* Clear to not leak any data into file. */ memset( &header, 0, sizeof(header) ); /* Allocate glyph info array. */ glyphs = (DGIFFGlyphInfo*) D_CALLOC( glyph_count, sizeof(DGIFFGlyphInfo) ); rows = (DGIFFGlyphRow*) D_CALLOC( glyph_count, sizeof(DGIFFGlyphRow) ); /* WORST case :) */ row_data = (void**) D_CALLOC( glyph_count, sizeof(void*) ); /* WORST case :) */ descs = (DFBSurfaceDescription*) D_CALLOC( glyph_count, sizeof(DFBSurfaceDescription) ); /* WORST case :) */ for (Entity::vector::const_iterator iter = glyph_vector.begin(); iter != glyph_vector.end(); iter++) { const Glyph *glyph = dynamic_cast<const Glyph*>( *iter ); glyph->Dump(); DGIFFGlyphInfo *info = &glyphs[num_glyphs]; DGIFFGlyphRow *row = &rows[num_rows - 1]; D_DEBUG_AT( mkdgiff, " -> code %3u\n", glyph->unicode ); ret = load_image( glyph->file.c_str(), &descs[num_glyphs] ); if (ret) continue; info->unicode = glyph->unicode; info->width = descs[num_glyphs].width; info->height = descs[num_glyphs].height; info->left = glyph->left; info->top = glyph->top; info->advance = glyph->advance; num_glyphs++; if (row->width > 0 && row->width + info->width > MAX_ROW_WIDTH) { num_rows++; row++; } row->width += (info->width + align) & ~align; if (row->height < info->height) row->height = info->height; } for (i=0; i<num_rows; i++) { DGIFFGlyphRow *row = &rows[i]; D_DEBUG_AT( mkdgiff, " -> row %d, width %d, height %d\n", i, row->width, row->height ); total_height += row->height; row->pitch = (DFB_BYTES_PER_LINE( m_format, row->width ) + 7) & ~7; row_data[i] = D_CALLOC( row->height, row->pitch ); next_face += row->height * row->pitch; } D_DEBUG_AT( mkdgiff, " -> %d glyphs, %d rows, total height %d\n", num_glyphs, num_rows, total_height ); next_face += num_glyphs * sizeof(DGIFFGlyphInfo); next_face += num_rows * sizeof(DGIFFGlyphRow); for (i=0; i<num_glyphs; i++) { DGIFFGlyphInfo *glyph = &glyphs[i]; D_DEBUG_AT( mkdgiff, " -> writing character 0x%x (%d)\n", glyph->unicode, i ); if (row_offset > 0 && row_offset + glyph->width > MAX_ROW_WIDTH) { row_index++; row_offset = 0; } D_DEBUG_AT( mkdgiff, " -> row offset %d\n", row_offset ); write_glyph( glyph, descs[i], (char*) row_data[row_index] + DFB_BYTES_PER_LINE( m_format, row_offset ), rows[row_index].pitch ); glyph->row = row_index; glyph->offset = row_offset; row_offset += (glyph->width + align) & ~align; } D_ASSERT( row_index == num_rows - 1 ); header.next_face = next_face; header.size = face->size; header.ascender = face->ascender; header.descender = face->descender; header.height = face->height; header.max_advance = face->maxadvance; header.pixelformat = m_format; header.num_glyphs = num_glyphs; header.num_rows = num_rows; header.blittingflags = face->blittingflags; D_DEBUG_AT( mkdgiff, " -> ascender %d, descender %d\n", header.ascender, header.descender ); D_DEBUG_AT( mkdgiff, " -> height %d, max advance %d\n", header.height, header.max_advance ); fwrite( &header, sizeof(header), 1, stdout ); fwrite( glyphs, sizeof(*glyphs), num_glyphs, stdout ); for (i=0; i<num_rows; i++) { DGIFFGlyphRow *row = &rows[i]; fwrite( row, sizeof(*row), 1, stdout ); fwrite( row_data[i], row->pitch, row->height, stdout ); } for (i=0; i<num_rows; i++) { if (row_data[i]) D_FREE( row_data[i] ); } D_FREE( row_data ); D_FREE( rows ); D_FREE( glyphs ); return 0; }
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; }
static DFBResult driver_init_device( CoreGraphicsDevice *device, GraphicsDeviceInfo *device_info, void *driver_data, void *device_data ) { SH7722DriverData *sdrv = driver_data; SH7722DeviceData *sdev = device_data; D_DEBUG_AT( SH7722_Driver, "%s()\n", __FUNCTION__ ); /* FIXME: Add a runtime option / config file. */ sdev->lcd_format = DSPF_RGB16; /* Check format of LCD buffer. */ switch (sdev->lcd_format) { case DSPF_RGB16: case DSPF_NV16: break; default: return DFB_UNSUPPORTED; } if (sdev->sh772x == 7723) memset( dfb_gfxcard_memory_virtual(device,0), 0, dfb_gfxcard_memory_length() ); /* * Setup LCD buffer. */ #ifdef SH772X_FBDEV_SUPPORT { struct fb_fix_screeninfo fsi; struct fb_var_screeninfo vsi; int fbdev; if ((fbdev = open("/dev/fb", O_RDONLY)) < 0) { D_ERROR( "SH7722/Driver: Can't open fbdev to get LCDC info!\n" ); return DFB_FAILURE; } if (ioctl(fbdev, FBIOGET_FSCREENINFO, &fsi) < 0) { D_ERROR( "SH7722/Driver: FBIOGET_FSCREEINFO failed.\n" ); close(fbdev); return DFB_FAILURE; } if (ioctl(fbdev, FBIOGET_VSCREENINFO, &vsi) < 0) { D_ERROR( "SH7722/Driver: FBIOGET_VSCREEINFO failed.\n" ); close(fbdev); return DFB_FAILURE; } sdev->lcd_width = vsi.xres; sdev->lcd_height = vsi.yres; sdev->lcd_pitch = fsi.line_length; sdev->lcd_size = fsi.smem_len; sdev->lcd_offset = 0; sdev->lcd_phys = fsi.smem_start; #if 0 sdrv->lcd_virt = mmap(NULL, fsi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev, 0); if (sdrv->lcd_virt == MAP_FAILED) { D_PERROR( "SH7722/Driver: mapping fbdev failed.\n" ); close(fbdev); return DFB_FAILURE; } /* Clear LCD buffer. */ switch (sdev->lcd_format) { case DSPF_RGB16: memset( (void*) sdrv->lcd_virt, 0x00, sdev->lcd_height * sdev->lcd_pitch ); break; case DSPF_NV16: memset( (void*) sdrv->lcd_virt, 0x10, sdev->lcd_height * sdev->lcd_pitch ); memset( (void*) sdrv->lcd_virt + sdev->lcd_height * sdev->lcd_pitch, 0x80, sdev->lcd_height * sdev->lcd_pitch ); break; default: D_BUG( "unsupported format" ); return DFB_BUG; } #endif close(fbdev); } #else sdev->lcd_width = SH7722_LCD_WIDTH; sdev->lcd_height = SH7722_LCD_HEIGHT; sdev->lcd_pitch = (DFB_BYTES_PER_LINE( sdev->lcd_format, sdev->lcd_width ) + 0xf) & ~0xf; sdev->lcd_size = DFB_PLANE_MULTIPLY( sdev->lcd_format, sdev->lcd_height ) * sdev->lcd_pitch; sdev->lcd_offset = dfb_gfxcard_reserve_memory( device, sdev->lcd_size ); if (sdev->lcd_offset < 0) { D_ERROR( "SH7722/Driver: Allocating %d bytes for the LCD buffer failed!\n", sdev->lcd_size ); return DFB_FAILURE; } sdev->lcd_phys = dfb_gfxcard_memory_physical( device, sdev->lcd_offset ); /* Get virtual addresses for LCD buffer in master here, slaves do it in driver_init_driver(). */ sdrv->lcd_virt = dfb_gfxcard_memory_virtual( device, sdev->lcd_offset ); #endif D_INFO( "SH7722/LCD: Allocated %dx%d %s Buffer (%d bytes) at 0x%08lx (%p)\n", sdev->lcd_width, sdev->lcd_height, dfb_pixelformat_name(sdev->lcd_format), sdev->lcd_size, sdev->lcd_phys, sdrv->lcd_virt ); D_ASSERT( ! (sdev->lcd_pitch & 0xf) ); D_ASSERT( ! (sdev->lcd_phys & 0xf) ); /* * Initialize hardware. */ switch (sdev->sh772x) { case 7722: /* Reset the drawing engine. */ sh7722EngineReset( sdrv, sdev ); /* Fill in the device info. */ snprintf( device_info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "SH7722" ); snprintf( device_info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "Renesas" ); /* Set device limitations. */ device_info->limits.surface_byteoffset_alignment = 16; device_info->limits.surface_bytepitch_alignment = 8; /* Set device capabilities. */ device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS; device_info->caps.accel = SH7722_SUPPORTED_DRAWINGFUNCTIONS | SH7722_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = SH7722_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = SH7722_SUPPORTED_BLITTINGFLAGS; /* Change font format for acceleration. */ if (!dfb_config->software_only) { dfb_config->font_format = DSPF_ARGB; dfb_config->font_premult = false; } break; case 7723: /* Reset the drawing engine. */ sh7723EngineReset( sdrv, sdev ); /* Fill in the device info. */ snprintf( device_info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "SH7723" ); snprintf( device_info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "Renesas" ); /* Set device limitations. */ device_info->limits.surface_byteoffset_alignment = 512; device_info->limits.surface_bytepitch_alignment = 64; /* Set device capabilities. */ device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS; device_info->caps.accel = SH7723_SUPPORTED_DRAWINGFUNCTIONS | \ SH7723_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = SH7723_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = SH7723_SUPPORTED_BLITTINGFLAGS; break; default: D_BUG( "unexpected device" ); return DFB_BUG; } /* Wait for idle BEU. */ while (SH7722_GETREG32( sdrv, BSTAR ) & 1); /* Disable all inputs. */ SH7722_SETREG32( sdrv, BESTR, 0 ); /* Disable all multi windows. */ SH7722_SETREG32( sdrv, BMWCR0, SH7722_GETREG32( sdrv, BMWCR0 ) & ~0xf ); #ifndef SH772X_FBDEV_SUPPORT /* Clear LCD buffer. */ switch (sdev->lcd_format) { case DSPF_RGB16: memset( (void*) sdrv->lcd_virt, 0x00, sdev->lcd_height * sdev->lcd_pitch ); break; case DSPF_NV16: memset( (void*) sdrv->lcd_virt, 0x10, sdev->lcd_height * sdev->lcd_pitch ); memset( (void*) sdrv->lcd_virt + sdev->lcd_height * sdev->lcd_pitch, 0x80, sdev->lcd_height * sdev->lcd_pitch ); break; default: D_BUG( "unsupported format" ); return DFB_BUG; } #endif /* * TODO: Make LCD Buffer format and primary BEU format runtime configurable. */ /* Set output pixel format of the BEU. */ switch (sdev->lcd_format) { case DSPF_RGB16: SH7722_SETREG32( sdrv, BPKFR, BPKFR_RY_RGB | WPCK_RGB16 ); break; case DSPF_NV16: SH7722_SETREG32( sdrv, BPKFR, BPKFR_RY_RGB | BPKFR_TE_ENABLED | CHDS_YCBCR422 ); SH7722_SETREG32( sdrv, BDACR, sdev->lcd_phys + sdev->lcd_height * sdev->lcd_pitch ); break; default: D_BUG( "unsupported format" ); return DFB_BUG; } SH7722_SETREG32( sdrv, BPROCR, 0x00000000 ); /* Have BEU render into LCD buffer. */ SH7722_SETREG32( sdrv, BBLCR1, MT_MEMORY ); SH7722_SETREG32( sdrv, BDAYR, sdev->lcd_phys & 0xfffffffc ); SH7722_SETREG32( sdrv, BDMWR, sdev->lcd_pitch & 0x0003fffc ); #ifndef SH772X_FBDEV_SUPPORT /* Setup LCD controller to show the buffer. */ sh7722_lcd_setup( sdrv, sdev->lcd_width, sdev->lcd_height, sdev->lcd_phys, sdev->lcd_pitch, sdev->lcd_format, false ); #endif /* Initialize BEU lock. */ fusion_skirmish_init( &sdev->beu_lock, "BEU", dfb_core_world(sdrv->core) ); return DFB_OK; }
static DFBResult update_screen( int x, int y, int w, int h ) { #if 0 int i, n; void *dst; void *src; DFBResult ret; CoreSurface *surface; CoreSurfaceBuffer *buffer; CoreSurfaceBufferLock lock; u16 *src16, *dst16; u8 *src8; #endif D_DEBUG_AT( SDL_Updates, "%s( %d, %d, %d, %d )\n", __FUNCTION__, x, y, w, h ); D_DEBUG_AT( SDL_Updates, " -> locking sdl lock...\n" ); fusion_skirmish_prevail( &dfb_sdl->lock ); #if 0 surface = dfb_sdl->primary; D_MAGIC_ASSERT_IF( surface, CoreSurface ); D_DEBUG_AT( SDL_Updates, " -> primary is %p\n", surface ); if (!surface) { D_DEBUG_AT( SDL_Updates, " -> unlocking sdl lock...\n" ); fusion_skirmish_dismiss( &dfb_sdl->lock ); D_DEBUG_AT( SDL_Updates, " -> done.\n" ); return DFB_OK; } buffer = dfb_surface_get_buffer( surface, CSBR_FRONT ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); D_DEBUG_AT( SDL_Updates, " -> locking sdl surface...\n" ); if (SDL_LockSurface( screen ) < 0) { D_ERROR( "DirectFB/SDL: " "Couldn't lock the display surface: %s\n", SDL_GetError() ); fusion_skirmish_dismiss( &dfb_sdl->lock ); return DFB_FAILURE; } D_DEBUG_AT( SDL_Updates, " -> locking dfb surface...\n" ); ret = dfb_surface_buffer_lock( buffer, CSAF_CPU_READ, &lock ); if (ret) { D_ERROR( "DirectFB/SDL: Couldn't lock layer surface: %s\n", DirectFBErrorString( ret ) ); SDL_UnlockSurface(screen); fusion_skirmish_dismiss( &dfb_sdl->lock ); return ret; } src = lock.addr; dst = screen->pixels; src += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * lock.pitch; dst += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * screen->pitch; D_DEBUG_AT( SDL_Updates, " -> copying pixels...\n" ); switch (screen->format->BitsPerPixel) { case 16: dfb_convert_to_rgb16( surface->config.format, src, lock.pitch, surface->config.size.h, dst, screen->pitch, w, h ); break; default: direct_memcpy( dst, src, DFB_BYTES_PER_LINE( surface->config.format, w ) ); } D_DEBUG_AT( SDL_Updates, " -> unlocking dfb surface...\n" ); dfb_surface_buffer_unlock( &lock ); D_DEBUG_AT( SDL_Updates, " -> unlocking sdl surface...\n" ); SDL_UnlockSurface( screen ); #endif D_DEBUG_AT( SDL_Updates, " -> calling SDL_UpdateRect()...\n" ); SDL_UpdateRect( dfb_sdl->screen, x, y, w, h ); D_DEBUG_AT( SDL_Updates, " -> unlocking sdl lock...\n" ); fusion_skirmish_dismiss( &dfb_sdl->lock ); D_DEBUG_AT( SDL_Updates, " -> done.\n" ); return DFB_OK; }
DFBResult dfb_surfacemanager_assure_video( SurfaceManager *manager, SurfaceBuffer *buffer ) { DFBResult ret; CoreSurface *surface = buffer->surface; D_MAGIC_ASSERT( manager, SurfaceManager ); if (manager->suspended) return DFB_NOVIDEOMEMORY; switch (buffer->video.health) { case CSH_STORED: if (buffer->video.chunk) buffer->video.chunk->tolerations = 0; return DFB_OK; case CSH_INVALID: ret = dfb_surfacemanager_allocate( manager, buffer ); if (ret) return ret; /* FALL THROUGH, because after successful allocation the surface health is CSH_RESTORE */ case CSH_RESTORE: if (buffer->system.health != CSH_STORED) D_BUG( "system/video instances both not stored!" ); if (buffer->flags & SBF_WRITTEN) { int i; char *src = buffer->system.addr; char *dst = dfb_system_video_memory_virtual( buffer->video.offset ); for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->system.pitch; dst += buffer->video.pitch; } if (buffer->format == DSPF_YV12 || buffer->format == DSPF_I420) { for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width / 2) ); src += buffer->system.pitch / 2; dst += buffer->video.pitch / 2; } } else if (buffer->format == DSPF_NV12 || buffer->format == DSPF_NV21) { for (i=0; i<surface->height/2; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->system.pitch; dst += buffer->video.pitch; } } else if (buffer->format == DSPF_NV16) { for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->system.pitch; dst += buffer->video.pitch; } } } buffer->video.health = CSH_STORED; buffer->video.chunk->tolerations = 0; dfb_surface_notify_listeners( surface, CSNF_VIDEO ); return DFB_OK; default: break; } D_BUG( "unknown video instance health" ); return DFB_BUG; }
DFBResult dfb_surfacemanager_assure_system( SurfaceManager *manager, SurfaceBuffer *buffer ) { CoreSurface *surface = buffer->surface; D_MAGIC_ASSERT( manager, SurfaceManager ); if (buffer->policy == CSP_VIDEOONLY) { D_BUG( "surface_manager_assure_system() called on video only surface" ); return DFB_BUG; } if (buffer->system.health == CSH_STORED) return DFB_OK; else if (buffer->video.health == CSH_STORED) { int i; char *src = dfb_system_video_memory_virtual( buffer->video.offset ); char *dst = buffer->system.addr; /* from video_access_by_software() in surface.c */ if (buffer->video.access & VAF_HARDWARE_WRITE) { dfb_gfxcard_sync(); buffer->video.access &= ~VAF_HARDWARE_WRITE; } buffer->video.access |= VAF_SOFTWARE_READ; for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->video.pitch; dst += buffer->system.pitch; } if (buffer->format == DSPF_YV12 || buffer->format == DSPF_I420) { for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width / 2) ); src += buffer->video.pitch / 2; dst += buffer->system.pitch / 2; } } else if (buffer->format == DSPF_NV12 || buffer->format == DSPF_NV21) { for (i=0; i<surface->height/2; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->video.pitch; dst += buffer->system.pitch; } } else if (buffer->format == DSPF_NV16) { for (i=0; i<surface->height; i++) { direct_memcpy( dst, src, DFB_BYTES_PER_LINE(buffer->format, surface->width) ); src += buffer->video.pitch; dst += buffer->system.pitch; } } buffer->system.health = CSH_STORED; dfb_surface_notify_listeners( surface, CSNF_SYSTEM ); return DFB_OK; } D_BUG( "no valid surface instance" ); return DFB_BUG; }
DFBResult dfb_surface_read_buffer( CoreSurface *surface, CoreSurfaceBufferRole role, void *destination, int pitch, const DFBRectangle *prect ) { DFBResult ret; int y; int bytes; DFBRectangle rect; DFBSurfacePixelFormat format; CoreSurfaceAllocation *allocation; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( destination != NULL ); D_ASSERT( pitch > 0 ); DFB_RECTANGLE_ASSERT_IF( prect ); D_DEBUG_AT( Core_Surface, "%s( %p, %p [%d] )\n", __FUNCTION__, surface, destination, pitch ); /* Determine area. */ rect.x = 0; rect.y = 0; rect.w = surface->config.size.w; rect.h = surface->config.size.h; if (prect && (!dfb_rectangle_intersect( &rect, prect ) || !DFB_RECTANGLE_EQUAL( rect, *prect ))) return DFB_INVAREA; /* Calculate bytes per read line. */ format = surface->config.format; bytes = DFB_BYTES_PER_LINE( format, rect.w ); D_DEBUG_AT( Core_Surface, " -> %d,%d - %dx%d (%s)\n", DFB_RECTANGLE_VALS(&rect), dfb_pixelformat_name( format ) ); ret = CoreSurface_PreLockBuffer2( surface, role, CSAID_CPU, CSAF_READ, false, &allocation ); if (ret == DFB_NOALLOCATION) { for (y=0; y<rect.h; y++) { memset( destination, 0, bytes ); destination += pitch; } return DFB_OK; } if (ret) return ret; D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); D_DEBUG_AT( Core_Surface, " -> PreLockBuffer returned allocation %p (%s)\n", allocation, allocation->pool->desc.name ); /* Try reading from allocation directly... */ ret = dfb_surface_pool_read( allocation->pool, allocation, destination, pitch, &rect ); if (ret) { /* ...otherwise use fallback method via locking if possible. */ if (allocation->access[CSAID_CPU] & CSAF_READ) { CoreSurfaceBufferLock lock; /* Lock the allocation. */ dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_READ ); ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock ); if (ret) { D_DERROR( ret, "Core/SurfBuffer: Locking allocation failed! [%s]\n", allocation->pool->desc.name ); dfb_surface_buffer_lock_deinit( &lock ); dfb_surface_allocation_unref( allocation ); return ret; } /* Move to start of read. */ lock.addr += DFB_BYTES_PER_LINE( format, rect.x ) + rect.y * lock.pitch; /* Copy the data. */ for (y=0; y<rect.h; y++) { direct_memcpy( destination, lock.addr, bytes ); destination += pitch; lock.addr += lock.pitch; } /* Unlock the allocation. */ ret = dfb_surface_pool_unlock( allocation->pool, allocation, &lock ); if (ret) D_DERROR( ret, "Core/SurfBuffer: Unlocking allocation failed! [%s]\n", allocation->pool->desc.name ); dfb_surface_buffer_lock_deinit( &lock ); } } dfb_surface_allocation_unref( allocation ); return DFB_OK; }
DFBResult dfb_surface_write_buffer( CoreSurface *surface, CoreSurfaceBufferRole role, const void *source, int pitch, const DFBRectangle *prect ) { DFBResult ret; int bytes; DFBRectangle rect; DFBSurfacePixelFormat format; CoreSurfaceAllocation *allocation; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( pitch > 0 || source == NULL ); DFB_RECTANGLE_ASSERT_IF( prect ); D_DEBUG_AT( Core_Surface, "%s( %p, %p [%d] )\n", __FUNCTION__, surface, source, pitch ); /* Determine area. */ rect.x = 0; rect.y = 0; rect.w = surface->config.size.w; rect.h = surface->config.size.h; if (prect) { if (!dfb_rectangle_intersect( &rect, prect )) { D_DEBUG_AT( Core_Surface, " -> no intersection!\n" ); return DFB_INVAREA; } if (!DFB_RECTANGLE_EQUAL( rect, *prect )) { D_DEBUG_AT( Core_Surface, " -> got clipped to %d,%d-%dx%d!\n", DFB_RECTANGLE_VALS(&rect) ); return DFB_INVAREA; } } /* Calculate bytes per read line. */ format = surface->config.format; bytes = DFB_BYTES_PER_LINE( format, rect.w ); D_DEBUG_AT( Core_Surface, " -> %d,%d - %dx%d (%s)\n", DFB_RECTANGLE_VALS(&rect), dfb_pixelformat_name( format ) ); ret = CoreSurface_PreLockBuffer2( surface, role, CSAID_CPU, CSAF_WRITE, false, &allocation ); if (ret) return ret; D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); D_DEBUG_AT( Core_Surface, " -> PreLockBuffer returned allocation %p (%s)\n", allocation, allocation->pool->desc.name ); /* Try writing to allocation directly... */ ret = source ? dfb_surface_pool_write( allocation->pool, allocation, source, pitch, &rect ) : DFB_UNSUPPORTED; if (ret) { /* ...otherwise use fallback method via locking if possible. */ if (allocation->access[CSAID_CPU] & CSAF_WRITE) { int y; int bytes; DFBSurfacePixelFormat format; CoreSurfaceBufferLock lock; /* Calculate bytes per written line. */ format = surface->config.format; bytes = DFB_BYTES_PER_LINE( format, rect.w ); /* Lock the allocation. */ dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_WRITE ); ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock ); if (ret) { D_DERROR( ret, "Core/SurfBuffer: Locking allocation failed! [%s]\n", allocation->pool->desc.name ); dfb_surface_buffer_lock_deinit( &lock ); dfb_surface_allocation_unref( allocation ); return ret; } /* Move to start of write. */ lock.addr += DFB_BYTES_PER_LINE( format, rect.x ) + rect.y * lock.pitch; /* Copy the data. */ for (y=0; y<rect.h; y++) { if (source) { direct_memcpy( lock.addr, source, bytes ); source += pitch; } else memset( lock.addr, 0, bytes ); lock.addr += lock.pitch; } /* Unlock the allocation. */ ret = dfb_surface_pool_unlock( allocation->pool, allocation, &lock ); if (ret) D_DERROR( ret, "Core/SurfBuffer: Unlocking allocation failed! [%s]\n", allocation->pool->desc.name ); dfb_surface_buffer_lock_deinit( &lock ); } } dfb_surface_allocation_unref( allocation ); return DFB_OK; }
static DFBResult load_image (const char *filename, DFBSurfaceDescription *desc) { DFBSurfacePixelFormat dest_format; DFBSurfacePixelFormat src_format; FILE *fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; unsigned char *data = NULL; int type; char header[8]; int bytes, pitch; dest_format = (desc->flags & DSDESC_PIXELFORMAT) ? desc->pixelformat : DSPF_UNKNOWN; desc->flags = DSDESC_NONE; desc->preallocated[0].data = NULL; if (!(fp = fopen (filename, "rb"))) { fprintf (stderr, "Failed to open file '%s': %s.\n", filename, strerror (errno)); goto cleanup; } bytes = fread (header, 1, sizeof(header), fp); if (png_sig_cmp ((unsigned char*) header, 0, bytes)) { fprintf (stderr, "File '%s' doesn't seem to be a PNG image file.\n", filename); goto cleanup; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto cleanup; if (setjmp (png_jmpbuf(png_ptr))) { if (desc->preallocated[0].data) { free (desc->preallocated[0].data); desc->preallocated[0].data = NULL; } /* data might have been clobbered, set it to NULL and leak instead of crashing */ data = NULL; goto cleanup; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) goto cleanup; png_init_io (png_ptr, fp); png_set_sig_bytes (png_ptr, bytes); png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bytes, &type, NULL, NULL, NULL); if (bytes == 16) png_set_strip_16 (png_ptr); #ifdef WORDS_BIGENDIAN png_set_swap_alpha (png_ptr); #else png_set_bgr (png_ptr); #endif src_format = (type & PNG_COLOR_MASK_ALPHA) ? DSPF_ARGB : DSPF_RGB32; switch (type) { case PNG_COLOR_TYPE_GRAY: if (dest_format == DSPF_A8) { src_format = DSPF_A8; break; } /* fallthru */ case PNG_COLOR_TYPE_GRAY_ALPHA: png_set_gray_to_rgb (png_ptr); // if (rgbformat) // dest_format = rgbformat; break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb (png_ptr); /* fallthru */ case PNG_COLOR_TYPE_RGB: // if (rgbformat) // dest_format = rgbformat; case PNG_COLOR_TYPE_RGB_ALPHA: if (dest_format == DSPF_RGB24) { png_set_strip_alpha (png_ptr); src_format = DSPF_RGB24; } break; } switch (src_format) { case DSPF_RGB32: png_set_filler (png_ptr, 0xFF, #ifdef WORDS_BIGENDIAN PNG_FILLER_BEFORE #else PNG_FILLER_AFTER #endif ); break; case DSPF_ARGB: case DSPF_A8: if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); break; default: break; } pitch = (DFB_BYTES_PER_LINE( src_format, width ) + 7) & ~7; data = (unsigned char*) malloc (height * pitch); if (!data) { fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * pitch)); goto cleanup; } { unsigned int i; png_bytep bptrs[height]; for (i = 0; i < height; i++) bptrs[i] = data + i * pitch; png_read_image (png_ptr, bptrs); } if (!dest_format) dest_format = src_format; if (DFB_BYTES_PER_PIXEL(src_format) != DFB_BYTES_PER_PIXEL(dest_format)) { unsigned char *s, *d, *dest; int d_pitch, h; D_ASSERT( DFB_BYTES_PER_PIXEL(src_format) == 4 ); d_pitch = (DFB_BYTES_PER_LINE(dest_format, width) + 7) & ~7; dest = (unsigned char*) malloc (height * d_pitch); if (!dest) { fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * d_pitch)); goto cleanup; } h = height; switch (dest_format) { case DSPF_RGB16: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgb16 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB8565: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb8565 ((u32 *) s, (u8 *) d, width); break; case DSPF_ARGB1555: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb1555 ((u32 *) s, (u16 *) d, width); break; case DSPF_RGBA5551: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgba5551 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB2554: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb2554 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB4444: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb4444 ((u32 *) s, (u16 *) d, width); break; case DSPF_RGB332: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgb332 ((u32 *) s, (u8 *) d, width); break; case DSPF_A8: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_a8 ((u32 *) s, (u8 *) d, width); break; default: fprintf (stderr, "Sorry, unsupported format conversion.\n"); goto cleanup; } free (data); data = dest; pitch = d_pitch; } desc->flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED); desc->width = width; desc->height = height; desc->pixelformat = dest_format; desc->preallocated[0].pitch = pitch; desc->preallocated[0].data = data; data = NULL; cleanup: if (fp) fclose (fp); if (png_ptr) png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (data) free (data); return ((desc->flags) ? DFB_OK : DFB_FAILURE); }