static DFBResult update_screen( CoreSurface *surface, int x, int y, int w, int h ) { DFBResult ret; void *src; CoreSurfaceBufferLock lock; D_ASSERT( surface != NULL ); ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ, &lock ); if (ret) { D_DERROR( ret, "DirectFB/RTD: Couldn't lock layer surface!\n" ); return ret; } src = lock.addr; /* + DFB_BYTES_PER_LINE( surface->config.format, x ) + y * lock.pitch;*/ switch(surface->config.format) { case DSPF_RGB16: libk_copyrect_16(src, lock.pitch, x, y, w, h); break; case DSPF_RGB32: case DSPF_ARGB: libk_copyrect_32(src, lock.pitch, x, y, w, h); break; default: printf("bad pixel format %d\n", surface->config.format); break; } dfb_surface_unlock_buffer( surface, &lock ); return DFB_OK; }
static DFBResult unrealize_region( CoreLayerRegion *region ) { DFBResult ret; int index; CoreLayer *layer; CoreLayerShared *shared; const DisplayLayerFuncs *funcs; D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); layer = dfb_layer_at( region->context->layer_id ); D_ASSERT( layer != NULL ); D_ASSERT( layer->shared != NULL ); D_ASSERT( layer->funcs != NULL ); shared = layer->shared; funcs = layer->funcs; D_ASSERT( fusion_vector_contains( &shared->added_regions, region ) ); index = fusion_vector_index_of( &shared->added_regions, region ); D_DEBUG_AT( Core_Layers, "Removing region (%d, %d - %dx%d) from '%s'.\n", DFB_RECTANGLE_VALS( ®ion->config.dest ), shared->description.name ); /* Remove the region from hardware and driver. */ if (funcs->RemoveRegion) { ret = funcs->RemoveRegion( layer, layer->driver_data, layer->layer_data, region->region_data ); if (ret) { D_DERROR( ret, "Core/Layers: Could not remove region!\n" ); return ret; } } /* Remove the region from the 'added' list. */ fusion_vector_remove( &shared->added_regions, index ); /* Deallocate the driver's region data. */ if (region->region_data) { SHFREE( shared->shmpool, region->region_data ); region->region_data = NULL; } /* Update the region's state. */ D_FLAGS_CLEAR( region->state, CLRSF_REALIZED ); D_FLAGS_SET( region->state, CLRSF_FROZEN ); if (region->surface && region->surface_lock.buffer) { dfb_surface_unlock_buffer( region->surface, ®ion->surface_lock ); dfb_surface_destroy_buffers( region->surface ); } return DFB_OK; }
static DFBResult region_buffer_lock( CoreLayerRegion *region, CoreSurface *surface, CoreSurfaceBufferRole role ) { DFBResult ret; CoreSurfaceBuffer *buffer; CoreSurfaceAllocation *allocation; CoreLayerContext *context; D_ASSERT( region != NULL ); D_MAGIC_ASSERT( surface, CoreSurface ); context = region->context; D_MAGIC_ASSERT( context, CoreLayerContext ); /* First unlock any previously locked buffer. */ if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } if (dfb_surface_lock( surface )) return DFB_FUSION; buffer = dfb_surface_get_buffer( surface, role ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); /* Lock the surface buffer. */ ret = dfb_surface_buffer_lock( buffer, CSAID_LAYER0 + context->layer_id, CSAF_READ, ®ion->surface_lock ); if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); dfb_surface_unlock( surface ); return ret; } allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; } /* surface is unlocked by caller */ return DFB_OK; }
static DFBResult region_buffer_lock( CoreLayerRegion *region, CoreSurface *surface, CoreSurfaceBufferRole role ) { DFBResult ret; CoreSurfaceAccessFlags flags; CoreSurfaceBuffer *buffer; CoreSurfaceAllocation *allocation; /* First unlock any previously locked buffer. */ if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } /* Determine flags to use. */ if (surface->config.caps & DSCAPS_SYSTEMONLY) flags = CSAF_CPU_READ; else flags = CSAF_GPU_READ; if (dfb_surface_lock( surface )) return DFB_FUSION; buffer = dfb_surface_get_buffer( surface, role ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); /* Lock the surface buffer. */ ret = dfb_surface_buffer_lock( buffer, flags, ®ion->surface_lock ); if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); dfb_surface_unlock( surface ); return ret; } allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed & CSAF_GPU_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed &= ~CSAF_GPU_WRITE; } return DFB_OK; }
static DFBResult IDirectFBImageProvider_GIF_RenderTo( IDirectFBImageProvider *thiz, IDirectFBSurface *destination, const DFBRectangle *dest_rect ) { DFBResult ret; DFBRegion clip; DFBRectangle rect; DFBSurfacePixelFormat format; IDirectFBSurface_data *dst_data; CoreSurface *dst_surface; DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_GIF) dst_data = (IDirectFBSurface_data*) destination->priv; if (!dst_data) return DFB_DEAD; dst_surface = dst_data->surface; if (!dst_surface) return DFB_DESTROYED; dfb_region_from_rectangle( &clip, &dst_data->area.current ); if (dest_rect) { if (dest_rect->w < 1 || dest_rect->h < 1) return DFB_INVARG; rect = *dest_rect; rect.x += dst_data->area.wanted.x; rect.y += dst_data->area.wanted.y; } else { rect = dst_data->area.wanted; } ret = destination->GetPixelFormat( destination, &format ); if (ret) return ret; /* actual loading and rendering */ if (dfb_rectangle_region_intersects( &rect, &clip )) { CoreSurfaceBufferLock lock; ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); if (ret) return ret; dfb_scale_linear_32( data->image, data->image_width, data->image_height, lock.addr, lock.pitch, &rect, dst_surface, &clip ); dfb_surface_unlock_buffer( dst_surface, &lock ); if (data->base.render_callback) { DIRenderCallbackResult r; rect.x = 0; rect.y = 0; rect.w = data->image_width; rect.h = data->image_height; r = data->base.render_callback( &rect, data->base.render_callback_context ); if (r != DIRCR_OK) return DFB_INTERRUPTED; } } return DFB_OK; }
static DFBResult IDirectFBImageProvider_JPEG2000_RenderTo( IDirectFBImageProvider *thiz, IDirectFBSurface *destination, const DFBRectangle *dest_rect ) { IDirectFBSurface_data *dst_data; CoreSurface *dst_surface; CoreSurfaceBufferLock lock; DFBRectangle rect; DFBRegion clip; DIRenderCallbackResult cb_result = DIRCR_OK; DFBResult ret = DFB_OK; DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_JPEG2000 ) if (!destination) return DFB_INVARG; dst_data = destination->priv; if (!dst_data || !dst_data->surface) return DFB_DESTROYED; dst_surface = dst_data->surface; if (dest_rect) { if (dest_rect->w < 1 || dest_rect->h < 1) return DFB_INVARG; rect = *dest_rect; rect.x += dst_data->area.wanted.x; rect.y += dst_data->area.wanted.y; } else { rect = dst_data->area.wanted; } dfb_region_from_rectangle( &clip, &dst_data->area.current ); if (!dfb_rectangle_region_intersects( &rect, &clip )) return DFB_OK; ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); if (ret) return ret; if (!data->buf) { int cmptlut[3]; int width, height; int tlx, tly; int hs, vs; int i, j; bool direct, mono; if (jas_image_numcmpts(data->image) > 1) { cmptlut[0] = jas_image_getcmptbytype(data->image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); cmptlut[1] = jas_image_getcmptbytype(data->image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); cmptlut[2] = jas_image_getcmptbytype(data->image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); if (cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[2] < 0) { dfb_surface_unlock_buffer( dst_surface, &lock ); return DFB_UNSUPPORTED; } mono = false; } else { cmptlut[0] = cmptlut[1] = cmptlut[2] = 0; mono = true; } width = jas_image_width(data->image); height = jas_image_height(data->image); tlx = jas_image_cmpttlx(data->image, 0); tly = jas_image_cmpttly(data->image, 0); hs = jas_image_cmpthstep(data->image, 0); vs = jas_image_cmptvstep(data->image, 0); data->buf = D_MALLOC( width*height*4 ); if (!data->buf) { dfb_surface_unlock_buffer( dst_surface, &lock ); return D_OOM(); } direct = (rect.w == width && rect.h == height && data->render_callback); #define GET_SAMPLE( n, x, y ) ({ \ int _s; \ _s = jas_image_readcmptsample(data->image, cmptlut[n], x, y); \ _s >>= jas_image_cmptprec(data->image, cmptlut[n]) - 8; \ if (_s > 255) \ _s = 255; \ else if (_s < 0) \ _s = 0; \ _s; \ }) for (i = 0; i < height; i++) { u32 *dst = data->buf + i * width; int x, y; y = (i - tly) / vs; if (y >= 0 && y < height) { for (j = 0; j < width; j++) { x = (j - tlx) / hs; if (x >= 0 && x < width) { unsigned int r, g, b; if (mono) { r = g = b = GET_SAMPLE(0, x, y); } else { r = GET_SAMPLE(0, x, y); g = GET_SAMPLE(1, x, y); b = GET_SAMPLE(2, x, y); } *dst++ = 0xff000000 | (r << 16) | (g << 8) | b; } else { *dst++ = 0; } } } else { memset( dst, 0, width*4 ); } if (direct) { DFBRectangle r = { rect.x, rect.y+i, width, 1 }; dfb_copy_buffer_32( data->buf + i*width, lock.addr, lock.pitch, &r, dst_surface, &clip ); if (data->render_callback) { r = (DFBRectangle) { 0, i, width, 1 }; cb_result = data->render_callback( &r, data->render_callback_ctx ); if (cb_result != DIRCR_OK) break; } } } if (!direct) { dfb_scale_linear_32( data->buf, width, height, lock.addr, lock.pitch, &rect, dst_surface, &clip ); if (data->render_callback) { DFBRectangle r = { 0, 0, width, height }; data->render_callback( &r, data->render_callback_ctx ); } } if (cb_result != DIRCR_OK) { D_FREE( data->buf ); data->buf = NULL; ret = DFB_INTERRUPTED; } } else { int width = jas_image_width(data->image); int height = jas_image_height(data->image); dfb_scale_linear_32( data->buf, width, height, lock.addr, lock.pitch, &rect, dst_surface, &clip ); if (data->render_callback) { DFBRectangle r = {0, 0, width, height}; data->render_callback( &r, data->render_callback_ctx ); } } dfb_surface_unlock_buffer( dst_surface, &lock ); return ret; }
static DFBResult IDirectFBImageProvider_MPEG2_RenderTo( IDirectFBImageProvider *thiz, IDirectFBSurface *destination, const DFBRectangle *dest_rect ) { DFBResult ret; IDirectFBSurface_data *dst_data; CoreSurface *dst_surface; DFBRegion clip; DFBRectangle rect; DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_MPEG2) dst_data = (IDirectFBSurface_data*) destination->priv; if (!dst_data) return DFB_DEAD; dst_surface = dst_data->surface; if (!dst_surface) return DFB_DESTROYED; dfb_region_from_rectangle( &clip, &dst_data->area.current ); if (dest_rect) { if (dest_rect->w < 1 || dest_rect->h < 1) return DFB_INVARG; rect = *dest_rect; rect.w += dst_data->area.wanted.w; rect.h += dst_data->area.wanted.h; } else { rect = dst_data->area.wanted; } switch (data->stage) { case STAGE_END: break; case STAGE_IMAGE: if (MPEG2_Decode( data->dec, mpeg2_write_func, data )) { data->stage = STAGE_ERROR; return DFB_FAILURE; } data->stage = STAGE_END; break; default: return DFB_FAILURE; } /* actual rendering */ if (dfb_rectangle_region_intersects( &rect, &clip )) { CoreSurfaceBufferLock lock; ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); if (ret) return ret; dfb_scale_linear_32( data->image, data->width, data->height, lock.addr, lock.pitch, &rect, dst_surface, &clip ); dfb_surface_unlock_buffer( dst_surface, &lock ); } return DFB_OK; }
static DFBResult IDirectFBImageProvider_ANDROID_RenderTo( IDirectFBImageProvider *thiz, IDirectFBSurface *destination, const DFBRectangle *dest_rect ) { DFBResult ret; bool direct = false; DFBRegion clip; DFBRectangle rect; DFBSurfacePixelFormat format; IDirectFBSurface_data *dst_data; CoreSurface *dst_surface; CoreSurfaceBufferLock lock; DIRenderCallbackResult cb_result = DIRCR_OK; DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_ANDROID) dst_data = (IDirectFBSurface_data*) destination->priv; if (!dst_data) return DFB_DEAD; dst_surface = dst_data->surface; if (!dst_surface) return DFB_DESTROYED; ret = decodeImage( data ); if (ret) return ret; ret = destination->GetPixelFormat( destination, &format ); if (ret) return ret; dfb_region_from_rectangle( &clip, &dst_data->area.current ); if (dest_rect) { if (dest_rect->w < 1 || dest_rect->h < 1) return DFB_INVARG; rect = *dest_rect; rect.x += dst_data->area.wanted.x; rect.y += dst_data->area.wanted.y; if (!dfb_rectangle_region_intersects( &rect, &clip )) return DFB_OK; } else { rect = dst_data->area.wanted; } ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); if (ret) return ret; dfb_scale_linear_32( (u32 *)data->image, data->width, data->height, lock.addr, lock.pitch, &rect, dst_surface, &clip ); if (data->base.render_callback) { DFBRectangle r = { 0, 0, data->width, data->height }; data->base.render_callback( &r, data->base.render_callback_context ); } dfb_surface_unlock_buffer( dst_surface, &lock ); return DFB_OK; }
static DFBResult IDirectFBImageProvider_WebP_RenderTo( IDirectFBImageProvider *thiz, IDirectFBSurface *destination, const DFBRectangle *dest_rect ) { DFBResult ret; DFBRegion clip; CoreSurface *dst_surface; CardState state; CoreSurfaceBufferLock lock; IDirectFBSurface_data *dst_data; DIRenderCallbackResult cb_result = DIRCR_OK; DFBRectangle src_rect; DFBRectangle rect; DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP ) if (!destination) return DFB_INVARG; dst_data = destination->priv; if (!dst_data || !dst_data->surface) return DFB_DESTROYED; dst_surface = dst_data->surface; if (dest_rect) { if (dest_rect->w < 1 || dest_rect->h < 1) return DFB_INVARG; rect = *dest_rect; rect.x += dst_data->area.wanted.x; rect.y += dst_data->area.wanted.y; } else { rect = dst_data->area.wanted; } dfb_region_from_rectangle( &clip, &dst_data->area.current ); if (!dfb_rectangle_region_intersects( &rect, &clip )) return DFB_OK; ret = dfb_surface_create_simple( data->base.core, data->width, data->height, data->pixelformat, DSCS_RGB, DSCAPS_NONE, CSTF_NONE, 0, NULL, &data->decode_surface ); if (ret) { D_ERROR( "Failed to create surface : '%s'\n", DirectResultString(ret) ); goto error; } ret = dfb_surface_lock_buffer( data->decode_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); if (ret) { D_ERROR( "Failed to lock the surface : '%s'\n", DirectResultString(ret) ); goto error; } ret = WebP_decode_image( data, &lock ); if (ret) { D_ERROR( "Failed to decode the image : '%s'\n", DirectResultString(ret) ); goto error; } dfb_surface_unlock_buffer( data->decode_surface, &lock ); dfb_state_init( &state, data->base.core ); state.modified |= SMF_CLIP; state.clip = DFB_REGION_INIT_FROM_RECTANGLE_VALS( rect.x, rect.y, rect.w, rect.h ); src_rect = (DFBRectangle){0, 0, data->width, data->height}; dfb_state_set_source( &state, data->decode_surface ); dfb_state_set_destination( &state, dst_surface ); dfb_gfxcard_batchstretchblit( &src_rect, &rect, 1, &state ); data->serial = &state.serial; dfb_state_set_source(&state, NULL); dfb_state_set_destination(&state, NULL); dfb_state_destroy(&state); if (data->base.render_callback) { DFBRectangle r = { 0, 0, data->width, data->height }; cb_result=data->base.render_callback( &r, data->base.render_callback_context ); } if (cb_result == DIRCR_OK) { data->base.buffer->Release( data->base.buffer ); data->base.buffer = NULL; } return DFB_OK; error: if (data->decode_surface && lock.pitch) dfb_surface_unlock_buffer( data->decode_surface, &lock ); dfb_surface_unref( data->decode_surface ); data->base.buffer->Release( data->base.buffer ); data->base.buffer = NULL; return ret; }
static DFBResult set_region( CoreLayerRegion *region, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags flags, CoreSurface *surface ) { DFBResult ret; CoreLayer *layer; CoreLayerShared *shared; const DisplayLayerFuncs *funcs; D_DEBUG_AT( Core_Layers, "%s( %p, %p, 0x%08x, %p )\n", __FUNCTION__, region, config, flags, surface ); DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_Layers, config ); D_DEBUG_AT( Core_Layers, " -> state 0x%08x\n", region->state ); D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); D_ASSERT( config != NULL ); D_ASSERT( config->buffermode != DLBM_WINDOWS ); D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); layer = dfb_layer_at( region->context->layer_id ); D_ASSERT( layer != NULL ); D_ASSERT( layer->shared != NULL ); D_ASSERT( layer->funcs != NULL ); D_ASSERT( layer->funcs->SetRegion != NULL ); if (region->state & CLRSF_FROZEN) { D_DEBUG_AT( Core_Layers, " -> FROZEN!\n" ); return DFB_OK; } shared = layer->shared; funcs = layer->funcs; if (surface) { if (flags & (CLRCF_SURFACE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT)) { ret = region_buffer_lock( region, surface, CSBR_FRONT ); if (ret) return ret; dfb_surface_unlock( surface ); } D_ASSERT( region->surface_lock.buffer != NULL ); } else if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } D_DEBUG_AT( Core_Layers, " => setting region of '%s'\n", shared->description.name ); /* Setup hardware. */ return funcs->SetRegion( layer, layer->driver_data, layer->layer_data, region->region_data, config, flags, surface, surface ? surface->palette : NULL, ®ion->surface_lock ); }
static DFBResult set_region( CoreLayerRegion *region, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags flags, CoreSurface *surface ) { DFBResult ret = DFB_OK; CoreLayer *layer; const DisplayLayerFuncs *funcs; D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); D_ASSERT( config != NULL ); D_ASSERT( config->buffermode != DLBM_WINDOWS ); D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); layer = dfb_layer_at( region->context->layer_id ); D_ASSERT( layer != NULL ); D_ASSERT( layer->funcs != NULL ); D_ASSERT( layer->funcs->SetRegion != NULL ); if (region->state & CLRSF_FROZEN) return DFB_OK; funcs = layer->funcs; if (surface) { if (flags & (CLRCF_SURFACE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT)) { if (region->surface_lock.buffer) { CoreSurfaceBuffer *buffer = region->surface_lock.buffer; D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); if (surface == buffer->surface) { if (dfb_surface_lock( surface )) return DFB_FUSION; dfb_surface_buffer_unlock( ®ion->surface_lock ); buffer = dfb_surface_get_buffer( surface, CSBR_FRONT ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); ret = dfb_surface_buffer_lock( buffer, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); dfb_surface_unlock( surface ); } else { dfb_surface_unlock_buffer( buffer->surface, ®ion->surface_lock ); ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); } } else ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); } if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); return ret; } D_ASSERT( region->surface_lock.buffer != NULL ); } else if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } /* Setup hardware. */ return funcs->SetRegion( layer, layer->driver_data, layer->layer_data, region->region_data, config, flags, surface, surface ? surface->palette : NULL, ®ion->surface_lock ); }