DirectResult fusion_ref_init (FusionRef *ref, const char *name, const FusionWorld *world) { D_ASSERT( ref != NULL ); D_ASSERT( name != NULL ); D_MAGIC_ASSERT( world, FusionWorld ); D_DEBUG_AT( Fusion_Ref, "fusion_ref_init( %p, '%s' )\n", ref, name ? : "" ); ref->multi.id = ++world->shared->ref_ids; ref->multi.builtin.local = 0; ref->multi.builtin.global = 0; fusion_skirmish_init( &ref->multi.builtin.lock, name, world ); ref->multi.builtin.call = NULL; /* Keep back pointer to shared world data. */ ref->multi.shared = world->shared; ref->multi.creator = fusion_id( world ); return DR_OK; }
static DFBResult system_initialize( CoreDFB *core, void **data ) { char *driver; CoreScreen *screen; D_ASSERT( dfb_osx == NULL ); dfb_osx = (DFBOSX*) SHCALLOC( dfb_core_shmpool(dfb_osx_core), 1, sizeof(DFBOSX) ); if (!dfb_osx) { D_ERROR( "DirectFB/OSX: Couldn't allocate shared memory!\n" ); return D_OOSHM(); } dfb_osx_core = core; /* Initialize OSX */ fusion_skirmish_init( &dfb_osx->lock, "OSX System", dfb_core_world(core) ); fusion_call_init( &dfb_osx->call, dfb_osx_call_handler, NULL, dfb_core_world(core) ); screen = dfb_screens_register( NULL, NULL, &osxPrimaryScreenFuncs ); dfb_layers_register( screen, NULL, &osxPrimaryLayerFuncs ); fusion_arena_add_shared_field( dfb_core_arena( core ), "OSX", dfb_osx ); *data = dfb_osx; return DFB_OK; }
static void bench_skirmish() { DirectResult ret; FusionSkirmish skirmish; ret = fusion_skirmish_init( &skirmish, "Benchmark", world ); if (ret) { fprintf( stderr, "Fusion Error %d\n", ret ); return; } /* skirmish prevail/dismiss */ BENCH_START(); BENCH_LOOP() { fusion_skirmish_prevail( &skirmish ); fusion_skirmish_dismiss( &skirmish ); } BENCH_STOP(); printf( "skirmish prevail/dismiss -> %8.2f k/sec\n", BENCH_RESULT() ); fusion_skirmish_destroy( &skirmish ); printf( "\n" ); }
DirectResult fusion_skirmish_init2( FusionSkirmish *skirmish, const char *name, const FusionWorld *world, bool local ) { D_ASSERT( skirmish != NULL ); D_ASSERT( name != NULL ); D_MAGIC_ASSERT( world, FusionWorld ); D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_init2( %p, '%s', %s )\n", skirmish, name ? : "", local ? "local" : "shared" ); if (!local) return fusion_skirmish_init( skirmish, name, world ); skirmish->single = D_CALLOC( 1, sizeof(FusionSkirmishSingle) + strlen(name) + 1 ); if (skirmish->single == 0) return DR_NOLOCALMEMORY; skirmish->single->name = (char*)(skirmish->single + 1); strcpy( skirmish->single->name, name ); direct_util_recursive_pthread_mutex_init( &skirmish->single->lock ); pthread_cond_init( &skirmish->single->cond, NULL ); /* Keep back pointer to shared world data. */ skirmish->multi.shared = world->shared; return DR_OK; }
static DFBResult system_initialize( CoreDFB *core, void **data ) { CoreScreen *core_screen; D_ASSERT( dfb_vnc == NULL ); dfb_vnc = (DFBVNC*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBVNC) ); if (!dfb_vnc) { D_ERROR( "DirectFB/VNC: Couldn't allocate shared memory!\n" ); return D_OOSHM(); } dfb_vnc_core = core; fusion_skirmish_init( &dfb_vnc->lock, "VNC System", dfb_core_world(core) ); fusion_call_init( &dfb_vnc->call, dfb_vnc_call_handler, NULL, dfb_core_world(core) ); core_screen = dfb_screens_register( NULL, NULL, &vncPrimaryScreenFuncs ); dfb_layers_register( core_screen, NULL, &vncPrimaryLayerFuncs ); fusion_arena_add_shared_field( dfb_core_arena( core ), "vnc", dfb_vnc ); *data = dfb_vnc; return DFB_OK; }
static int dfb_core_arena_initialize( FusionArena *arena, void *ctx ) { DFBResult ret; CoreDFB *core = ctx; CoreDFBShared *shared; FusionSHMPoolShared *pool; D_MAGIC_ASSERT( core, CoreDFB ); D_DEBUG_AT( DirectFB_Core, "Initializing...\n" ); /* Create the shared memory pool first! */ ret = fusion_shm_pool_create( core->world, "DirectFB Main Pool", 0x400000, fusion_config->debugshm, &pool ); if (ret) return ret; /* Allocate shared structure in the new pool. */ shared = SHCALLOC( pool, 1, sizeof(CoreDFBShared) ); if (!shared) { fusion_shm_pool_destroy( core->world, pool ); return D_OOSHM(); } core->shared = shared; core->master = true; shared->shmpool = pool; D_MAGIC_SET( shared, CoreDFBShared ); /* Initialize. */ ret = dfb_core_initialize( core ); if (ret) { D_MAGIC_CLEAR( shared ); SHFREE( pool, shared ); fusion_shm_pool_destroy( core->world, pool ); return ret; } fusion_skirmish_init( &shared->lock, "DirectFB Core", core->world ); CoreDFB_Init_Dispatch( core, core, &shared->call ); fusion_call_add_permissions( &shared->call, 0, FUSION_CALL_PERMIT_EXECUTE ); /* Register shared data. */ fusion_arena_add_shared_field( arena, "Core/Shared", shared ); return DFB_OK; }
static DFBResult system_initialize( CoreDFB *core, void **data ) { char *driver; CoreScreen *screen; D_ASSERT( dfb_sdl == NULL ); dfb_sdl = (DFBSDL*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBSDL) ); if (!dfb_sdl) { D_ERROR( "DirectFB/SDL: Couldn't allocate shared memory!\n" ); return D_OOSHM(); } dfb_sdl_core = core; dfb_fbdev_read_modes(); /* use same mode list as a fake */ driver = getenv( "SDL_VIDEODRIVER" ); if (driver && !strcasecmp( driver, "directfb" )) { D_INFO( "DirectFB/SDL: SDL_VIDEODRIVER is 'directfb', unsetting it.\n" ); unsetenv( "SDL_VIDEODRIVER" ); } /* Initialize SDL */ if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { D_ERROR( "DirectFB/SDL: Couldn't initialize SDL: %s\n", SDL_GetError() ); SHFREE( dfb_core_shmpool(core), dfb_sdl ); dfb_sdl = NULL; return DFB_INIT; } fusion_skirmish_init( &dfb_sdl->lock, "SDL System", dfb_core_world(core) ); fusion_call_init( &dfb_sdl->call, dfb_sdl_call_handler, NULL, dfb_core_world(core) ); screen = dfb_screens_register( NULL, NULL, sdlPrimaryScreenFuncs ); dfb_layers_register( screen, NULL, sdlPrimaryLayerFuncs ); fusion_arena_add_shared_field( dfb_core_arena( core ), "sdl", dfb_sdl ); dfb_surface_pool_initialize( core, &sdlSurfacePoolFuncs, &dfb_sdl->sdl_pool ); *data = dfb_sdl; return DFB_OK; }
DFBResult dfb_layer_region_create( CoreLayerContext *context, CoreLayerRegion **ret_region ) { CoreLayer *layer; CoreLayerRegion *region; D_ASSERT( context != NULL ); D_ASSERT( ret_region != NULL ); layer = dfb_layer_at( context->layer_id ); /* Create the object. */ region = dfb_core_create_layer_region( layer->core ); if (!region) return DFB_FUSION; /* Link the context into the structure. */ if (dfb_layer_context_link( ®ion->context, context )) { fusion_object_destroy( ®ion->object ); return DFB_FUSION; } /* Initialize the lock. */ if (fusion_skirmish_init( ®ion->lock, "Layer Region", dfb_core_world(layer->core) )) { dfb_layer_context_unlink( ®ion->context ); fusion_object_destroy( ®ion->object ); return DFB_FUSION; } /* Change global reaction lock. */ fusion_object_set_lock( ®ion->object, ®ion->lock ); region->state = CLRSF_FROZEN; /* Activate the object. */ fusion_object_activate( ®ion->object ); /* Add the region to the context. */ dfb_layer_context_add_region( context, region ); /* Return the new region. */ *ret_region = region; return DFB_OK; }
static DFBResult dfb_clipboard_core_initialize( CoreDFB *core, DFBClipboardCore *data, DFBClipboardCoreShared *shared ) { D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_initialize( %p, %p, %p )\n", core, data, shared ); D_ASSERT( data != NULL ); D_ASSERT( shared != NULL ); data->core = core; data->shared = shared; shared->shmpool = dfb_core_shmpool( core ); fusion_skirmish_init( &shared->lock, "Clipboard Core", dfb_core_world(core) ); D_MAGIC_SET( data, DFBClipboardCore ); D_MAGIC_SET( shared, DFBClipboardCoreShared ); return DFB_OK; }
SurfaceManager * dfb_surfacemanager_create( unsigned int length, CardLimitations *limits ) { Chunk *chunk; SurfaceManager *manager; manager = SHCALLOC( 1, sizeof(SurfaceManager) ); if (!manager) return NULL; chunk = SHCALLOC( 1, sizeof(Chunk) ); if (!chunk) { SHFREE( manager ); return NULL; } chunk->offset = 0; chunk->length = length; manager->chunks = chunk; manager->length = length; manager->available = length; manager->byteoffset_align = limits->surface_byteoffset_alignment; manager->pixelpitch_align = limits->surface_pixelpitch_alignment; manager->bytepitch_align = limits->surface_bytepitch_alignment; manager->max_power_of_two_pixelpitch = limits->surface_max_power_of_two_pixelpitch; manager->max_power_of_two_bytepitch = limits->surface_max_power_of_two_bytepitch; manager->max_power_of_two_height = limits->surface_max_power_of_two_height; fusion_skirmish_init( &manager->lock, "Surface Manager" ); D_MAGIC_SET( chunk, _Chunk_ ); D_MAGIC_SET( manager, SurfaceManager ); return manager; }
static void bench_skirmish_threaded() { int i; DirectResult ret; FusionSkirmish skirmish; ret = fusion_skirmish_init( &skirmish, "Threaded Benchmark", world ); if (ret) { fprintf( stderr, "Fusion Error %d\n", ret ); return; } /* skirmish prevail/dismiss (2-5 threads) */ for (i=2; i<=5; i++) { int t; pthread_t threads[i]; BENCH_START(); for (t=0; t<i; t++) pthread_create( &threads[t], NULL, prevail_dismiss_loop, &skirmish ); for (t=0; t<i; t++) pthread_join( threads[t], NULL ); BENCH_STOP(); printf( "skirmish prevail/dismiss (%d threads) -> %8.2f k/sec\n", i, BENCH_RESULT() ); } fusion_skirmish_destroy( &skirmish ); printf( "\n" ); }
static DFBResult dfb_colorhash_core_initialize( CoreDFB *core, DFBColorHashCore *data, DFBColorHashCoreShared *shared ) { D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_initialize( %p, %p, %p )\n", core, data, shared ); D_ASSERT( data != NULL ); D_ASSERT( shared != NULL ); core_colorhash = data; /* FIXME */ data->core = core; data->shared = shared; shared->shmpool = dfb_core_shmpool( core ); fusion_skirmish_init( &shared->hash_lock, "Colorhash Core", dfb_core_world(core) ); D_MAGIC_SET( data, DFBColorHashCore ); D_MAGIC_SET( shared, DFBColorHashCoreShared ); return DFB_OK; }
DirectResult fusion_shm_init( FusionWorld *world ) { int i; int num; DirectResult ret; FusionSHM *shm; FusionSHMShared *shared; D_MAGIC_ASSERT( world, FusionWorld ); D_MAGIC_ASSERT( world->shared, FusionWorldShared ); shm = &world->shm; shared = &world->shared->shm; /* Initialize local data. */ memset( shm, 0, sizeof(FusionSHM) ); shm->world = world; shm->shared = shared; /* Initialize shared data. */ if (fusion_master( world )) { memset( shared, 0, sizeof(FusionSHMShared) ); if (fusion_config->tmpfs) { snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, fusion_config->tmpfs ); } else if (!find_tmpfs( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN )) { D_ERROR( "Fusion/SHM: Could not find tmpfs mount point, falling back to /dev/shm!\n" ); snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, "/dev/shm" ); } shared->world = world->shared; /* Initialize shared lock. */ ret = fusion_skirmish_init( &shared->lock, "Fusion SHM", world ); if (ret) { D_DERROR( ret, "Fusion/SHM: Failed to create skirmish!\n" ); return ret; } /* Initialize static pool array. */ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) shared->pools[i].index = i; D_MAGIC_SET( shm, FusionSHM ); D_MAGIC_SET( shared, FusionSHMShared ); } else { D_MAGIC_ASSERT( shared, FusionSHMShared ); ret = fusion_skirmish_prevail( &shared->lock ); if (ret) return ret; D_MAGIC_SET( shm, FusionSHM ); for (i=0, num=0; i<FUSION_SHM_MAX_POOLS; i++) { if (shared->pools[i].active) { D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); ret = fusion_shm_pool_attach( shm, &shared->pools[i] ); if (ret) { for (--i; i>=0; i--) { if (shared->pools[i].active) fusion_shm_pool_detach( shm, &shared->pools[i] ); } fusion_skirmish_dismiss( &shared->lock ); D_MAGIC_CLEAR( shm ); return ret; } num++; } } D_ASSERT( num == shared->num_pools ); fusion_skirmish_dismiss( &shared->lock ); } return DR_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 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 DirectResult init_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared, const char *name, unsigned int max_size, bool debug ) { DirectResult ret; int fd; int size; FusionWorld *world; FusionSHMPoolNew pool_new = { .pool_id = 0 }; FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; FusionEntryInfo info; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_ASSERT( name != NULL ); D_ASSERT( max_size > sizeof(shmalloc_heap) ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); D_ASSERT( pool != NULL ); D_ASSERT( shared != NULL ); /* Fill out information for new pool. */ pool_new.max_size = max_size; pool_new.max_size += BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); /* Create the new pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_NEW, &pool_new )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_NEW failed!\n" ); return DR_FUSION; } /* Set the pool info. */ info.type = FT_SHMPOOL; info.id = pool_new.pool_id; snprintf( info.name, sizeof(info.name), "%s", name ); ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info ); /* Set pool to attach to. */ pool_attach.pool_id = pool_new.pool_id; /* Attach to the pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } return DR_FUSION; } /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( shm->world ), pool_new.pool_id ); /* Initialize the heap. */ ret = __shmalloc_init_heap( shm, buf, pool_new.addr_base, max_size, &fd, &size ); if (ret) { while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } return ret; } /* Initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = pool_new.pool_id; pool->fd = fd; pool->filename = D_STRDUP( buf ); /* Initialize shared data. */ shared->active = true; shared->debug = debug; shared->shm = shm->shared; shared->max_size = pool_new.max_size; shared->pool_id = pool_new.pool_id; shared->addr_base = pool_new.addr_base; shared->heap = pool_new.addr_base; shared->heap->pool = shared; fusion_skirmish_init( &shared->lock, name, world ); D_MAGIC_SET( pool, FusionSHMPool ); D_MAGIC_SET( shared, FusionSHMPoolShared ); shared->name = SHSTRDUP( shared, name ); return DR_OK; } static DirectResult join_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { DirectResult ret; int fd; FusionWorld *world; FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); #if !DIRECT_BUILD_DEBUGS if (shared->debug) { D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" ); return DR_UNSUPPORTED; } #endif world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); /* Set pool to attach to. */ pool_attach.pool_id = shared->pool_id; /* Attach to the pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); return DR_FUSION; } /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( shm->world ), shared->pool_id ); /* Join the heap. */ ret = __shmalloc_join_heap( shm, buf, pool_attach.addr_base, shared->max_size, &fd ); if (ret) { while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); break; } } return ret; } /* Initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = shared->pool_id; pool->fd = fd; pool->filename = D_STRDUP( buf ); D_MAGIC_SET( pool, FusionSHMPool ); return DR_OK; } static void leave_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { FusionWorld *world; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( pool, FusionSHMPool ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); break; } } if (munmap( shared->addr_base, shared->max_size )) D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); if (pool->fd != -1 && close( pool->fd )) D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); pool->attached = false; D_FREE( pool->filename ); D_MAGIC_CLEAR( pool ); } static void shutdown_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { FusionWorld *world; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( pool, FusionSHMPool ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); SHFREE( shared, shared->name ); fusion_dbg_print_memleaks( shared ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } if (munmap( shared->addr_base, shared->max_size )) D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); if (pool->fd != -1 && close( pool->fd )) D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); if (unlink( pool->filename )) D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename ); shared->active = false; pool->attached = false; D_FREE( pool->filename ); D_MAGIC_CLEAR( pool ); fusion_skirmish_destroy( &shared->lock ); D_MAGIC_CLEAR( shared ); }
DFBResult dfb_surface_create( CoreDFB *core, const CoreSurfaceConfig *config, CoreSurfaceTypeFlags type, unsigned long resource_id, CorePalette *palette, CoreSurface **ret_surface ) { DFBResult ret = DFB_BUG; int i; int buffers; CoreSurface *surface; char buf[64]; D_ASSERT( core != NULL ); D_FLAGS_ASSERT( type, CSTF_ALL ); D_MAGIC_ASSERT_IF( palette, CorePalette ); D_ASSERT( ret_surface != NULL ); D_DEBUG_AT( Core_Surface, "dfb_surface_create( %p, %p, %p )\n", core, config, ret_surface ); surface = dfb_core_create_surface( core ); if (!surface) return DFB_FUSION; if (config) { D_FLAGS_ASSERT( config->flags, CSCONF_ALL ); surface->config.flags = config->flags; if (config->flags & CSCONF_SIZE) { D_DEBUG_AT( Core_Surface, " -> %dx%d\n", config->size.w, config->size.h ); surface->config.size = config->size; } if (config->flags & CSCONF_FORMAT) { D_DEBUG_AT( Core_Surface, " -> %s\n", dfb_pixelformat_name( config->format ) ); surface->config.format = config->format; } if (config->flags & CSCONF_CAPS) { D_DEBUG_AT( Core_Surface, " -> caps 0x%08x\n", config->caps ); surface->config.caps = config->caps; } if (config->flags & CSCONF_PREALLOCATED) { D_DEBUG_AT( Core_Surface, " -> prealloc %p [%d]\n", config->preallocated[0].addr, config->preallocated[0].pitch ); direct_memcpy( surface->config.preallocated, config->preallocated, sizeof(config->preallocated) ); type |= CSTF_PREALLOCATED; } } if (surface->config.caps & DSCAPS_SYSTEMONLY) surface->type = (type & ~CSTF_EXTERNAL) | CSTF_INTERNAL; else if (surface->config.caps & DSCAPS_VIDEOONLY) surface->type = (type & ~CSTF_INTERNAL) | CSTF_EXTERNAL; else surface->type = type & ~(CSTF_INTERNAL | CSTF_EXTERNAL); if (surface->config.caps & DSCAPS_SHARED) surface->type |= CSTF_SHARED; surface->resource_id = resource_id; if (surface->config.caps & DSCAPS_TRIPLE) buffers = 3; else if (surface->config.caps & DSCAPS_DOUBLE) buffers = 2; else buffers = 1; surface->notifications = CSNF_ALL & ~CSNF_FLIP; surface->alpha_ramp[0] = 0x00; surface->alpha_ramp[1] = 0x55; surface->alpha_ramp[2] = 0xaa; surface->alpha_ramp[3] = 0xff; if (surface->config.caps & DSCAPS_STATIC_ALLOC) surface->config.min_size = surface->config.size; surface->shmpool = dfb_core_shmpool( core ); direct_serial_init( &surface->serial ); snprintf( buf, sizeof(buf), "Surface %dx%d %s", surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(surface->config.format) ); fusion_ref_set_name( &surface->object.ref, buf ); fusion_skirmish_init( &surface->lock, buf, dfb_core_world(core) ); fusion_object_set_lock( &surface->object, &surface->lock ); D_MAGIC_SET( surface, CoreSurface ); if (dfb_config->warn.flags & DCWF_CREATE_SURFACE && dfb_config->warn.create_surface.min_size.w <= surface->config.size.w && dfb_config->warn.create_surface.min_size.h <= surface->config.size.h) D_WARN( "create-surface %4dx%4d %6s, buffers %d, caps 0x%08x, type 0x%08x", surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(surface->config.format), buffers, surface->config.caps, surface->type ); if (palette) { dfb_surface_set_palette( surface, palette ); } else if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) { ret = dfb_surface_init_palette( core, surface ); if (ret) goto error; } /* Create the Surface Buffers. */ for (i=0; i<buffers; i++) { CoreSurfaceBuffer *buffer; ret = dfb_surface_buffer_new( surface, CSBF_NONE, &buffer ); if (ret) { D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" ); goto error; } surface->buffers[surface->num_buffers++] = buffer; switch (i) { case 0: surface->buffer_indices[CSBR_FRONT] = i; case 1: surface->buffer_indices[CSBR_BACK] = i; case 2: surface->buffer_indices[CSBR_IDLE] = i; } } fusion_object_activate( &surface->object ); *ret_surface = surface; return DFB_OK; error: D_MAGIC_CLEAR( surface ); for (i=0; i<MAX_SURFACE_BUFFERS; i++) { if (surface->buffers[i]) dfb_surface_buffer_destroy( surface->buffers[i] ); } fusion_skirmish_destroy( &surface->lock ); direct_serial_deinit( &surface->serial ); fusion_object_destroy( &surface->object ); return ret; }
static DFBResult system_initialize( CoreDFB *core, void **data ) { int i, n; CoreScreen *screen; D_ASSERT( dfb_x11 == NULL ); dfb_x11 = (DFBX11*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBX11) ); if (!dfb_x11) { D_ERROR( "DirectFB/X11: Couldn't allocate shared memory!\n" ); return D_OOSHM(); } dfb_x11_core = core; fusion_skirmish_init( &dfb_x11->lock, "X11 System", dfb_core_world(core) ); fusion_call_init( &dfb_x11->call, call_handler, NULL, dfb_core_world(core) ); dfb_surface_pool_initialize( core, &x11SurfacePoolFuncs, &dfb_x11->surface_pool ); screen = dfb_screens_register( NULL, NULL, &x11PrimaryScreenFuncs ); dfb_layers_register( screen, NULL, &x11PrimaryLayerFuncs ); fusion_arena_add_shared_field( dfb_core_arena( core ), "x11", dfb_x11 ); *data = dfb_x11; XInitThreads(); dfb_x11->data_shmpool = dfb_core_shmpool_data( core ); dfb_x11->display = XOpenDisplay(getenv("DISPLAY")); if (!dfb_x11->display) { D_ERROR("X11: Error in XOpenDisplay for '%s'\n", getenv("DISPLAY")); return DFB_INIT; } dfb_x11->screenptr = DefaultScreenOfDisplay(dfb_x11->display); dfb_x11->screennum = DefaultScreen(dfb_x11->display); for (i=0; i<dfb_x11->screenptr->ndepths; i++) { const Depth *depth = &dfb_x11->screenptr->depths[i]; for (n=0; n<depth->nvisuals; n++) { Visual *visual = &depth->visuals[n]; D_DEBUG( "X11/Visual: ID %02lu, depth %d, red 0x%06lx, green 0x%06lx, blue 0x%06lx, %d bits/rgb, %d entries\n", visual->visualid, depth->depth, visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->map_entries ); switch (depth->depth) { case 24: if (visual->red_mask == 0xff0000 && visual->green_mask == 0x00ff00 && visual->blue_mask == 0x0000ff) { dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = visual; dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = visual; } break; case 16: if (visual->red_mask == 0xf800 && visual->green_mask == 0x07e0 && visual->blue_mask == 0x001f) dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = visual; break; case 15: if (visual->red_mask == 0x7c00 && visual->green_mask == 0x03e0 && visual->blue_mask == 0x001f) dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB555)] = visual; break; } } } return DFB_OK; }
static DirectResult init_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared, const char *name, unsigned int max_size, bool debug ) { DirectResult ret; int size; long page_size; int pool_id; unsigned int pool_max_size; void *pool_addr_base = NULL; FusionWorld *world; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_ASSERT( name != NULL ); D_ASSERT( max_size > sizeof(shmalloc_heap) ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); D_ASSERT( pool != NULL ); D_ASSERT( shared != NULL ); page_size = direct_pagesize(); pool_id = ++world->shared->pool_ids; pool_max_size = max_size + BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); pool_addr_base = world->shared->pool_base; world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size; /* Exceeded limit? */ if (world->shared->pool_base > world->shared->pool_max) return DR_NOSHAREDMEMORY; /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( world ), pool_id ); /* Initialize the heap. */ ret = __shmalloc_init_heap( shm, buf, pool_addr_base, max_size, &size ); if (ret) return ret; /* initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = pool_id; pool->filename = D_STRDUP( buf ); /* Initialize shared data. */ shared->active = true; shared->debug = debug; shared->shm = shm->shared; shared->max_size = pool_max_size; shared->pool_id = pool_id; shared->addr_base = pool_addr_base; shared->heap = pool_addr_base; shared->heap->pool = shared; fusion_skirmish_init( &shared->lock, name, world ); D_MAGIC_SET( pool, FusionSHMPool ); D_MAGIC_SET( shared, FusionSHMPoolShared ); shared->name = SHSTRDUP( shared, name ); return DR_OK; }
static DFBResult system_initialize( CoreDFB *core, void **data ) { DFBResult ret; DFBX11 *x11; DFBX11Shared *shared; D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); x11 = D_CALLOC( 1, sizeof(DFBX11) ); if (!x11) return D_OOM(); shared = SHCALLOC( dfb_core_shmpool( core ), 1, sizeof(DFBX11Shared) ); if (!shared) { D_FREE( x11 ); return D_OOSHM(); } /* we need the error handler to signal the error to us, so use a global static */ shared_for_error_handler = shared; XSetErrorHandler( error_handler ); /* * Local init (master and slave) */ ret = InitLocal( x11, shared, core ); if (ret) { SHFREE( dfb_core_shmpool( core ), shared ); D_FREE( x11 ); return ret; } /* * Shared init (master only) */ shared->data_shmpool = dfb_core_shmpool_data( core ); shared->screen_size.w = x11->screenptr->width; shared->screen_size.h = x11->screenptr->height; fusion_skirmish_init( &shared->lock, "X11 System", dfb_core_world(core) ); fusion_call_init( &shared->call, call_handler, x11, dfb_core_world(core) ); /* * Must be set before initializing the pools! */ *data = x11; /* * Master init */ dfb_surface_pool_initialize( core, &x11SurfacePoolFuncs, &shared->x11image_pool ); #ifdef USE_GLX dfb_surface_pool_initialize( core, &glxSurfacePoolFuncs, &shared->glx_pool ); #endif if (dfb_config->video_length) { shared->vpsmem_length = dfb_config->video_length; dfb_surface_pool_initialize( core, &vpsmemSurfacePoolFuncs, &shared->vpsmem_pool ); } #ifdef USE_GLX dfb_surface_pool_bridge_initialize( core, &x11SurfacePoolBridgeFuncs, x11, &shared->x11_pool_bridge ); #endif fusion_arena_add_shared_field( dfb_core_arena( core ), "x11", shared ); return DFB_OK; }
int fusion_init( int world, int abi_version, int *world_ret ) { char buf[20]; FusionEnter enter; /* Check against multiple initialization. */ if (_fusion_id) { /* Increment local reference counter. */ fusion_refs++; return _fusion_id; } direct_initialize(); /* Open Fusion Kernel Device. */ if (world < 0) { for (world=0; world<256; world++) { snprintf( buf, sizeof(buf), "/dev/fusion/%d", world ); _fusion_fd = open (buf, O_RDWR | O_NONBLOCK | O_EXCL); if (_fusion_fd < 0) { if (errno == EBUSY) continue; D_PERROR( "Fusion/Init: opening '%s' failed!\n", buf ); direct_shutdown(); return -1; } else break; } } else { snprintf( buf, sizeof(buf), "/dev/fusion/%d", world ); _fusion_fd = open (buf, O_RDWR | O_NONBLOCK); if (_fusion_fd < 0) { D_PERROR( "Fusion/Init: opening '%s' failed!\n", buf ); direct_shutdown(); return -1; } } enter.api.major = FUSION_API_MAJOR; enter.api.minor = FUSION_API_MINOR; enter.fusion_id = 0; /* Get our Fusion ID. */ if (ioctl( _fusion_fd, FUSION_ENTER, &enter )) { D_PERROR( "Fusion/Init: FUSION_ENTER failed!\n" ); goto error; } if (!enter.fusion_id) { D_ERROR( "Fusion/Init: Got no ID from FUSION_ENTER! Kernel module might be too old.\n" ); goto error; } _fusion_id = enter.fusion_id; /* Initialize local reference counter. */ fusion_refs = 1; /* Initialize shmalloc part. */ if (!__shmalloc_init( world, _fusion_id == 1 )) { D_ERROR( "Fusion/Init: Shared memory initialization failed.\n" "\n" "Please make sure that a tmpfs mount point with at least 4MB of free space\n" "is available for read/write, see the DirectFB README for more instructions.\n" ); goto error; } if (_fusion_id == 1) { _fusion_shared = __shmalloc_allocate_root( sizeof(FusionShared) ); _fusion_shared->abi_version = abi_version; fusion_skirmish_init( &_fusion_shared->arenas_lock, "Fusion Arenas" ); fusion_skirmish_init( &_fusion_shared->reactor_globals, "Fusion Reactor Globals" ); _sheap->reactor = fusion_reactor_new( sizeof(long), "Shared Memory Heap" ); if (!_sheap->reactor) { __shmalloc_exit( true, true ); goto error_reactor; } gettimeofday( &_fusion_shared->start_time, NULL ); } else { _fusion_shared = __shmalloc_get_root(); if (_fusion_shared->abi_version != abi_version) { D_ERROR( "Fusion/Init: ABI version mismatch (my: %d, their: %d)\n", abi_version, _fusion_shared->abi_version ); __shmalloc_exit( false, false ); goto error; } } __shmalloc_attach(); direct_clock_set_start( &_fusion_shared->start_time ); direct_signal_handler_add( SIGSEGV, fusion_signal_handler, NULL, &signal_handler ); read_loop = direct_thread_create( DTT_MESSAGING, fusion_read_loop, NULL, "Fusion Dispatch" ); if (world_ret) *world_ret = world; return _fusion_id; error_reactor: fusion_skirmish_destroy( &_fusion_shared->arenas_lock ); fusion_skirmish_destroy( &_fusion_shared->reactor_globals ); error: _fusion_shared = NULL; _fusion_id = 0; close( _fusion_fd ); _fusion_fd = -1; direct_shutdown(); return -1; }