static DFBResult dfb_rtd_set_video_mode( CoreDFB *core, CoreLayerRegionConfig *config ) { int ret; CoreLayerRegionConfig *tmp = NULL; D_ASSERT( config != NULL ); if (dfb_core_is_master( core )) return dfb_rtd_set_video_mode_handler( config ); if (!fusion_is_shared( dfb_core_world(core), config )) { tmp = SHMALLOC( dfb_core_shmpool(core), sizeof(CoreLayerRegionConfig) ); if (!tmp) return D_OOSHM(); direct_memcpy( tmp, config, sizeof(CoreLayerRegionConfig) ); } fusion_call_execute( &dfb_rtd->call, FCEF_NONE, RTD_SET_VIDEO_MODE, tmp ? tmp : config, &ret ); if (tmp) SHFREE( dfb_core_shmpool(core), tmp ); return ret; }
static DFBResult dfb_rtd_update_screen( CoreDFB *core, DFBRegion *region ) { int ret; DFBRegion *tmp = NULL; if (dfb_core_is_master( core )) return dfb_rtd_update_screen_handler( region ); if (region) { if (!fusion_is_shared( dfb_core_world(core), region )) { tmp = SHMALLOC( dfb_core_shmpool(core), sizeof(DFBRegion) ); if (!tmp) return D_OOSHM(); direct_memcpy( tmp, region, sizeof(DFBRegion) ); } } fusion_call_execute( &dfb_rtd->call, FCEF_NONE, RTD_UPDATE_SCREEN, tmp ? tmp : region, &ret ); if (tmp) SHFREE( dfb_core_shmpool(core), tmp ); return DFB_OK; }
DFBResult dfb_sdl_set_palette( CorePalette *palette ) { int ret; fusion_call_execute( &dfb_sdl->call, FCEF_NONE, SDL_SET_PALETTE, palette, &ret ); return ret; }
static DFBResult dfb_rtd_set_palette( CorePalette *palette ) { int ret; fusion_call_execute( &dfb_rtd->call, FCEF_NONE, RTD_SET_PALETTE, palette, &ret ); return ret; }
DirectResult fusion_call_execute2(FusionCall *call, FusionCallExecFlags flags, int call_arg, void *ptr, unsigned int length, int *ret_val) { return fusion_call_execute( call, flags, call_arg, ptr, ret_val ); }
static DFBResult dfb_x11_destroy_window( DFBX11 *x11 ) { int ret; DFBX11Shared *shared = x11->shared; if (fusion_call_execute( &shared->call, FCEF_NONE, X11_DESTROY_WINDOW, NULL, &ret )) return DFB_FUSION; return ret; }
static DFBResult dfb_x11_set_palette( DFBX11 *x11, X11LayerData *lds, CorePalette *palette ) { int ret; DFBX11Shared *shared = x11->shared; D_ASSERT( palette != NULL ); if (fusion_call_execute( &shared->call, FCEF_NONE, X11_SET_PALETTE, palette, &ret )) return DFB_FUSION; return ret; }
static DFBResult dfb_x11_destroy_window( DFBX11 *x11, X11LayerData *lds ) { int ret; DFBX11Shared *shared = x11->shared; DestroyData destroy; destroy.xw = &(lds->xw); if (fusion_call_execute( &shared->call, FCEF_NONE, X11_DESTROY_WINDOW, &destroy, &ret )) return DFB_FUSION; return ret; }
static DFBResult dfb_x11_create_window( DFBX11 *x11, const CoreLayerRegionConfig *config ) { int ret; DFBX11Shared *shared = x11->shared; D_ASSERT( config != NULL ); shared->setmode.config = *config; if (fusion_call_execute( &shared->call, FCEF_NONE, X11_CREATE_WINDOW, &shared->setmode, &ret )) return DFB_FUSION; return ret; }
DirectResult _fusion_ref_change (FusionRef *ref, int add, bool global) { DirectResult ret; D_ASSERT( ref != NULL ); D_ASSERT( add != 0 ); ret = fusion_skirmish_prevail( &ref->multi.builtin.lock ); if (ret) return ret; if (global) { if (ref->multi.builtin.global+add < 0) { D_BUG( "ref has no global references" ); fusion_skirmish_dismiss( &ref->multi.builtin.lock ); return DR_BUG; } ref->multi.builtin.global += add; } else { if (ref->multi.builtin.local+add < 0) { D_BUG( "ref has no local references" ); fusion_skirmish_dismiss( &ref->multi.builtin.lock ); return DR_BUG; } ref->multi.builtin.local += add; _fusion_add_local( _fusion_world(ref->multi.shared), ref, add ); } if (ref->multi.builtin.local+ref->multi.builtin.global == 0) { fusion_skirmish_notify( &ref->multi.builtin.lock ); if (ref->multi.builtin.call) { fusion_skirmish_dismiss( &ref->multi.builtin.lock ); return fusion_call_execute( ref->multi.builtin.call, FCEF_ONEWAY, ref->multi.builtin.call_arg, NULL, NULL ); } } fusion_skirmish_dismiss( &ref->multi.builtin.lock ); return DR_OK; }
DFBResult x11ImageDestroy( x11Image *image ) { int ret; D_MAGIC_ASSERT( image, x11Image ); if (fusion_call_execute( &dfb_x11->call, FCEF_NONE, X11_IMAGE_DESTROY, image, &ret )) return DFB_FUSION; if (ret) { D_DERROR( ret, "X11/Image: X11_IMAGE_DESTROY call failed!\n" ); return ret; } D_MAGIC_CLEAR( image ); return DFB_OK; }
DFBResult x11ImageInit( DFBX11 *x11, x11Image *image, int width, int height, DFBSurfacePixelFormat format ) { int ret; Visual *visual; DFBX11Shared *shared = x11->shared; if (!x11->use_shm) return DFB_UNSUPPORTED; /* Lookup visual. */ visual = x11->visuals[DFB_PIXELFORMAT_INDEX(format)]; if (!visual) return DFB_UNSUPPORTED; /* For probing. */ if (!image) return DFB_OK; image->width = width; image->height = height; image->format = format; image->depth = DFB_COLOR_BITS_PER_PIXEL( format ); D_MAGIC_SET( image, x11Image ); if (fusion_call_execute( &shared->call, FCEF_NONE, X11_IMAGE_INIT, image, &ret )) { D_MAGIC_CLEAR( image ); return DFB_FUSION; } if (ret) { D_DERROR( ret, "X11/Image: X11_IMAGE_INIT call failed!\n" ); D_MAGIC_CLEAR( image ); return ret; } return DFB_OK; }
static DFBResult dfb_x11_update_screen( DFBX11 *x11, const DFBRegion *region, CoreSurfaceBufferLock *lock ) { int ret; DFBX11Shared *shared = x11->shared; DFB_REGION_ASSERT( region ); D_ASSERT( lock != NULL ); /* FIXME: Just a hot fix! */ while (shared->update.lock) usleep( 10000 ); shared->update.region = *region; shared->update.lock = lock; if (fusion_call_execute( &shared->call, FCEF_NONE, X11_UPDATE_SCREEN, &shared->update, &ret )) return DFB_FUSION; return ret; }
DirectResult fusion_ref_down (FusionRef *ref, bool global) { D_ASSERT( ref != NULL ); direct_mutex_lock (&ref->single.lock); if (!ref->single.refs) { D_BUG( "no more references" ); direct_mutex_unlock (&ref->single.lock); return DR_BUG; } if (ref->single.destroyed) { direct_mutex_unlock (&ref->single.lock); return DR_DESTROYED; } if (! --ref->single.refs) { if (ref->single.call) { FusionCall *call = ref->single.call; if (call->handler) { fusion_call_execute( call, FCEF_NODIRECT | FCEF_ONEWAY, ref->single.call_arg, NULL, NULL ); direct_mutex_unlock( &ref->single.lock ); return DR_OK; } } else direct_waitqueue_broadcast (&ref->single.cond); } direct_mutex_unlock (&ref->single.lock); return DR_OK; }
int main( int argc, char *argv[] ) { DirectResult ret; FusionWorld *world; FusionCall call = {0}; FusionSHMPoolShared *pool; void *buffer; int i, max_busy = 0, active = 1; long long t1 = 0, t2; long long start = 0; long long bytes = 0; long long last_bytes = 0; unsigned long blocks = 0; unsigned long last_blocks = 0; unsigned long last_busy = 0; u32 checksum = 0; bool produce = true; int delay = 66000; if (parse_cmdline( argc, argv )) return -1; if (bit_rate) { int blocks_per_sec = (bit_rate * 1024 / 8) / block_size; if (blocks_per_sec < 100) delay = 900000 / blocks_per_sec - 2000; else delay = 300000 * 100 / blocks_per_sec; num_blocks = bit_rate * 1024 / 8 / block_size * delay / 900000; if (num_blocks > MAX_NUM_BLOCKS) num_blocks = MAX_NUM_BLOCKS; if (!num_blocks) { num_blocks = 1; delay = 970 * block_size / (bit_rate * 1024 / 8) * 1000 - 2000; } } sync(); if (run_busy) { pthread_create( &busy_thread, NULL, busy_loop, NULL ); printf( "Calibrating...\n" ); pthread_mutex_lock( &busy_lock ); for (i=0; i<7; i++) { int busy_rate; busy_count = 0; t1 = get_millis(); pthread_mutex_unlock( &busy_lock ); usleep( 300000 ); pthread_mutex_lock( &busy_lock ); t2 = get_millis(); busy_rate = busy_count * 1000 / (t2 - t1); if (busy_rate > max_busy) max_busy = busy_rate; } printf( "Calibrating done. (%d busy counts/sec)\n", max_busy ); } ret = fusion_enter( -1, 23, FER_MASTER, &world ); if (ret) return ret; ret = fusion_call_init( &call, call_handler, NULL, world ); if (ret) return ret; ret = fusion_shm_pool_create( world, "Stream Buffer", block_size + 8192, false, &pool ); if (ret) return ret; ret = fusion_shm_pool_allocate( pool, block_size, false, true, &buffer ); if (ret) return ret; /* * Do the fork() magic! */ if (do_fork) { fusion_world_set_fork_action( world, FFA_FORK ); switch (fork()) { case -1: D_PERROR( "fork() failed!\n" ); return -1; case 0: /* child continues as the producer */ run_busy = false; break; default: /* parent is the consumer (callback in Fusion Dispatch thread) */ produce = false; usleep( 50000 ); } fusion_world_set_fork_action( world, FFA_CLOSE ); } start = t1 = get_millis(); if (run_busy) { busy_count = 0; pthread_mutex_unlock( &busy_lock ); } #ifdef LINUX_2_4 delay -= 10000; #endif do { if (bit_rate || !produce) { if (delay > 10) usleep( delay ); } if (produce) { for (i=0; i<num_blocks; i++) { int n; u32 retsum; u32 *values = buffer; for (n=0; n<block_size/4; n++) { values[n] = n; checksum += n; } bytes += block_size; fusion_call_execute( &call, do_thread ? FCEF_NODIRECT : FCEF_NONE, 0, buffer, (int*) &retsum ); if (retsum != checksum) D_ERROR( "Checksum returned by consumer (0x%08x) does not match 0x%08x!\n", retsum, checksum ); } blocks += num_blocks; } t2 = get_millis(); if (t2 - t1 > 2000) { if (produce) { long long kbits = 0, avgkbits, total_time, diff_time, diff_bytes; printf( "\n\n\n" ); total_time = t2 - start; diff_time = t2 - t1; diff_bytes = bytes - last_bytes; avgkbits = (long long)bytes * 8LL * 1000LL / (long long)total_time / 1024LL; if (diff_time) kbits = (long long)diff_bytes * 8LL * 1000LL / (long long)diff_time / 1024LL; printf( "Total Time: %7lld ms\n", total_time ); printf( "Stream Size: %7lld kb\n", bytes / 1024 ); printf( "Stream Rate: %7lld kb/sec -> %lld.%03lld MBit (avg. %lld.%03lld MBit)\n", kbits / 8, (kbits * 1000 / 1024) / 1000, (kbits * 1000 / 1024) % 1000, (avgkbits * 1000 / 1024) / 1000, (avgkbits * 1000 / 1024) % 1000 ); printf( "\n" ); if (last_bytes && bit_rate) { long long diff_bytes = (bytes - last_bytes) * 1000 / (t2 - t1); long long need_bytes = bit_rate * 1024 / 8; if (diff_bytes) { int new_blocks = (num_blocks * need_bytes + diff_bytes/2) / diff_bytes; num_blocks = (new_blocks + num_blocks + 1) / 2; if (num_blocks > MAX_NUM_BLOCKS) num_blocks = MAX_NUM_BLOCKS; } } read_stat(); if (ftotal != ctotal && dtotal) { int load, aload; load = 1000 - didle * 1000 / dtotal; aload = 1000 - (cidle - fidle) * 1000 / (ctotal - ftotal); printf( "Overall Stats\n" ); printf( " Total Time: %7lld ms\n", t2 - start ); printf( " Block Size: %7ld\n", block_size ); printf( " Blocks/cycle: %7ld\n", num_blocks ); printf( " Blocks/second: %7lld\n", (blocks - last_blocks) * 1000 / diff_time ); printf( " Delay: %7d\n", delay ); printf( " CPU Load: %5d.%d %% (avg. %d.%d %%)\n", load / 10, load % 10, aload / 10, aload % 10 ); } last_bytes = bytes; last_blocks = blocks; } if (run_busy) { pthread_mutex_lock( &busy_lock ); if (last_busy) { int busy_diff; int busy_rate, busy_load; int abusy_rate, abusy_load; busy_diff = busy_count - last_busy; busy_rate = max_busy - (busy_diff * 1000 / (t2 - t1)); busy_load = busy_rate * 1000 / max_busy; abusy_rate = max_busy - (busy_count * 1000 / (t2 - start)); abusy_load = abusy_rate * 1000 / max_busy; printf( " Real CPU Load: %5d.%d %% (avg. %d.%d %%)\n", busy_load / 10, busy_load % 10, abusy_load / 10, abusy_load % 10 ); } last_busy = busy_count; pthread_mutex_unlock( &busy_lock ); } t1 = t2; } } while (active > 0); if (run_busy) { busy_alive = 0; pthread_join( busy_thread, NULL ); } return -1; }