static void handle_response( VoodooManager *manager, VoodooResponseMessage *response ) { D_MAGIC_ASSERT( manager, VoodooManager ); D_ASSERT( response != NULL ); D_ASSERT( response->header.size >= sizeof(VoodooResponseMessage) ); D_ASSERT( response->header.type == VMSG_RESPONSE ); D_ASSERT( response->request < manager->msg_serial ); D_DEBUG( "Voodoo/Dispatch: Handling RESPONSE message %llu (%s) with instance %u for request " "%llu (%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( response->result ), response->instance, (unsigned long long)response->request, response->header.size ); pthread_mutex_lock( &manager->response.lock ); D_ASSERT( manager->response.current == NULL ); manager->response.current = response; pthread_cond_broadcast( &manager->response.wait ); while (manager->response.current && !manager->quit) pthread_cond_wait( &manager->response.wait, &manager->response.lock ); pthread_mutex_unlock( &manager->response.lock ); }
const char * DirectFBErrorString( DFBResult error ) { if (D_RESULT_TYPE_IS( error, 'D','F','B' )) { switch (error) { case DFB_NOVIDEOMEMORY: return "Out of video memory!"; case DFB_MISSINGFONT: return "No font has been set!"; case DFB_MISSINGIMAGE: return "No image has been set!"; default: return "UKNOWN DIRECTFB RESULT!"; } } return DirectResultString( error ); }
DFBResult dfb_surface_pool_bridges_transfer( CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *from, CoreSurfaceAllocation *to, const DFBRectangle *rects, unsigned int num_rects ) { DFBResult ret; int i; DFBRectangle rect; CoreSurfacePoolBridge *bridge = NULL; const SurfacePoolBridgeFuncs *funcs; CoreSurfacePoolTransfer *transfer; D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); CORE_SURFACE_ALLOCATION_ASSERT( from ); CORE_SURFACE_ALLOCATION_ASSERT( to ); D_ASSERT( rects != NULL || num_rects == 0 ); D_ASSERT( num_rects > 0 || rects == NULL ); D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%dx%d %s], %p -> %p, %d rects )\n", __FUNCTION__, buffer, buffer->config.size.w, buffer->config.size.h, dfb_pixelformat_name( buffer->format ), from, to, num_rects ); if (!rects) { rect.x = rect.y = 0; rect.w = buffer->config.size.w; rect.h = buffer->config.size.h; rects = ▭ num_rects = 1; } for (i=0; i<bridge_count; i++) { D_ASSERT( bridge_order[i] >= 0 ); D_ASSERT( bridge_order[i] < bridge_count ); bridge = bridge_array[bridge_order[i]]; D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); funcs = get_funcs( bridge ); D_ASSERT( funcs->CheckTransfer != NULL ); ret = funcs->CheckTransfer( bridge, bridge->data, get_local(bridge), buffer, from, to ); if (ret) bridge = NULL; else break; } if (!bridge) return DFB_UNSUPPORTED; D_DEBUG_AT( Core_SurfPoolBridge, " -> using '%s'\n", bridge->desc.name ); ret = allocate_transfer( bridge, buffer, from, to, rects, num_rects, &transfer ); if (ret) return ret; D_ASSERT( funcs->StartTransfer != NULL ); D_DEBUG_AT( Core_SurfPoolBridge, " -> start...\n" ); ret = funcs->StartTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); if (ret) D_DERROR( ret, "Core/SurfacePoolBridge: Starting transfer via '%s' failed!\n", bridge->desc.name ); else if (funcs->FinishTransfer) { D_DEBUG_AT( Core_SurfPoolBridge, " -> finish...\n" ); ret = funcs->FinishTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); if (ret) D_DERROR( ret, "Core/SurfacePoolBridge: Finishing transfer via '%s' failed!\n", bridge->desc.name ); } D_DEBUG_AT( Core_SurfPoolBridge, " => %s\n", DirectResultString(ret) ); deallocate_transfer( transfer ); return ret; }
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; }
const char * DirectFBErrorString( DFBResult error ) { return DirectResultString( error ); }
DirectResult voodoo_manager_respond( VoodooManager *manager, VoodooMessageSerial request, DirectResult result, VoodooInstanceID instance, VoodooMessageBlockType block_type, ... ) { DirectResult ret; int size; void *ptr; VoodooMessageSerial serial; VoodooResponseMessage *msg; va_list args; D_MAGIC_ASSERT( manager, VoodooManager ); D_DEBUG( "Voodoo/Response: " "Request %llu, result %d, instance %u...\n", (unsigned long long)request, result, instance ); /* Calculate the total message size. */ va_start( args, block_type ); size = sizeof(VoodooResponseMessage) + calc_blocks( block_type, args ); va_end( args ); D_DEBUG( "Voodoo/Response: --> complete message size: %d\n", size ); /* Lock the output buffer for direct writing. */ ret = manager_lock_output( manager, size, &ptr ); if (ret) return ret; msg = ptr; serial = manager->msg_serial++; /* Fill message header. */ msg->header.size = size; msg->header.serial = serial; msg->header.type = VMSG_RESPONSE; /* Fill message body. */ msg->request = request; msg->result = result; msg->instance = instance; /* Append custom data. */ va_start( args, block_type ); write_blocks( msg + 1, block_type, args ); va_end( args ); D_DEBUG( "Voodoo/Manager: " "Sending RESPONSE message %llu (%s) with instance %u for request %llu (%d bytes).\n", (unsigned long long)serial, DirectResultString( result ), instance, (unsigned long long)request, size ); /* Unlock the output buffer. */ manager_unlock_output( manager, true ); return DR_OK; }
DirectResult voodoo_manager_request( VoodooManager *manager, VoodooInstanceID instance, VoodooMethodID method, VoodooRequestFlags flags, VoodooResponseMessage **ret_response, VoodooMessageBlockType block_type, ... ) { DirectResult ret; int size; void *ptr; VoodooMessageSerial serial; VoodooRequestMessage *msg; va_list args; D_MAGIC_ASSERT( manager, VoodooManager ); D_ASSERT( instance != VOODOO_INSTANCE_NONE ); D_ASSERT( ret_response != NULL || !(flags & VREQ_RESPOND) ); D_ASSUME( (flags & (VREQ_RESPOND | VREQ_QUEUE)) != (VREQ_RESPOND | VREQ_QUEUE) ); D_DEBUG( "Voodoo/Request: " "Instance %u, method %u, flags 0x%08x...\n", instance, method, flags ); /* Calculate the total message size. */ va_start( args, block_type ); size = sizeof(VoodooRequestMessage) + calc_blocks( block_type, args ); va_end( args ); D_DEBUG( "Voodoo/Request: --> complete message size: %d\n", size ); /* Lock the output buffer for direct writing. */ ret = manager_lock_output( manager, size, &ptr ); if (ret) return ret; msg = ptr; serial = manager->msg_serial++; /* Fill message header. */ msg->header.size = size; msg->header.serial = serial; msg->header.type = VMSG_REQUEST; /* Fill message body. */ msg->instance = instance; msg->method = method; msg->flags = flags; /* Append custom data. */ va_start( args, block_type ); write_blocks( msg + 1, block_type, args ); va_end( args ); D_DEBUG( "Voodoo/Manager: Sending REQUEST message %llu to %u::%u %s(%d bytes).\n", (unsigned long long)serial, instance, method, (flags & VREQ_RESPOND) ? "[RESPONDING] " : "", size ); /* Unlock the output buffer. */ manager_unlock_output( manager, !(flags & VREQ_QUEUE) ); /* Wait for and lock the response buffer. */ if (flags & VREQ_RESPOND) { VoodooResponseMessage *response; ret = manager_lock_response( manager, serial, &response ); if (ret) { D_ERROR( "Voodoo/Manager: " "Waiting for the response failed (%s)!\n", DirectResultString( ret ) ); return ret; } D_DEBUG( "Voodoo/Manager: Got response %llu (%s) with instance %u for request %llu " "(%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( response->result ), response->instance, (unsigned long long)response->request, response->header.size ); *ret_response = response; } return DR_OK; }
DirectResult voodoo_manager_super( VoodooManager *manager, const char *name, VoodooInstanceID *ret_instance ) { DirectResult ret; int len; int size; void *ptr; VoodooMessageSerial serial; VoodooSuperMessage *msg; VoodooResponseMessage *response; D_MAGIC_ASSERT( manager, VoodooManager ); D_ASSERT( name != NULL ); D_ASSERT( ret_instance != NULL ); /* Calculate the total message size. */ len = strlen( name ) + 1; size = sizeof(VoodooSuperMessage) + len; /* Lock the output buffer for direct writing. */ ret = manager_lock_output( manager, size, &ptr ); if (ret) return ret; msg = ptr; serial = manager->msg_serial++; /* Fill message header. */ msg->header.size = size; msg->header.serial = serial; msg->header.type = VMSG_SUPER; /* Append the name of the super interface to create. */ direct_memcpy( msg + 1, name, len ); D_DEBUG( "Voodoo/Manager: Sending SUPER message %llu for '%s' (%d bytes).\n", (unsigned long long)serial, name, size ); /* Unlock the output buffer. */ manager_unlock_output( manager, true ); /* Wait for and lock the response buffer. */ ret = manager_lock_response( manager, serial, &response ); if (ret) { D_ERROR( "Voodoo/Manager: " "Waiting for the response failed (%s)!\n", DirectResultString( ret ) ); return ret; } D_DEBUG( "Voodoo/Manager: Got response %llu (%s) with instance %u for request %llu " "(%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( ret ), response->instance, (unsigned long long)response->request, response->header.size ); ret = response->result; if (ret) { D_ERROR( "Voodoo/Manager: Could not create remote super interface '%s' (%s)!\n", name, DirectResultString( ret ) ); manager_unlock_response( manager, response ); return ret; } D_INFO( "Voodoo/Manager: Created remote super interface '%s'.\n", name ); /* Return the new instance ID. */ *ret_instance = response->instance; /* Unlock the response buffer. */ manager_unlock_response( manager, response ); return DR_OK; }