void direct_thread_join( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSERT( thread->handle.thread != -1 ); D_ASSUME( !pthread_equal( thread->handle.thread, pthread_self() ) ); D_ASSUME( !thread->joining ); D_ASSUME( !thread->joined ); D_ASSUME( !thread->detached ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); if (thread->detached) { D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" ); return; } if (!thread->joining && !pthread_equal( thread->handle.thread, pthread_self() )) { thread->joining = true; D_DEBUG_AT( Direct_Thread, " -> joining...\n" ); pthread_join( thread->handle.thread, NULL ); thread->joined = true; D_DEBUG_AT( Direct_Thread, " -> joined.\n" ); } }
void direct_thread_deinit( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSUME( !pthread_equal( thread->handle.thread, pthread_self() ) ); D_ASSUME( !thread->detached ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); if (thread->detached) { D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" ); return; } if (!thread->joined && !pthread_equal( thread->handle.thread, pthread_self() )) { if (thread->canceled) D_DEBUG_AT( Direct_Thread, " -> cancled but not joined!\n" ); else { D_DEBUG_AT( Direct_Thread, " -> still running!\n" ); if (thread->name) D_ERROR( "Direct/Thread: Canceling '%s' (%d)!\n", thread->name, thread->tid ); else D_ERROR( "Direct/Thread: Canceling %d!\n", thread->tid ); #ifndef DIRECT_BUILD_NO_PTHREAD_CANCEL pthread_cancel( thread->handle.thread ); #endif } pthread_join( thread->handle.thread, NULL ); } }
void direct_thread_terminate( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSERT( thread->thread != -1 ); D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) ); D_ASSUME( !thread->canceled ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); thread->terminated = true; direct_thread_notify( thread ); }
DirectResult voodoo_manager_quit( VoodooManager *manager ) { D_MAGIC_ASSERT( manager, VoodooManager ); D_ASSUME( !manager->quit ); if (manager->quit) return DR_OK; D_DEBUG( "Voodoo/Manager: Quitting manager at %p!\n", manager ); /* Have all threads quit upon this. */ manager->quit = true; /* Acquire locks and wake up waiters. */ pthread_mutex_lock( &manager->input.lock ); pthread_cond_broadcast( &manager->input.wait ); pthread_mutex_unlock( &manager->input.lock ); pthread_mutex_lock( &manager->response.lock ); pthread_cond_broadcast( &manager->response.wait ); pthread_mutex_unlock( &manager->response.lock ); pthread_mutex_lock( &manager->output.lock ); pthread_cond_broadcast( &manager->output.wait ); pthread_mutex_unlock( &manager->output.lock ); return DR_OK; }
DFBResult dfb_core_get_graphics_state( CoreDFB *core, u32 object_id, CoreGraphicsState **ret_state ) { DFBResult ret; FusionObject *object; CoreDFBShared *shared; D_ASSUME( core != NULL ); D_ASSERT( ret_state != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); D_ASSERT( core->shared->graphics_state_pool != NULL ); ret = fusion_object_get( core->shared->graphics_state_pool, object_id, &object ); if (ret) return ret; *ret_state = (CoreGraphicsState*) object; return DFB_OK; }
CoreCleanup * dfb_core_cleanup_add( CoreDFB *core, CoreCleanupFunc func, void *data, bool emergency ) { CoreCleanup *cleanup; D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); cleanup = D_CALLOC( 1, sizeof(CoreCleanup) ); cleanup->func = func; cleanup->data = data; cleanup->emergency = emergency; direct_list_prepend( &core->cleanups, &cleanup->link ); return cleanup; }
DFBResult dfb_core_get_layer_region( CoreDFB *core, u32 object_id, CoreLayerRegion **ret_region ) { DFBResult ret; FusionObject *object; CoreDFBShared *shared; D_ASSUME( core != NULL ); D_ASSERT( ret_region != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); D_ASSERT( core->shared->layer_region_pool != NULL ); ret = fusion_object_get( core->shared->layer_region_pool, object_id, &object ); if (ret) return ret; *ret_region = (CoreLayerRegion*) object; return DFB_OK; }
DFBResult dfb_layer_region_disable( CoreLayerRegion *region ) { DFBResult ret; D_ASSERT( region != NULL ); /* Lock the region. */ if (dfb_layer_region_lock( region )) return DFB_FUSION; D_ASSUME( D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ) ); if (! D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) { dfb_layer_region_unlock( region ); return DFB_OK; } /* Unrealize the region if it's active. */ if (D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) { ret = unrealize_region( region ); if (ret) return ret; } /* Update the region's state. */ D_FLAGS_CLEAR( region->state, CLRSF_ENABLED ); /* Unlock the region. */ dfb_layer_region_unlock( region ); return DFB_OK; }
DFBResult dfb_layer_region_get_surface( CoreLayerRegion *region, CoreSurface **ret_surface ) { D_ASSERT( region != NULL ); D_ASSERT( ret_surface != NULL ); /* Lock the region. */ if (dfb_layer_region_lock( region )) return DFB_FUSION; D_ASSUME( region->surface != NULL ); /* Check for NULL surface. */ if (!region->surface) { dfb_layer_region_unlock( region ); return DFB_UNSUPPORTED; } /* Increase the surface's reference counter. */ if (dfb_surface_ref( region->surface )) { dfb_layer_region_unlock( region ); return DFB_FUSION; } /* Return the surface. */ *ret_surface = region->surface; /* Unlock the region. */ dfb_layer_region_unlock( region ); return DFB_OK; }
void dfb_colorhash_attach( DFBColorHashCore *core, CorePalette *palette ) { DFBColorHashCoreShared *shared; D_ASSUME( core != NULL ); if (core) { D_MAGIC_ASSERT( core, DFBColorHashCore ); D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); } else core = core_colorhash; shared = core->shared; fusion_skirmish_prevail( &shared->hash_lock ); if (!shared->hash) { D_ASSERT( shared->hash_users == 0 ); shared->hash = SHCALLOC( shared->shmpool, HASH_SIZE, sizeof (Colorhash) ); } shared->hash_users++; fusion_skirmish_dismiss( &shared->hash_lock ); }
void dfb_colorhash_detach( DFBColorHashCore *core, CorePalette *palette ) { DFBColorHashCoreShared *shared; D_ASSUME( core != NULL ); if (core) { D_MAGIC_ASSERT( core, DFBColorHashCore ); D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); } else core = core_colorhash; shared = core->shared; D_ASSERT( shared->hash_users > 0 ); D_ASSERT( shared->hash != NULL ); fusion_skirmish_prevail( &shared->hash_lock ); shared->hash_users--; if (!shared->hash_users) { /* no more users, free allocated resources */ SHFREE( shared->shmpool, shared->hash ); shared->hash = NULL; } fusion_skirmish_dismiss( &shared->hash_lock ); }
void VoodooConnectionLink::Stop() { D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p )\n", __func__, this ); D_MAGIC_ASSERT( this, VoodooConnection ); direct_mutex_lock( &output.lock ); while (output.packets) { VoodooPacket *packet = (VoodooPacket*) output.packets; D_DEBUG_AT( Voodoo_Connection, " -> discarding output packet %p\n", packet ); D_ASSUME( packet->sending ); packet->sending = false; direct_list_remove( &output.packets, &packet->link ); } direct_mutex_unlock( &output.lock ); direct_waitqueue_broadcast( &output.wait ); }
DirectResult direct_serial_notify( DirectSerial *serial, const DirectSerial *source ) { D_ASSERT( serial != NULL ); D_ASSERT( source != NULL ); D_DEBUG_AT( Direct_Serial_Notify, " ###### %s( %p, %p ) ### %lu <-= %lu ### ### ###\n", __FUNCTION__, serial, source, serial->value, source->value ); D_MAGIC_ASSERT( serial, DirectSerial ); D_MAGIC_ASSERT( source, DirectSerial ); D_ASSERT( serial->overflow <= source->overflow ); D_ASSERT( serial->overflow == source->overflow || serial->value != source->value ); if (serial->overflow < source->overflow) { serial->overflow = source->overflow; serial->value = source->value; } else if (serial->overflow == source->overflow && serial->value < source->value) serial->value = source->value; else { D_ASSUME( serial->value == source->value ); return DR_OK; } if (serial->waiting > 0) { D_SYNC_ADD( &serial->wakeup, 1 ); return direct_futex_wake( &serial->wakeup, 1024 ); } return DR_OK; }
DFBResult dfb_core_get_window( CoreDFB *core, u32 object_id, CoreWindow **ret_window ) { DFBResult ret; FusionObject *object; CoreDFBShared *shared; D_ASSUME( core != NULL ); D_ASSERT( ret_window != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); D_ASSERT( core->shared->window_pool != NULL ); ret = fusion_object_get( core->shared->window_pool, object_id, &object ); if (ret) return ret; *ret_window = (CoreWindow*) object; return DFB_OK; }
DFBResult dfb_screen_test_output_config( CoreScreen *screen, int output, const DFBScreenOutputConfig *config, DFBScreenOutputConfigFlags *ret_failed ) { DFBResult ret; DFBScreenOutputConfigFlags failed = DSOCONF_NONE; D_ASSERT( screen != NULL ); D_ASSERT( screen->shared != NULL ); D_ASSERT( screen->funcs != NULL ); D_ASSERT( screen->funcs->TestOutputConfig != NULL ); D_ASSERT( output >= 0 ); D_ASSERT( output < screen->shared->description.outputs ); D_ASSERT( config != NULL ); D_ASSERT( config->flags == screen->shared->outputs[output].configuration.flags ); /* Test the output configuration. */ ret = screen->funcs->TestOutputConfig( screen, screen->driver_data, screen->screen_data, output, config, &failed ); D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); if (ret_failed) *ret_failed = failed; return ret; }
DFBResult dfb_screen_test_encoder_config( CoreScreen *screen, int encoder, const DFBScreenEncoderConfig *config, DFBScreenEncoderConfigFlags *ret_failed ) { DFBResult ret; DFBScreenEncoderConfigFlags failed = DSECONF_NONE; D_ASSERT( screen != NULL ); D_ASSERT( screen->shared != NULL ); D_ASSERT( screen->funcs != NULL ); D_ASSERT( screen->funcs->TestEncoderConfig != NULL ); D_ASSERT( encoder >= 0 ); D_ASSERT( encoder < screen->shared->description.encoders ); D_ASSERT( config != NULL ); D_ASSERT( config->flags == screen->shared->encoders[encoder].configuration.flags ); /* Test the encoder configuration. */ ret = screen->funcs->TestEncoderConfig( screen, screen->driver_data, screen->screen_data, encoder, config, &failed ); D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); if (ret_failed) *ret_failed = failed; return ret; }
DirectResult fusion_shm_deinit( FusionWorld *world ) { int i; DirectResult ret; FusionSHM *shm; FusionSHMShared *shared; D_MAGIC_ASSERT( world, FusionWorld ); shm = &world->shm; D_MAGIC_ASSERT( shm, FusionSHM ); shared = shm->shared; D_MAGIC_ASSERT( shared, FusionSHMShared ); ret = fusion_skirmish_prevail( &shared->lock ); if (ret) return ret; /* Deinitialize shared data. */ if (fusion_master( world )) { D_ASSUME( shared->num_pools == 0 ); for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { if (shared->pools[i].active) { D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); D_WARN( "destroying remaining '%s'", shared->pools[i].name ); fusion_shm_pool_destroy( world, &shared->pools[i] ); } } /* Destroy shared lock. */ fusion_skirmish_destroy( &shared->lock ); D_MAGIC_CLEAR( shared ); } else { for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { if (shared->pools[i].active) { D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); fusion_shm_pool_detach( shm, &shared->pools[i] ); } } fusion_skirmish_dismiss( &shared->lock ); } D_MAGIC_CLEAR( shm ); return DR_OK; }
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; } }
DirectResult fusion_property_cede (FusionProperty *property) { D_ASSERT( property != NULL ); if (property->multi.builtin.destroyed) return DR_DESTROYED; D_ASSUME( property->multi.builtin.state != FUSION_PROPERTY_AVAILABLE ); D_ASSUME( property->multi.builtin.owner == direct_gettid() ); property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE; property->multi.builtin.owner = 0; asm( "" ::: "memory" ); if (property->multi.builtin.requested) { property->multi.builtin.requested = false; asm( "" ::: "memory" ); direct_sched_yield(); }
void direct_thread_unlock( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSERT( thread->thread != -1 ); D_ASSUME( !thread->canceled ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); pthread_mutex_unlock( &thread->lock ); }
FusionArena * dfb_core_arena( CoreDFB *core ) { D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); return core->arena; }
DFBFontManager * dfb_core_font_manager( CoreDFB *core ) { D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); return core->font_manager; }
void direct_thread_destroy( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) ); D_ASSUME( !thread->detached ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); if (thread->detached) { D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" ); return; } if (!thread->joined && !pthread_equal( thread->thread, pthread_self() )) { if (thread->canceled) D_DEBUG_AT( Direct_Thread, " -> cancled but not joined!\n" ); else { D_DEBUG_AT( Direct_Thread, " -> still running!\n" ); if (thread->name) D_ERROR( "Direct/Thread: Canceling '%s' (%d)!\n", thread->name, thread->tid ); else D_ERROR( "Direct/Thread: Canceling %d!\n", thread->tid ); thread->detached = true; pthread_detach( thread->thread ); pthread_cancel( thread->thread ); return; } } D_MAGIC_CLEAR( thread ); D_FREE( thread->name ); D_FREE( thread ); }
DirectResult fusion_property_purchase (FusionProperty *property) { int count = 0; D_ASSERT( property != NULL ); if (property->multi.builtin.destroyed) return DR_DESTROYED; D_ASSUME( property->multi.builtin.owner != direct_gettid() ); asm( "" ::: "memory" ); while (property->multi.builtin.state == FUSION_PROPERTY_LEASED) { /* Check whether owner exited without releasing. */ if (kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) { property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE; property->multi.builtin.requested = false; break; } property->multi.builtin.requested = true; asm( "" ::: "memory" ); if (++count > 1000) { usleep( 10000 ); count = 0; } else { direct_sched_yield(); } if (property->multi.builtin.destroyed) return DR_DESTROYED; } if (property->multi.builtin.state == FUSION_PROPERTY_PURCHASED) { /* Check whether owner exited without releasing. */ if (!(kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH)) return DR_BUSY; } property->multi.builtin.state = FUSION_PROPERTY_PURCHASED; property->multi.builtin.owner = direct_gettid(); asm( "" ::: "memory" ); return DR_OK; }
void direct_thread_detach( DirectThread *thread ) { D_MAGIC_ASSERT( thread, DirectThread ); D_ASSERT( !pthread_equal( thread->handle.thread, pthread_self() ) ); D_ASSUME( !thread->canceled ); D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid ); thread->detached = true; pthread_detach( thread->handle.thread ); }
VoodooPacket * VoodooConnectionLink::GetPacket( size_t length ) { D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p, length "_ZU" )\n", __func__, this, length ); D_MAGIC_ASSERT( this, VoodooConnection ); D_ASSERT( length >= (int) sizeof(VoodooMessageHeader) ); D_ASSUME( length <= MAX_MSG_SIZE ); if (length > MAX_MSG_SIZE) { D_WARN( _ZU" exceeds maximum message size of %d", length, MAX_MSG_SIZE ); return NULL; } size_t aligned = VOODOO_MSG_ALIGN( length ); Packets *packets = (Packets*) direct_tls_get( output.tls ); if (!packets) { packets = new Packets( this ); direct_tls_set( output.tls, packets ); } VoodooPacket *packet = packets->active; if (packet) { if (packet->append( aligned )) return packet; Flush( packet ); } packet = packets->Get(); if (packet) { if (packet->sending) { direct_mutex_lock( &output.lock ); while (packet->sending) direct_waitqueue_wait( &output.wait, &output.lock ); direct_mutex_unlock( &output.lock ); } packet->reset( aligned ); } return packet; }
void dfb_core_cleanup_remove( CoreDFB *core, CoreCleanup *cleanup ) { D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); direct_list_remove( &core->cleanups, &cleanup->link ); D_FREE( cleanup ); }
DFBResult dfb_core_resume( CoreDFB *core ) { DFBResult ret; D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); if (!core->master) return DFB_ACCESSDENIED; if (!core->suspended) return DFB_BUSY; ret = dfb_graphics_core.Resume( dfb_graphics_core.data_local ); if (ret) goto error_graphics; ret = dfb_screen_core.Resume( dfb_screen_core.data_local ); if (ret) goto error_screens; ret = dfb_layer_core.Resume( dfb_layer_core.data_local ); if (ret) goto error_layers; ret = dfb_input_core.Resume( dfb_input_core.data_local ); if (ret) goto error_input; core->suspended = false; return DFB_OK; error_input: dfb_layer_core.Suspend( dfb_layer_core.data_local ); error_layers: dfb_screen_core.Suspend( dfb_screen_core.data_local ); error_screens: dfb_graphics_core.Suspend( dfb_graphics_core.data_local ); error_graphics: return ret; }
DirectResult fusion_call_return3( FusionCall *call, unsigned int serial, void *ptr, unsigned int length ) { FusionCallReturn3 call_ret; D_DEBUG_AT( Fusion_Call, "%s( %p, serial %u, ptr %p, length %u )\n", __FUNCTION__, call, serial, ptr, length ); D_ASSERT( call != NULL ); if (direct_log_domain_check( &Fusion_Call )) // avoid call to direct_trace_lookup_symbol_at D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) ); D_ASSUME( serial != 0 ); if (!serial) return DR_UNSUPPORTED; call_ret.call_id = call->call_id; call_ret.serial = serial; call_ret.ptr = ptr; call_ret.length = length; fusion_world_flush_calls( _fusion_world( call->shared ), 1 ); while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_RETURN3, &call_ret)) { switch (errno) { case EINTR: continue; case EIDRM: D_WARN( "caller withdrawn (signal?)" ); return DR_NOCONTEXT; case EINVAL: D_ERROR( "Fusion/Call: invalid call\n" ); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_RETURN3"); return DR_FAILURE; } return DR_OK; }
FusionSHMPoolShared * dfb_core_shmpool_data( CoreDFB *core ) { CoreDFBShared *shared; D_ASSUME( core != NULL ); if (!core) core = core_dfb; D_MAGIC_ASSERT( core, CoreDFB ); shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); return shared->shmpool_data; }