DirectResult voodoo_client_create( const char *host, int port, VoodooClient **ret_client ) { DirectResult ret; VoodooPlayInfo info; VoodooClient *client; VoodooPlayer *player; char buf[100] = { 0 }; const char *hostname = host; bool raw = true; D_ASSERT( ret_client != NULL ); if (!host) host = ""; if (!port) port = 2323; D_DEBUG_AT( Voodoo_Client, "%s( '%s', %d )\n", __FUNCTION__, host, port ); if (port != 2323) { D_DEBUG_AT( Voodoo_Client, " -> port != 2323, using PACKET mode right away\n" ); raw = false; } direct_list_foreach (client, m_clients) { if (!strcmp( client->host, host ) && client->port == port) { D_INFO( "Voodoo/Client: Reconnecting to '%s', increasing ref count of existing connection!\n", host ); client->refs++; *ret_client = client; return DR_OK; } } /* * Get the player singleton */ ret = voodoo_player_create( NULL, &player ); if (ret) { D_DERROR( ret, "Voodoo/Client: Could not create the player!\n" ); return ret; } /* * If we got a hostname or address try to lookup the player info */ // FIXME: resolve first, not late in voodoo_link_init_connect if (hostname && hostname[0]) { ret = voodoo_player_lookup_by_address( player, hostname, &info ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; } } else { /* * Start discovery and use first host visible */ ret = discover_host( player, NULL, &info, buf, sizeof(buf) ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; hostname = buf; } } if (!hostname || !hostname[0]) { D_ERROR( "Voodoo/Client: Did not find any other player!\n" ); return DR_ITEMNOTFOUND; } /* Allocate client structure. */ client = D_CALLOC( 1, sizeof(VoodooClient) ); if (!client) return D_OOM(); raw = !voodoo_config->link_packet && (voodoo_config->link_raw || raw); /* Create a link to the other player. */ ret = voodoo_link_init_connect( &client->vl, hostname, port, raw ); if (ret) { D_DERROR( ret, "Voodoo/Client: Failed to initialize Voodoo Link!\n" ); D_FREE( client ); return ret; } D_INFO( "Voodoo/Client: Fetching player information...\n" ); if (raw) { // FIXME: send_discover_and_receive_info() only does RAW, but we don't need it for packet connection, yet VoodooPlayVersion version; VoodooPlayInfo info; ret = send_discover_and_receive_info( &client->vl, &version, &info ); if (ret) { D_DEBUG_AT( Voodoo_Client, " -> Failed to receive player info via TCP!\n" ); D_INFO( "Voodoo/Client: No player information from '%s', trying to discover via UDP!\n", host ); /* * Fallback to UDP discovery */ ret = discover_host( player, hostname, &info, buf, sizeof(buf) ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; } } else { D_INFO( "Voodoo/Client: Connected to '%s' (%-15s) %s " "=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x= " "(vendor: %s, model: %s)\n", info.name, host, (info.flags & VPIF_LEVEL2) ? "*" : " ", info.uuid[0], info.uuid[1], info.uuid[2], info.uuid[3], info.uuid[4], info.uuid[5], info.uuid[6], info.uuid[7], info.uuid[8], info.uuid[9], info.uuid[10], info.uuid[11], info.uuid[12], info.uuid[13], info.uuid[14], info.uuid[15], info.vendor, info.model ); if (raw && !voodoo_config->link_raw) { /* * Switch to packet mode? */ if (info.flags & VPIF_PACKET) raw = false; } } /* * Switch to packet mode? */ if (!raw) { D_INFO( "Voodoo/Client: Switching to packet mode!\n" ); client->vl.Close( &client->vl ); /* Create another link to the other player. */ ret = voodoo_link_init_connect( &client->vl, hostname, port, false ); if (ret) { D_DERROR( ret, "Voodoo/Client: Failed to initialize second Voodoo Link!\n" ); D_FREE( client ); return ret; } } } /* Create the manager. */ ret = voodoo_manager_create( &client->vl, client, NULL, &client->manager ); if (ret) { client->vl.Close( &client->vl ); D_FREE( client ); return ret; } client->refs = 1; client->host = D_STRDUP( host ); client->port = port; direct_list_prepend( &m_clients, &client->link ); /* Return the new client. */ *ret_client = client; D_DEBUG_AT( Voodoo_Client, " => client %p\n", client ); return DR_OK; }
int main( int argc, char *argv[] ) { DirectResult ret; pid_t child_pid; TestMessage message = {0}; FusionReactor *reactor; Reaction reaction; FusionCall call; DirectFBInit( &argc, &argv ); ret = fusion_enter( -1, 0, FER_MASTER, &m_world ); if (ret) { D_DERROR( ret, "fusion_enter() failed" ); return ret; } MSG( "Entered world %d as master (FusionID %lu, pid %d)\n", fusion_world_index( m_world ), fusion_id( m_world ), getpid() ); reactor = fusion_reactor_new( sizeof(TestMessage), "Test", m_world ); if (!reactor) { D_ERROR( "fusion_reactor_new() failed\n" ); return -1; } MSG( "Attaching to reactor...\n" ); ret = fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction ); if (ret) { D_DERROR( ret, "fusion_reactor_attach() failed" ); return ret; } MSG( ".........FORKING NOW.........\n" ); fusion_world_set_fork_action( m_world, FFA_FORK ); child_pid = fork(); fusion_world_set_fork_action( m_world, FFA_CLOSE ); switch (child_pid) { case -1: D_PERROR( "fork() failed" ); break; case 0: setsid(); MSG( "...arrived after fork() in child (pid %d)..\n", getpid() ); MSG( "..child (FusionID %lu).\n", fusion_id( m_world ) ); usleep( 400000 ); break; default: usleep( 100000 ); MSG( "...returned from fork() in parent, child pid %d.\n", child_pid ); MSG( "Initializing dispatch callback...\n" ); ret = fusion_call_init( &call, dispatch_callback, NULL, m_world ); if (ret) { D_DERROR( ret, "fusion_call_init() failed" ); return ret; } MSG( "Setting dispatch callback...\n" ); ret = fusion_reactor_set_dispatch_callback( reactor, &call, NULL ); if (ret) { D_DERROR( ret, "fusion_reactor_set_dispatch_callback() failed" ); return ret; } MSG( "Sending message via reactor...\n" ); fusion_reactor_dispatch( reactor, &message, true, NULL ); usleep( 100000 ); MSG( "Destroying reactor...\n" ); fusion_reactor_destroy( reactor ); MSG( "...destroyed reactor!\n" ); usleep( 400000 ); MSG( "Freeing reactor...\n" ); fusion_reactor_free( reactor ); MSG( "...freed reactor!\n" ); break; } MSG( "Exiting from world %d (FusionID %lu, pid %d)...\n", fusion_world_index( m_world ), fusion_id( m_world ), getpid() ); fusion_exit( m_world, false ); return 0; }
Bool dfb_x11_open_window( DFBX11 *x11, XWindow** ppXW, int iXPos, int iYPos, int iWidth, int iHeight, DFBSurfacePixelFormat format ) { XWindow *xw; XSetWindowAttributes attr = { .background_pixmap = 0 }; void *old_error_handler = 0; unsigned int cw_mask = CWEventMask; D_DEBUG_AT( X11_Window, "Creating %4dx%4d %s window...\n", iWidth, iHeight, dfb_pixelformat_name(format) ); xw = D_CALLOC( 1, sizeof(XWindow) ); if (!xw) return D_OOM(); /* We set the structure as needed for our window */ xw->width = iWidth; xw->height = iHeight; xw->display = x11->display; xw->screenptr = DefaultScreenOfDisplay(xw->display); xw->screennum = DefaultScreen(xw->display); xw->depth = DefaultDepthOfScreen(xw->screenptr); xw->visual = DefaultVisualOfScreen(xw->screenptr); attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask; if (dfb_config->x11_borderless) { attr.override_redirect = True; cw_mask |= CWOverrideRedirect; } XLockDisplay( x11->display ); old_error_handler = XSetErrorHandler( error_handler ); error_code = 0; xw->window = XCreateWindow( xw->display, RootWindowOfScreen(xw->screenptr), iXPos, iYPos, iWidth, iHeight, 0, xw->depth, InputOutput, xw->visual, cw_mask, &attr ); XSync( xw->display, False ); if (!xw->window || error_code) { D_FREE( xw ); XUnlockDisplay( x11->display ); return False; } XSizeHints Hints; /* * Here we inform the function of what we are going to change for the * window (there's also PPosition but it's obsolete) */ Hints.flags = PSize | PMinSize | PMaxSize; /* * Now we set the structure to the values we need for width & height. * For esthetic reasons we set Width=MinWidth=MaxWidth. * The same goes for Height. You can try whith differents values, or * let's use Hints.flags=Psize; and resize your window.. */ Hints.min_width = Hints.max_width = Hints.base_width = xw->width; Hints.min_height = Hints.max_height = Hints.base_height = xw->height; /* Now we can set the size hints for the specified window */ XSetWMNormalHints(xw->display,xw->window,&Hints); /* We change the title of the window (default:Untitled) */ XStoreName(xw->display,xw->window,"DFB X11 system window"); xw->gc = XCreateGC(xw->display, xw->window, 0, NULL); #if 0 // Create a null cursor Pixmap pixmp1; Pixmap pixmp2; XColor fore; XColor back; char zero = 0; pixmp1 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); pixmp2 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); xw->NullCursor = XCreatePixmapCursor( xw->display, pixmp1, pixmp2, &fore, &back, 0, 0 ); XFreePixmap ( xw->display, pixmp1 ); XFreePixmap ( xw->display, pixmp2 ); XDefineCursor( xw->display, xw->window, xw->NullCursor ); #endif /* maps the window and raises it to the top of the stack */ XMapRaised( xw->display, xw->window ); if (x11->use_shm) { // Shared memory xw->shmseginfo=(XShmSegmentInfo *)D_CALLOC(1, sizeof(XShmSegmentInfo)); if (!xw->shmseginfo) { x11->use_shm = false; goto no_shm; } xw->ximage=XShmCreateImage(xw->display, xw->visual, xw->depth, ZPixmap, NULL,xw->shmseginfo, xw->width, xw->height * 2); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR("X11: Error creating shared image (XShmCreateImage) \n"); x11->use_shm = false; D_FREE(xw->shmseginfo); error_code = 0; goto no_shm; } xw->bpp = (xw->ximage->bits_per_pixel + 7) / 8; /* we firstly create our shared memory segment with the size we need, and correct permissions for the owner, the group and the world --> 0777 */ xw->shmseginfo->shmid=shmget(IPC_PRIVATE, xw->ximage->bytes_per_line * xw->ximage->height * 2, IPC_CREAT|0777); if (xw->shmseginfo->shmid<0) { x11->use_shm = false; XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* Then, we have to attach the segment to our process, and we let the function search the correct memory place --> NULL. It's safest ! */ xw->shmseginfo->shmaddr = shmat( xw->shmseginfo->shmid, NULL, 0 ); if (!xw->shmseginfo->shmaddr) { x11->use_shm = false; shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* We set the buffer in Read and Write mode */ xw->shmseginfo->readOnly=False; xw->virtualscreen= xw->ximage->data = xw->shmseginfo->shmaddr; XSetErrorHandler( error_handler_shm ); XShmAttach(x11->display,xw->shmseginfo); XShmPutImage(x11->display, xw->window, xw->gc, xw->ximage, 0, 0, 0, 0, 1, 1, False); XSync(x11->display, False); XSetErrorHandler( error_handler ); if (!x11->use_shm) { shmdt(xw->shmseginfo->shmaddr); shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); } } no_shm: if (!x11->use_shm) { int pitch; xw->bpp = (xw->depth > 16) ? 4 : (xw->depth > 8) ? 2 : 1; pitch = (xw->bpp * xw->width + 3) & ~3; /* Use malloc(), not D_MALLOC() here, because XCreateImage() * will call free() on this data. */ xw->virtualscreen = malloc ( 2 * xw->height * pitch ); xw->ximage = XCreateImage( xw->display, xw->visual, xw->depth, ZPixmap, 0, xw->virtualscreen, xw->width, xw->height * 2, 32, pitch ); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR( "X11/Window: XCreateImage( Visual %02lu, depth %d, size %dx%d, buffer %p [%d] ) failed!\n", xw->visual->visualid, xw->depth, xw->width, xw->height * 2, xw->virtualscreen, pitch ); XFreeGC(xw->display,xw->gc); XDestroyWindow(xw->display,xw->window); XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_FREE( xw ); return False; } } XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_INFO( "X11/Display: %ssing XShm.\n", x11->use_shm ? "U" : "Not u" ); (*ppXW) = xw; return True; } void dfb_x11_close_window( DFBX11 *x11, XWindow* xw ) { if (x11->use_shm) { XShmDetach( xw->display, xw->shmseginfo ); shmdt( xw->shmseginfo->shmaddr ); shmctl( xw->shmseginfo->shmid, IPC_RMID, NULL ); D_FREE( xw->shmseginfo ); } XDestroyImage( xw->ximage ); XFreeGC( xw->display, xw->gc ); XDestroyWindow( xw->display, xw->window ); #if 0 XFreeCursor( xw->display, xw->NullCursor ); #endif D_FREE( xw ); }
DFBResult IDirectFBFont_CreateFromBuffer( IDirectFBDataBuffer *buffer, CoreDFB *core, const DFBFontDescription *desc, IDirectFBFont **interface ) { DFBResult ret; DirectInterfaceFuncs *funcs = NULL; IDirectFBDataBuffer_data *buffer_data; IDirectFBFont *ifont; IDirectFBFont_ProbeContext ctx = {0}; /* Get the private information of the data buffer. */ buffer_data = (IDirectFBDataBuffer_data*) buffer->priv; if (!buffer_data) return DFB_DEAD; /* Provide a fallback for image providers without data buffer support. */ ctx.filename = buffer_data->filename; /* try to map the "file" content first */ if (try_map_file( buffer_data, &ctx ) != DFB_OK) { /* try to load the "file" content from the buffer */ /* we need to be able to seek (this implies non-streamed, so we also know the size) so we can reuse the buffer */ if (buffer->SeekTo( buffer, 0 ) == DFB_OK) { unsigned int size, got; /* get the "file" length */ buffer->GetLength( buffer, &size ); ctx.content = D_MALLOC( size ); if (!ctx.content) return DR_NOLOCALMEMORY; ctx.content_size = 0; while (ctx.content_size < size) { unsigned int get = size - ctx.content_size; if (get > 8192) get = 8192; ret = buffer->WaitForData( buffer, get ); if (ret) { D_DERROR( ret, "%s: WaitForData failed!\n", __FUNCTION__ ); break; } ret = buffer->GetData( buffer, get, ctx.content + ctx.content_size, &got ); if (ret) { D_DERROR( ret, "%s: GetData failed!\n", __FUNCTION__ ); break; } if (!got) break; ctx.content_size += got; } if (ctx.content_size != size) { D_ERROR( "%s: Got size %u differs from supposed %u!\n", __FUNCTION__, ctx.content_size, size ); D_FREE( ctx.content ); return DFB_FAILURE; } } } /* Find a suitable implementation. */ ret = DirectGetInterface( &funcs, "IDirectFBFont", NULL, DirectProbeInterface, &ctx ); if (ret) { unmap_or_free( &ctx ); return ret; } DIRECT_ALLOCATE_INTERFACE( ifont, IDirectFBFont ); /* Construct the interface. */ ret = funcs->Construct( ifont, core, &ctx, desc ); if (ret) { unmap_or_free( &ctx ); return ret; } /* store pointer for deletion at destroy */ { IDirectFBFont_data *data = (IDirectFBFont_data*)(ifont->priv); data->content = ctx.content; data->content_size = ctx.content_size; data->content_mapped = ctx.content_mapped; } *interface = ifont; return DFB_OK; }
DirectResult voodoo_link_init_connect( VoodooLink *link, const char *hostname, int port, bool raw ) { DirectResult ret; int err; struct addrinfo hints; struct addrinfo *addr; char portstr[10]; Link *l; memset( &hints, 0, sizeof(hints) ); hints.ai_flags = AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; hints.ai_family = PF_UNSPEC; D_INFO( "Voodoo/Link: Looking up host '%s'...\n", hostname ); snprintf( portstr, sizeof(portstr), "%d", port ); err = getaddrinfo( hostname, portstr, &hints, &addr ); if (err) { switch (err) { case EAI_FAMILY: D_ERROR( "Direct/Log: Unsupported address family!\n" ); return DR_UNSUPPORTED; case EAI_SOCKTYPE: D_ERROR( "Direct/Log: Unsupported socket type!\n" ); return DR_UNSUPPORTED; case EAI_NONAME: D_ERROR( "Direct/Log: Host not found!\n" ); return DR_FAILURE; case EAI_SERVICE: D_ERROR( "Direct/Log: Service is unreachable!\n" ); return DR_FAILURE; #ifdef EAI_ADDRFAMILY case EAI_ADDRFAMILY: #endif case EAI_NODATA: D_ERROR( "Direct/Log: Host found, but has no address!\n" ); return DR_FAILURE; case EAI_MEMORY: return D_OOM(); case EAI_FAIL: D_ERROR( "Direct/Log: A non-recoverable name server error occurred!\n" ); return DR_FAILURE; case EAI_AGAIN: D_ERROR( "Direct/Log: Temporary error, try again!\n" ); return DR_TEMPUNAVAIL; default: D_ERROR( "Direct/Log: Unknown error occured!?\n" ); return DR_FAILURE; } } l = D_CALLOC( 1, sizeof(Link) ); if (!l) return D_OOM(); /* Create the client socket. */ l->fd[0] = socket( addr->ai_family, SOCK_STREAM, 0 ); if (l->fd[0] < 0) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket creation failed!\n" ); freeaddrinfo( addr ); D_FREE( l ); return ret; } l->fd[1] = l->fd[0]; #if !VOODOO_BUILD_NO_SETSOCKOPT if (setsockopt( l->fd[0], SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0) D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" ); if (setsockopt( l->fd[0], SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0) D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" ); #endif D_INFO( "Voodoo/Link: Connecting to '%s:%d'...\n", addr->ai_canonname, port ); /* Connect to the server. */ err = connect( l->fd[0], addr->ai_addr, addr->ai_addrlen ); freeaddrinfo( addr ); if (err) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket connect failed!\n" ); close( l->fd[0] ); D_FREE( l ); return ret; } D_INFO( "Voodoo/Link: Connected.\n" ); DUMP_SOCKET_OPTION( l->fd[0], SO_SNDLOWAT ); DUMP_SOCKET_OPTION( l->fd[0], SO_RCVLOWAT ); DUMP_SOCKET_OPTION( l->fd[0], SO_SNDBUF ); DUMP_SOCKET_OPTION( l->fd[0], SO_RCVBUF ); if (!raw) { link->code = 0x80008676; if (write( l->fd[1], &link->code, sizeof(link->code) ) != 4) { D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" ); close( l->fd[0] ); D_FREE( l ); return DR_IO; } } D_INFO( "Voodoo/Link: Sent link code (%s).\n", raw ? "raw" : "packet" ); if (pipe( l->wakeup_fds )) return errno2result( errno ); link->priv = l; link->Close = Close; link->Read = Read; link->Write = Write; link->SendReceive = SendReceive; link->WakeUp = WakeUp; link->WaitForData = WaitForData; return DR_OK; }
int smd_nvme_list_streams(uint32_t *nr, struct smd_nvme_stream_bond *streams, daos_anchor_t *anchor) { struct smd_store *store = get_smd_store(); daos_anchor_t *probe_hash = NULL; dbtree_probe_opc_t opc; daos_handle_t sti_hdl; int i = 0; int rc = 0; D_DEBUG(DB_TRACE, "listing the stream table\n"); if (streams == NULL || nr == NULL) { D_ERROR("Streams array or NR cannot be NULL\n"); return -DER_INVAL; } smd_lock(SMD_STAB_LOCK); rc = dbtree_iter_prepare(store->sms_stream_tab, 0, &sti_hdl); if (rc) D_GOTO(out, rc); if (anchor != NULL && !daos_anchor_is_zero(anchor)) probe_hash = anchor; opc = probe_hash == NULL ? BTR_PROBE_FIRST : BTR_PROBE_GT; rc = dbtree_iter_probe(sti_hdl, opc, DAOS_INTENT_DEFAULT, NULL, anchor); if (rc != 0) D_GOTO(out_eof, rc); i = 0; while (i < *nr) { daos_iov_t key, value; int stream_id; daos_iov_set(&key, &stream_id, sizeof(stream_id)); daos_iov_set(&value, &streams[i], sizeof(struct smd_nvme_stream_bond)); rc = dbtree_iter_fetch(sti_hdl, &key, &value, anchor); if (rc != 0) { D_ERROR("Error while fetching stream info: %d\n", rc); break; } i++; rc = dbtree_iter_next(sti_hdl); if (rc) { if (rc != -DER_NONEXIST) D_ERROR("Failed to iterate next: %d\n", rc); break; } } out_eof: *nr = i; if (rc == -DER_NONEXIST) { anchor ? daos_anchor_set_eof(anchor) : NULL; rc = 0; } dbtree_iter_finish(sti_hdl); out: smd_unlock(SMD_STAB_LOCK); return rc; }
DirectResult fusion_shm_pool_create( FusionWorld *world, const char *name, unsigned int max_size, bool debug, FusionSHMPoolShared **ret_pool ) { int i; DirectResult ret; FusionSHM *shm; FusionSHMShared *shared; D_MAGIC_ASSERT( world, FusionWorld ); D_MAGIC_ASSERT( world->shared, FusionWorldShared ); D_ASSERT( name != NULL ); D_ASSERT( max_size > 0 ); D_ASSERT( ret_pool != NULL ); D_DEBUG_AT( Fusion_SHMPool, "%s( %p [%d], '%s', %d, %p, %sdebug )\n", __FUNCTION__, world, world->shared->world_index, name, max_size, ret_pool, debug ? "" : "non-" ); #if !DIRECT_BUILD_DEBUGS debug = false; #endif shm = &world->shm; D_MAGIC_ASSERT( shm, FusionSHM ); shared = shm->shared; D_MAGIC_ASSERT( shared, FusionSHMShared ); if (max_size < 8192) { D_ERROR( "Fusion/SHMPool: Maximum size (%d) should be 8192 at least!\n", max_size ); return DR_INVARG; } ret = fusion_skirmish_prevail( &shared->lock ); if (ret) goto error; if (shared->num_pools == FUSION_SHM_MAX_POOLS) { D_ERROR( "Fusion/SHMPool: Maximum number of pools (%d) already reached!\n", FUSION_SHM_MAX_POOLS ); ret = DR_LIMITEXCEEDED; goto error; } for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { if (!shared->pools[i].active) break; D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); D_MAGIC_ASSUME( &shm->pools[i], FusionSHMPool ); } D_ASSERT( i < FUSION_SHM_MAX_POOLS ); D_DEBUG_AT( Fusion_SHMPool, " -> index %d\n", i ); memset( &shm->pools[i], 0, sizeof(FusionSHMPool) ); memset( &shared->pools[i], 0, sizeof(FusionSHMPoolShared) ); shared->pools[i].index = i; ret = init_pool( shm, &shm->pools[i], &shared->pools[i], name, max_size, debug ); if (ret) goto error; shared->num_pools++; fusion_skirmish_dismiss( &shared->lock ); *ret_pool = &shared->pools[i]; D_DEBUG_AT( Fusion_SHMPool, " -> %p\n", *ret_pool ); return DR_OK; error: fusion_skirmish_dismiss( &shared->lock ); return ret; }
static int parse_cmdline( int argc, char *argv[] ) { int i; char *end; for (i=1; i<argc; i++) { if (!strcmp( argv[i], "-s" )) { if (++i < argc) { block_size = strtoul( argv[i], &end, 10 ); if (end && *end) { D_ERROR( "Parse error in number '%s'!\n", argv[i] ); return -1; } if (block_size < 1) return show_usage(); } else return show_usage(); } else if (!strcmp( argv[i], "-b" )) { if (++i < argc) { bit_rate = strtoul( argv[i], &end, 10 ); if (end && *end) { D_ERROR( "Parse error in number '%s'!\n", argv[i] ); return -1; } } else return show_usage(); } else if (!strcmp( argv[i], "-B" )) { if (++i < argc) { bit_rate = strtoul( argv[i], &end, 10 ) * 1024; if (end && *end) { D_ERROR( "Parse error in number '%s'!\n", argv[i] ); return -1; } } else return show_usage(); } else if (!strcmp( argv[i], "-c" )) { run_busy = 1; } else if (!strcmp( argv[i], "-f" )) { do_fork = 1; } else if (!strcmp( argv[i], "-t" )) { do_thread = 1; } else return show_usage(); } return 0; }
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 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; }
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; }
int main(int argc, char **argv) { int width = 640; int height = 480; int fd = open("/dev/video0", O_RDWR | O_NONBLOCK); int stat = 0; if (fd < 0) { D_ERROR("can not open device."); return -1; } struct v4l2_capability cap = {0}; stat = ioctl(fd, VIDIOC_QUERYCAP, &cap); if (stat == -1) { D_ERROR("can not get device capability."); return -1; } print_cap(&cap); int input_index = 0; stat = ioctl(fd, VIDIOC_G_INPUT, &input_index); if (stat == -1) { D_ERROR("can not get current input"); return -1; } D_PVAR_INT(input_index); struct v4l2_input input; memset(&input, 0, sizeof(input)); input.index = 0; D_PRINT("enum input"); do { stat = ioctl(fd, VIDIOC_ENUMINPUT, &input); if (stat == -1) { break; } D_PVAR_INT(input.index); D_PVAR_STR(input.name); input.index++; } while (1); D_PRINT("enum input end"); v4l2_std_id std; do { stat = ioctl(fd, VIDIOC_QUERYSTD, &std); } while (stat == -1 && errno == EAGAIN); if (stat == -1) { D_ERROR("can not get current video standard."); //return -1; } struct v4l2_standard standard; memset(&standard, 0, sizeof(standard)); D_PRINT("enum video standard."); while (1) { stat = ioctl(fd, VIDIOC_ENUMSTD, &standard); if (stat == -1) { break; } D_PVAR_INT(standard.index); D_PVAR_STR(standard.name); if (std == standard.id) { D_PRINT("above is current video standard."); } standard.index++; } D_PRINT("enum video standard end."); struct v4l2_fmtdesc fmtdesc; memset(&fmtdesc, 0, sizeof(fmtdesc)); fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; D_PRINT("enum image format."); while (1) { stat = ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc); if (stat == -1) { break; } D_PVAR_INT(fmtdesc.index); D_PVAR_STR(fmtdesc.description); fmtdesc.index++; } D_PRINT("enum image format end."); struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; D_PRINT("set format"); stat = ioctl(fd, VIDIOC_S_FMT, &fmt); if (stat == -1) { D_ERROR("can not set video format"); return -1; } if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { D_ERROR("can not set specific format"); struct v4l2_fmtdesc fmtqury; memset(&fmtqury, 0, sizeof(fmtqury)); fmtqury.pixelformat == fmt.fmt.pix.pixelformat; stat = ioctl(fd, VIDIOC_ENUM_FMT, &fmtqury); if (stat == -1) { printf("real format: %s\n", fmtqury.description); } printf("format = %d\n", fmt.fmt.pix.pixelformat); return -1; } struct v4l2_requestbuffers req; memset(&req, 0, sizeof(struct v4l2_requestbuffers)); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; stat = ioctl(fd, VIDIOC_REQBUFS, &req); if (stat == -1) { D_ERROR("can not require buffers"); return -1; } buffers = (struct buffer *)malloc(sizeof(struct buffer) * req.count); int i = 0; for (i = 0; i < req.count; i++) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; stat = ioctl(fd, VIDIOC_QUERYBUF, &buf); if (stat == -1) { D_ERROR("can not query buffer"); return -1; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (MAP_FAILED == buffers[i].start) { D_ERROR("mmap error"); return -1; } stat = ioctl(fd, VIDIOC_QBUF, &buf); if (stat == -1) { D_ERROR("can not put buf in queue"); return -1; } } enum v4l2_buf_type stream_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; D_PRINT("stream on."); stat = ioctl(fd, VIDIOC_STREAMON, &stream_type); if (stat == -1) { D_ERROR("can not turn stream on"); return -1; } i = 0; char filename[4096] = {0}; D_PRINT("start loop"); while (1) { fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); int ret = 0; ret = select(fd + 1, &fds, NULL, NULL, NULL); if (ret == -1) { if (EINTR == errno) { continue; } D_ERROR("select error."); return -1; } struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; stat = ioctl(fd, VIDIOC_DQBUF, &buf); if (stat == -1) { D_ERROR("can not out queue"); return -1; } sprintf(filename, "out/frame%d.jpg", i); printf("index: %d, out: %s\n", buf.index, filename); FILE *out = fopen(filename, "wb"); //fprintf(out, "P6\n%d %d\n255\n",640, 480); fwrite(buffers[buf.index].start, 1, buf.length, out); fclose(out); ioctl(fd, VIDIOC_QBUF, &buf); i++; } stat = ioctl(fd, VIDIOC_STREAMOFF, &stream_type); if (stat == -1) { D_ERROR("can not turn stream off"); return -1; } close(fd); return 0; }
static DFBResult sdlAllocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { DFBResult ret; CoreSurface *surface; SDLAllocationData *alloc = alloc_data; D_DEBUG_AT( SDL_Pool, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); surface = buffer->surface; D_MAGIC_ASSERT( surface, CoreSurface ); if (surface->type & CSTF_LAYER) { dfb_sdl->screen = NULL; /* clear? */ ret = dfb_sdl_set_video_mode( dfb_sdl_core, &surface->config ); if (ret) { D_DERROR( ret, "SDL/Surface: dfb_sdl_set_video_mode() failed!\n" ); return ret; } D_ASSERT( dfb_sdl->screen != NULL ); if (!dfb_sdl->screen) { D_ERROR( "SDL/Surface: No screen surface!?\n" ); return DFB_BUG; } alloc->sdl_surf = dfb_sdl->screen; D_DEBUG_AT( SDL_Pool, " -> screen surface %dx%d, %d, 0x%08x, pitch %d\n", dfb_sdl->screen->w, dfb_sdl->screen->h, dfb_sdl->screen->format->BitsPerPixel, dfb_sdl->screen->flags, dfb_sdl->screen->pitch ); allocation->flags |= CSALF_ONEFORALL; } else { DFBSurfacePixelFormat format = surface->config.format; Uint32 flags = SDL_HWSURFACE;// | SDL_ASYNCBLIT | SDL_FULLSCREEN; Uint32 rmask; Uint32 gmask; Uint32 bmask; Uint32 amask; if (surface->config.caps & DSCAPS_FLIPPING) flags |= SDL_DOUBLEBUF; switch (format) { case DSPF_A8: rmask = 0x00; gmask = 0x00; bmask = 0x00; amask = 0xff; break; case DSPF_RGB16: rmask = 0xf800; gmask = 0x07e0; bmask = 0x001f; amask = 0x0000; break; case DSPF_RGB32: rmask = 0x00ff0000; gmask = 0x0000ff00; bmask = 0x000000ff; amask = 0x00000000; break; case DSPF_ARGB: rmask = 0x00ff0000; gmask = 0x0000ff00; bmask = 0x000000ff; amask = 0xff000000; break; default: D_ERROR( "SDL/Surface: %s() has no support for %s!\n", __FUNCTION__, dfb_pixelformat_name(format) ); return DFB_UNSUPPORTED; } D_DEBUG_AT( SDL_Pool, " -> SDL_CreateRGBSurface( 0x%08x, " "%dx%d, %d, 0x%08x, 0x%08x, 0x%08x, 0x%08x )\n", flags, surface->config.size.w, surface->config.size.h, DFB_BITS_PER_PIXEL(format), rmask, gmask, bmask, amask ); alloc->sdl_surf = SDL_CreateRGBSurface( flags, surface->config.size.w, surface->config.size.h, DFB_BITS_PER_PIXEL(format), rmask, gmask, bmask, amask ); if (!alloc->sdl_surf) { D_ERROR( "SDL/Surface: SDL_CreateRGBSurface( 0x%08x, " "%dx%d, %d, 0x%08x, 0x%08x, 0x%08x, 0x%08x ) failed!\n", flags, surface->config.size.w, surface->config.size.h, DFB_BITS_PER_PIXEL(format), rmask, gmask, bmask, amask ); return DFB_FAILURE; } } D_MAGIC_SET( alloc, SDLAllocationData ); return DFB_OK; }
static DirectResult send_discover_and_receive_info( VoodooLink *link, VoodooPlayVersion *ret_version, VoodooPlayInfo *ret_info ) { struct { VoodooMessageHeader header; VoodooPlayVersion version; VoodooPlayInfo info; } msg; int ret; VoodooMessageHeader header; size_t got; D_INFO( "Voodoo/Player: Sending VMSG_DISCOVER message via Voodoo TCP port...\n" ); header.size = sizeof(VoodooMessageHeader); header.serial = 0; header.type = VMSG_DISCOVER; ret = link->Write( link, &header, sizeof(header) ); if (ret < 0) { ret = errno2result( errno ); D_PERROR( "Voodoo/Player: Failed to send VMSG_DISCOVER message via Voodoo TCP port!\n" ); return ret; } // wait for up to one second (old server will not reply anything, so we have to timeout) ret = link->WaitForData( link, 1000 ); if (ret) { D_DERROR( ret, "Voodoo/Player: Failed to wait for reply after sending VMSG_DISCOVER message via Voodoo TCP port!\n" ); return ret; } D_INFO( "Voodoo/Player: New Voodoo Server with VMSG_DISCOVER support, reading version/info (SENDINFO) reply...\n" ); got = 0; while (got < sizeof(msg)) { ret = link->Read( link, (u8*) &msg + got, sizeof(msg) - got ); if (ret < 0) { ret = errno2result( errno ); D_PERROR( "Voodoo/Player: Failed to read after sending VMSG_DISCOVER message via Voodoo TCP port!\n" ); return ret; } got += ret; } if (msg.header.type != VMSG_SENDINFO) { D_ERROR( "Voodoo/Player: Received message after sending VMSG_DISCOVER message via Voodoo TCP port is no VMSG_SENDINFO!\n"); return DR_INVARG; } *ret_version = msg.version; *ret_info = msg.info; D_INFO( "Voodoo/Player: Voodoo Server sent name '%s', version %d.%d.%d\n", msg.info.name, msg.version.v[1], msg.version.v[2], msg.version.v[3] ); return DR_OK; }
static int ik_btr_kv_operate(enum ik_btr_opc opc, char *str, bool verbose) { int count = 0; umem_id_t rec_mmid; int rc; if (daos_handle_is_inval(ik_toh)) { D_ERROR("Can't find opened tree\n"); return -1; } while (str != NULL && !isspace(*str) && *str != '\0') { char *val = NULL; daos_iov_t key_iov; daos_iov_t val_iov; uint64_t key; key = strtoul(str, NULL, 0); if (opc == BTR_OPC_UPDATE) { val = strchr(str, IK_SEP_VAL); if (val == NULL) { D_ERROR("Invalid parameters %s(errno %d)\n", str, errno); return -1; } str = ++val; } str = strchr(str, IK_SEP); if (str != NULL) { *str = '\0'; str++; } daos_iov_set(&key_iov, &key, sizeof(key)); switch (opc) { default: return -1; case BTR_OPC_UPDATE: daos_iov_set(&val_iov, val, strlen(val) + 1); rc = dbtree_update(ik_toh, &key_iov, &val_iov); if (rc != 0) { D_ERROR("Failed to update "DF_U64":%s\n", key, val); return -1; } break; case BTR_OPC_DELETE: rc = dbtree_delete(ik_toh, &key_iov, NULL); if (rc != 0) { D_ERROR("Failed to delete "DF_U64"\n", key); return -1; } if (verbose) D_PRINT("Deleted key "DF_U64"\n", key); if (dbtree_is_empty(ik_toh) && verbose) D_PRINT("Tree is empty now\n"); break; case BTR_OPC_DELETE_RETAIN: rc = dbtree_delete(ik_toh, &key_iov, &rec_mmid); if (rc != 0) { D_ERROR("Failed to delete "DF_U64"\n", key); return -1; } /** Verify and delete rec_mmid here */ rc = btr_rec_verify_delete(&rec_mmid, &key_iov); if (rc != 0) { D_ERROR("Failed to verify and delete rec\n"); return -1; } if (verbose) D_PRINT("Deleted key "DF_U64"\n", key); if (dbtree_is_empty(ik_toh) && verbose) D_PRINT("Tree is empty now\n"); break; case BTR_OPC_LOOKUP: D_DEBUG(DB_TEST, "Looking for "DF_U64"\n", key); daos_iov_set(&val_iov, NULL, 0); /* get address */ rc = dbtree_lookup(ik_toh, &key_iov, &val_iov); if (rc != 0) { D_ERROR("Failed to lookup "DF_U64"\n", key); return -1; } if (verbose) { D_PRINT("Found key "DF_U64", value %s\n", key, (char *)val_iov.iov_buf); } break; } count++; } if (verbose) D_PRINT("%s %d record(s)\n", btr_opc2str(opc), count); return 0; }
static int crt_proc_daos_iod_t(crt_proc_t proc, daos_iod_t *dvi) { crt_proc_op_t proc_op; int rc; int i; uint32_t existing_flags = 0; if (proc == NULL || dvi == NULL) { D_ERROR("Invalid parameter, proc: %p, data: %p.\n", proc, dvi); return -DER_INVAL; } rc = crt_proc_d_iov_t(proc, &dvi->iod_name); if (rc != 0) return rc; rc = crt_proc_daos_csum_buf_t(proc, &dvi->iod_kcsum); if (rc != 0) return rc; rc = crt_proc_memcpy(proc, &dvi->iod_type, sizeof(dvi->iod_type)); if (rc != 0) return -DER_HG; rc = crt_proc_uint64_t(proc, &dvi->iod_size); if (rc != 0) return -DER_HG; rc = crt_proc_uint32_t(proc, &dvi->iod_nr); if (rc != 0) return -DER_HG; if (dvi->iod_nr == 0 && dvi->iod_type != DAOS_IOD_ARRAY) { D_ERROR("invalid I/O descriptor, iod_nr = 0\n"); return -DER_HG; } rc = crt_proc_get_op(proc, &proc_op); if (rc != 0) return -DER_HG; if (proc_op == CRT_PROC_ENCODE) { if (dvi->iod_type == DAOS_IOD_ARRAY && dvi->iod_recxs != NULL) existing_flags |= IOD_REC_EXIST; if (dvi->iod_csums != NULL) existing_flags |= IOD_CSUM_EXIST; if (dvi->iod_eprs != NULL) existing_flags |= IOD_EPRS_EXIST; } rc = crt_proc_uint32_t(proc, &existing_flags); if (rc != 0) return -DER_HG; if (proc_op == CRT_PROC_DECODE) { if (existing_flags & IOD_REC_EXIST) { D_ALLOC_ARRAY(dvi->iod_recxs, dvi->iod_nr); if (dvi->iod_recxs == NULL) D_GOTO(free, rc = -DER_NOMEM); } if (existing_flags & IOD_CSUM_EXIST) { D_ALLOC_ARRAY(dvi->iod_csums, dvi->iod_nr); if (dvi->iod_csums == NULL) D_GOTO(free, rc = -DER_NOMEM); } if (existing_flags & IOD_EPRS_EXIST) { D_ALLOC_ARRAY(dvi->iod_eprs, dvi->iod_nr); if (dvi->iod_eprs == NULL) D_GOTO(free, rc = -DER_NOMEM); } } if (existing_flags & IOD_REC_EXIST) { for (i = 0; i < dvi->iod_nr; i++) { rc = crt_proc_daos_recx_t(proc, &dvi->iod_recxs[i]); if (rc != 0) { if (proc_op == CRT_PROC_DECODE) D_GOTO(free, rc); return rc; } } } if (existing_flags & IOD_CSUM_EXIST) { for (i = 0; i < dvi->iod_nr; i++) { rc = crt_proc_daos_csum_buf_t(proc, &dvi->iod_csums[i]); if (rc != 0) { if (proc_op == CRT_PROC_DECODE) D_GOTO(free, rc); return rc; } } } if (existing_flags & IOD_EPRS_EXIST) { for (i = 0; i < dvi->iod_nr; i++) { rc = crt_proc_daos_epoch_range_t(proc, &dvi->iod_eprs[i]); if (rc != 0) { if (proc_op == CRT_PROC_DECODE) D_GOTO(free, rc); return rc; } } } if (proc_op == CRT_PROC_FREE) { free: if (dvi->iod_recxs != NULL) D_FREE(dvi->iod_recxs); if (dvi->iod_csums != NULL) D_FREE(dvi->iod_csums); if (dvi->iod_eprs != NULL) D_FREE(dvi->iod_eprs); } return rc; }
static int ik_btr_iterate(char *args) { daos_handle_t ih; int i; int d; int del; int rc; int opc; char *err; if (daos_handle_is_inval(ik_toh)) { D_ERROR("Can't find opened tree\n"); return -1; } rc = dbtree_iter_prepare(ik_toh, BTR_ITER_EMBEDDED, &ih); if (rc != 0) { err = "initialize"; goto failed; } if (args[0] == 'b') opc = BTR_PROBE_LAST; else opc = BTR_PROBE_FIRST; if (strlen(args) >= 3 && args[1] == ':') del = atoi(&args[2]); else del = 0; for (i = d = 0;; i++) { daos_iov_t key_iov; daos_iov_t val_iov; uint64_t key; if (i == 0 || (del != 0 && d <= del)) { rc = dbtree_iter_probe(ih, opc, DAOS_INTENT_DEFAULT, NULL, NULL); if (rc == -DER_NONEXIST) break; if (rc != 0) { err = "probe"; goto failed; } if (del != 0) { if (d == del) del = d = 0; /* done */ else d++; } } daos_iov_set(&key_iov, NULL, 0); daos_iov_set(&val_iov, NULL, 0); rc = dbtree_iter_fetch(ih, &key_iov, &val_iov, NULL); if (rc != 0) { err = "fetch"; goto failed; } D_ASSERT(key_iov.iov_len == sizeof(key)); memcpy(&key, key_iov.iov_buf, sizeof(key)); if (d != 0) { /* delete */ D_PRINT("Delete "DF_U64": %s\n", key, (char *)val_iov.iov_buf); rc = dbtree_iter_delete(ih, NULL); if (rc != 0) { err = "delete"; goto failed; } } else { /* iterate */ D_PRINT(DF_U64": %s\n", key, (char *)val_iov.iov_buf); if (opc == BTR_PROBE_LAST) rc = dbtree_iter_prev(ih); else rc = dbtree_iter_next(ih); if (rc == -DER_NONEXIST) break; if (rc != 0) { err = "move"; goto failed; } } } D_PRINT("%s iterator: total %d, deleted %d\n", opc == BTR_PROBE_FIRST ? "forward" : "backward", i, d); dbtree_iter_finish(ih); return 0; failed: D_PRINT("Iterator %s failed: %d\n", err, rc); dbtree_iter_finish(ih); return -1; }
void * direct_dbg_realloc( const char *file, int line, const char *func, const char *what, void *mem, size_t bytes ) { unsigned long *val; MemDesc *desc; D_DEBUG_AT( Direct_Mem, " *"_ZUn(6)" bytes [%s:%d in %s()] '%s' <- %p\n", bytes, file, line, func, what, mem ); if (!mem) return direct_dbg_malloc( file, line, func, bytes ); if (!bytes) { direct_dbg_free( file, line, func, what, mem ); return NULL; } val = (unsigned long*)((char*) mem - DISABLED_OFFSET); if (val[0] == ~0) { D_DEBUG_AT( Direct_Mem, " *"_ZUn(6)" bytes [%s:%d in %s()] '%s'\n", bytes, file, line, func, what ); val = direct_realloc( val, bytes + DISABLED_OFFSET ); D_DEBUG_AT( Direct_Mem, " '-> %p\n", val ); if (val) { D_ASSERT( val[0] == ~0 ); mem = val; return (char*) mem + DISABLED_OFFSET; } return NULL; } /* Debug only. */ direct_mutex_lock( &alloc_lock ); desc = (MemDesc*)((char*) mem - sizeof(MemDesc)); D_ASSERT( desc->mem == mem ); if (direct_hash_remove( &alloc_hash, (unsigned long) mem )) { D_ERROR( "Direct/Mem: Not reallocating unknown %p (%s) from [%s:%d in %s()] - corrupt/incomplete list?\n", mem, what, file, line, func ); mem = direct_dbg_malloc( file, line, func, bytes ); } else { void *new_mem = direct_realloc( desc, bytes + sizeof(MemDesc) ); D_DEBUG_AT( Direct_Mem, " '-> %p\n", new_mem ); D_DEBUG_AT( Direct_Mem, " %c"_ZUn(6)" bytes [%s:%d in %s()] (%s"_ZU") <- %p -> %p '%s'\n", (bytes > desc->bytes) ? '>' : '<', bytes, file, line, func, (bytes > desc->bytes) ? "+" : "", bytes - desc->bytes, mem, new_mem, what); if (desc->trace) { direct_trace_free_buffer( desc->trace ); desc->trace = NULL; } if (!new_mem) D_WARN( "could not reallocate memory (%p: "_ZU"->"_ZU")", mem, desc->bytes, bytes ); else desc = fill_mem_desc( new_mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) ); mem = desc->mem; } direct_mutex_unlock( &alloc_lock ); return mem; }
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 ); }
/* HACK: implementation dumped in here for now, will move into context */ static DFBResult wm_update_cursor( CoreWindowStack *stack, void *wm_data, void *stack_data, CoreCursorUpdateFlags flags ) { DFBResult ret; DFBRegion old_region; WMData *wmdata = wm_data; StackData *data = stack_data; bool restored = false; CoreLayer *layer; CoreLayerRegion *region; CardState *state; CoreSurface *surface; UniqueContext *context; D_ASSERT( stack != NULL ); D_ASSERT( stack->context != NULL ); D_ASSERT( wm_data != NULL ); D_ASSERT( stack_data != NULL ); D_MAGIC_ASSERT( data, StackData ); context = data->context; D_MAGIC_ASSERT( context, UniqueContext ); /* Optimize case of invisible cursor moving. */ if (!(flags & ~(CCUF_POSITION | CCUF_SHAPE)) && (!stack->cursor.opacity || !stack->cursor.enabled)) { context->cursor_bs_valid = false; return DFB_OK; } layer = dfb_layer_at( context->layer_id ); state = &layer->state; region = context->region; surface = context->surface; D_ASSERT( region != NULL ); D_ASSERT( surface != NULL ); if (flags & CCUF_ENABLE) { CoreSurface *cursor_bs; DFBSurfaceCapabilities caps = DSCAPS_NONE; dfb_surface_caps_apply_policy( stack->cursor.policy, &caps ); D_ASSERT( context->cursor_bs == NULL ); /* Create the cursor backing store surface. */ ret = dfb_surface_create_simple( wmdata->core, stack->cursor.size.w, stack->cursor.size.h, region->config.format, caps, CSTF_SHARED | CSTF_CURSOR, 0, /* FIXME: no shared cursor objects, no cursor id */ NULL, &cursor_bs ); if (ret) { D_ERROR( "WM/Default: Failed creating backing store for cursor!\n" ); return ret; } ret = dfb_surface_globalize( cursor_bs ); D_ASSERT( ret == DFB_OK ); /* Ensure valid back buffer for now. * FIXME: Keep a flag to know when back/front have been swapped and need a sync. */ switch (region->config.buffermode) { case DLBM_BACKVIDEO: case DLBM_TRIPLE: dfb_gfx_copy( surface, surface, NULL ); break; default: break; } context->cursor_bs = cursor_bs; } else { D_ASSERT( context->cursor_bs != NULL ); /* restore region under cursor */ if (context->cursor_drawn) { DFBRectangle rect = { 0, 0, context->cursor_region.x2 - context->cursor_region.x1 + 1, context->cursor_region.y2 - context->cursor_region.y1 + 1 }; D_ASSERT( stack->cursor.opacity || (flags & CCUF_OPACITY) ); D_ASSERT( context->cursor_bs_valid ); dfb_gfx_copy_to( context->cursor_bs, surface, &rect, context->cursor_region.x1, context->cursor_region.y1, false ); context->cursor_drawn = false; old_region = context->cursor_region; restored = true; } if (flags & CCUF_SIZE) { ret = dfb_surface_reformat( context->cursor_bs, stack->cursor.size.w, stack->cursor.size.h, context->cursor_bs->config.format ); if (ret) { D_ERROR( "WM/Default: Failed resizing backing store for cursor!\n" ); return ret; } } } if (flags & (CCUF_ENABLE | CCUF_POSITION | CCUF_SIZE | CCUF_OPACITY)) { context->cursor_bs_valid = false; context->cursor_region.x1 = stack->cursor.x - stack->cursor.hot.x; context->cursor_region.y1 = stack->cursor.y - stack->cursor.hot.y; context->cursor_region.x2 = context->cursor_region.x1 + stack->cursor.size.w - 1; context->cursor_region.y2 = context->cursor_region.y1 + stack->cursor.size.h - 1; if (!dfb_region_intersect( &context->cursor_region, 0, 0, stack->width - 1, stack->height - 1 )) { D_BUG( "invalid cursor region" ); return DFB_BUG; } } D_ASSERT( context->cursor_bs != NULL ); if (flags & CCUF_DISABLE) { dfb_surface_unlink( &context->cursor_bs ); } else if (stack->cursor.opacity) { /* backup region under cursor */ if (!context->cursor_bs_valid) { DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &context->cursor_region ); D_ASSERT( !context->cursor_drawn ); /* FIXME: this requires using blitted flipping all the time, but fixing it seems impossible, for now DSFLIP_BLIT is forced in repaint_stack() when the cursor is enabled. */ dfb_gfx_copy_to( surface, context->cursor_bs, &rect, 0, 0, true ); context->cursor_bs_valid = true; } /* Set destination. */ state->destination = surface; state->modified |= SMF_DESTINATION; /* Set clipping region. */ dfb_state_set_clip( state, &context->cursor_region ); /* draw cursor */ unique_draw_cursor( stack, context, state, &context->cursor_region ); /* Reset destination. */ state->destination = NULL; state->modified |= SMF_DESTINATION; context->cursor_drawn = true; if (restored) { if (dfb_region_region_intersects( &old_region, &context->cursor_region )) dfb_region_region_union( &old_region, &context->cursor_region ); else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); } else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); } else if (restored) dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); return DFB_OK; }
static DFBResult x11Read( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceAllocation *allocation, void *alloc_data, void *destination, int pitch, const DFBRectangle *rect ) { XImage *image; XImage *sub; x11PoolLocalData *local = pool_local; x11AllocationData *alloc = alloc_data; DFBX11 *x11 = local->x11; D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); D_DEBUG_AT( X11_Surfaces, " -> allocation: %s\n", ToString_CoreSurfaceAllocation( allocation ) ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); D_ASSERT( destination != NULL ); D_ASSERT( pitch >= 0 ); DFB_RECTANGLE_ASSERT( rect ); D_DEBUG_AT( X11_Surfaces, " => %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->xid, DFB_RECTANGLE_VALS(rect) ); XLockDisplay( x11->display ); #if 1 image = XCreateImage( x11->display, alloc->visual, alloc->depth, ZPixmap, 0, destination, rect->w, rect->h, 32, pitch ); if (!image) { D_ERROR( "X11/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth ); XUnlockDisplay( x11->display ); return DFB_FAILURE; } sub = XGetSubImage( x11->display, alloc->xid, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap, image, 0, 0 ); #else image = XGetImage( x11->display, alloc->window ? alloc->window : alloc->xid, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap ); #endif if (image) { // dfb_surface_buffer_dump_type_locked2( allocation->buffer, ".", "x11Read", false, image->data, image->bytes_per_line ); /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */ image->data = NULL; XDestroyImage( image ); } XUnlockDisplay( x11->display ); #if 1 if (!sub) { D_ERROR( "X11/Surfaces: XGetSubImage( %d,%d-%dx%d ) failed!\n", DFB_RECTANGLE_VALS(rect) ); return DFB_FAILURE; } #endif return DFB_OK; }
int main( int argc, char *argv[] ) { DirectResult ret; pid_t child_pid; TestMessage message = {0}; DirectFBInit( &argc, &argv ); ret = fusion_enter( -1, 0, FER_MASTER, &m_world ); if (ret) { D_DERROR( ret, "fusion_enter() failed" ); return ret; } MSG( "Entered world %d as master (FusionID %lu, pid %d)\n", fusion_world_index( m_world ), fusion_id( m_world ), getpid() ); ret = fusion_ref_init( &m_ref, "Test", m_world ); if (ret) { D_DERROR( ret, "fusion_ref_init() failed" ); return -1; } MSG( "Adding local reference...\n" ); fusion_ref_up( &m_ref, false ); m_reactor = fusion_reactor_new( sizeof(TestMessage), "Test", m_world ); if (!m_reactor) { D_ERROR( "fusion_reactor_new() failed\n" ); return -1; } MSG( "Attaching to reactor...\n" ); ret = fusion_reactor_attach( m_reactor, reaction_callback, NULL, &m_reaction ); if (ret) { D_DERROR( ret, "fusion_reactor_attach() failed" ); return ret; } MSG( ".........FORKING NOW.........\n" ); fusion_world_set_fork_action( m_world, FFA_FORK ); child_pid = fork(); fusion_world_set_fork_action( m_world, FFA_CLOSE ); switch (child_pid) { case -1: D_PERROR( "fork() failed" ); break; case 0: setsid(); MSG( "...arrived after fork() in child (pid %d)..\n", getpid() ); MSG( "..child (FusionID %lu).\n", fusion_id( m_world ) ); break; default: usleep( 200000 ); MSG( "...returned from fork() in parent, child pid %d.\n", child_pid ); break; } MSG( "Sending message via reactor...\n" ); fusion_reactor_dispatch( m_reactor, &message, true, NULL ); usleep( 200000 ); MSG( "Removing local reference...\n" ); fusion_ref_down( &m_ref, false ); usleep( 200000 ); MSG( "Exiting from world %d (FusionID %lu, pid %d)...\n", fusion_world_index( m_world ), fusion_id( m_world ), getpid() ); fusion_exit( m_world, false ); return 0; }
// FIXME: refactor, optionally using lio_listio static DirectResult SendReceive( VoodooLink *link, VoodooChunk *sends, size_t num_send, VoodooChunk *recvs, size_t num_recv ) { Link *l = link->priv; size_t i; ssize_t ret; int select_result; D_DEBUG_AT( Voodoo_Link, "%s( link %p, sends %p, num_send %zu, recvs %p, num_recv %zu )\n", __func__, link, sends, num_send, recvs, num_recv ); while (true) { fd_set fds_read; fd_set fds_write; struct timeval tv; FD_ZERO( &fds_read ); FD_ZERO( &fds_write ); if (num_recv) FD_SET( l->fd[0], &fds_read ); if (num_send) FD_SET( l->fd[1], &fds_write ); FD_SET( l->wakeup_fds[0], &fds_read ); tv.tv_sec = 0; tv.tv_usec = 1000000; D_DEBUG_AT( Voodoo_Link, " -> select( %s%s )...\n", num_recv ? "R" : " ", num_send ? "W" : " " ); select_result = select( MAX(MAX(l->wakeup_fds[0],l->fd[0]),l->fd[1])+1, &fds_read, &fds_write, NULL, &tv ); switch (select_result) { default: if (FD_ISSET( l->fd[1], &fds_write )) { D_DEBUG_AT( Voodoo_Link, " => WRITE\n" ); for (i=0; i<num_send; i++) { while (sends[i].done != sends[i].length) { #if 1 ret = send( l->fd[1], sends[i].ptr, sends[i].length, MSG_DONTWAIT ); if (ret < 0) { D_PERROR( "Voodoo/Link: Failed to send() data!\n" ); return DR_IO; } else { sends[i].done += ret; /* if (sends[i].done != sends[i].length) D_WARN( "partial send of %d/%d bytes", ret, sends[i].length ); else D_WARN( "full send of %d bytes", ret, sends[i].length ); */ return DR_OK; } #else struct aiocb cb; memset( &cb, 0, sizeof(struct aiocb) ); cb.aio_fildes = l->fd[1]; cb.aio_buf = sends[i].ptr; cb.aio_nbytes = sends[i].length; cb.aio_offset = (intptr_t)-1; cb.aio_sigevent.sigev_notify = SIGEV_NONE; ret = aio_write( &cb ); if (ret < 0) { D_PERROR( "Voodoo/Link: aio_write() failed!\n" ); return DR_IO; } else { do { const struct aiocb *cbs[] = { &cb }; ret = aio_suspend( cbs, 1, NULL ); if (ret < 0) { D_PERROR( "Voodoo/Link: aio_suspend() failed!\n" ); return DR_IO; } ret = aio_error( &cb ); } while (ret == EINPROGRESS); switch (ret) { case 0: ret = aio_return( &cb ); if (ret < 0) { D_ERROR( "Voodoo/Link: aio_return() failed!\n -> %s\n", strerror(ret) ); return DR_IO; } break; default: D_ERROR( "Voodoo/Link: aio_error() failed!\n -> %s\n", strerror(ret) ); return DR_IO; } sends[i].done += ret; /* if (sends[i].done != sends[i].length) D_WARN( "partial send of %d/%d bytes", ret, sends[i].length ); else D_WARN( "full send of %d bytes", ret, sends[i].length ); */ return DR_OK; } #endif } } } if (FD_ISSET( l->fd[0], &fds_read )) { D_DEBUG_AT( Voodoo_Link, " => READ\n" ); for (i=0; i<num_recv; i++) { ret = recv( l->fd[0], recvs[i].ptr, recvs[i].length, MSG_DONTWAIT ); if (ret < 0) { if (errno == EAGAIN) { break; } D_PERROR( "Voodoo/Link: Failed to recv() data!\n" ); return DR_FAILURE; } if (!ret) return DR_IO; recvs[i].done = ret; if (recvs[i].done < recvs[i].length) break; } } if (FD_ISSET( l->wakeup_fds[0], &fds_read )) { D_DEBUG_AT( Voodoo_Link, " => WAKE UP\n" ); static char buf[1000]; if (read( l->wakeup_fds[0], buf, sizeof(buf) ) < 0) return errno2result( errno ); if (!FD_ISSET( l->fd[0], &fds_read ) && !FD_ISSET( l->fd[0], &fds_write )) return DR_INTERRUPTED; } return DR_OK; case 0: D_DEBUG_AT( Voodoo_Link, " => TIMEOUT\n" ); return DR_TIMEOUT; case -1: D_ERROR( "Voodoo/Link: select() failed!\n" ); return DR_FAILURE; } } return DR_OK; }
static DirectResult SendReceive( VoodooLink *link, VoodooChunk *sends, size_t num_send, VoodooChunk *recvs, size_t num_recv ) { Link *l = link->priv; size_t i; ssize_t ret; DWORD wait_result; // direct_mutex_lock( &l->lock ); for (i=0; i<num_send; i++) { //printf("writing %d\n",sends[i].length); ret = send( l->socket, sends[i].ptr, sends[i].length, 0 ); //printf("wrote %d/%d\n",ret,sends[i].length); if (ret < 0) { if (WSAGetLastError() == 10035) { break; } D_PERROR( "Voodoo/Link: Failed to send() data error %d!\n", WSAGetLastError() ); } else { sends[i].done = (size_t) ret; if (sends[i].done != sends[i].length) { D_UNIMPLEMENTED(); // direct_mutex_unlock( &l->lock ); return DR_UNIMPLEMENTED; } return DR_OK; } } while (true) { LONG events = 0; WSANETWORKEVENTS WsaNetworkEvents; if (num_recv) { //printf("wait for recv\n"); events |= FD_READ; } if (num_send) { //printf("wait for send\n"); events |= FD_WRITE; } WSAEventSelect( l->socket, l->event, events ); wait_result = WSAWaitForMultipleEvents( 1, &l->event, FALSE, 10, FALSE ); switch (wait_result) { case WSA_WAIT_EVENT_0: WSAResetEvent( l->event ); WSAEnumNetworkEvents(l->socket, l->event, &WsaNetworkEvents); //printf("<-- events 0x%08x\n",WsaNetworkEvents.lNetworkEvents); if (!WsaNetworkEvents.lNetworkEvents) return DR_INTERRUPTED; if (WsaNetworkEvents.lNetworkEvents & FD_WRITE) { //printf("<-- event write\n"); for (i=0; i<num_send; i++) { //printf("writing %d\n",sends[i].length); ret = send( l->socket, sends[i].ptr, sends[i].length, 0 ); //printf("wrote %d/%d\n",ret,sends[i].length); if (ret < 0) { if (WSAGetLastError() == 10035) { break; } D_PERROR( "Voodoo/Link: Failed to send() data error %d!\n", WSAGetLastError() ); return DR_IO; } else { sends[i].done = (size_t) ret; if (sends[i].done != sends[i].length) { D_UNIMPLEMENTED(); // direct_mutex_unlock( &l->lock ); return DR_UNIMPLEMENTED; } return DR_OK; } } } if (WsaNetworkEvents.lNetworkEvents & FD_READ) { //printf("<-- event read\n"); for (i=0; i<num_recv; i++) { ret = recv( l->socket, recvs[i].ptr, recvs[i].length, 0 ); //printf("read %d\n",ret); if (ret < 0) { if (WSAGetLastError() == 10035) { break; } D_PERROR( "Voodoo/Link: Failed to recv() data error %d!\n", WSAGetLastError() ); // direct_mutex_unlock( &l->lock ); return DR_IO; } recvs[i].done = (size_t) ret; if (recvs[i].done < recvs[i].length) return DR_OK; return DR_OK; } } break; case WSA_WAIT_TIMEOUT: //printf("<-- timeout\n"); return DR_TIMEOUT; break; default: D_ERROR( "Voodoo/Link: WaitForMultipleObjects() failed!\n" ); return DR_FAILURE; } } // direct_mutex_unlock( &l->lock ); return DR_OK; }
DirectResult voodoo_link_init_local( VoodooLink *link, const char *path, bool raw ) { DirectResult ret; int err; struct sockaddr_un addr; Link *l; D_ASSERT( link != NULL ); D_ASSERT( path != NULL ); l = D_CALLOC( 1, sizeof(Link) ); if (!l) return D_OOM(); /* Create the client socket. */ l->fd[0] = socket( AF_LOCAL, SOCK_STREAM, 0 ); if (l->fd[0] < 0) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket creation failed!\n" ); D_FREE( l ); return ret; } l->fd[1] = l->fd[0]; #if !VOODOO_BUILD_NO_SETSOCKOPT if (setsockopt( l->fd[0], SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0) D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" ); if (setsockopt( l->fd[0], SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0) D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" ); #endif D_INFO( "Voodoo/Link: Connecting to '%s'...\n", path ); memset( &addr, 0, sizeof(addr) ); /* Bind the socket to the local port. */ addr.sun_family = AF_UNIX; snprintf( addr.sun_path + 1, UNIX_PATH_MAX - 1, "%s", path ); /* Connect to the server. */ err = connect( l->fd[0], (struct sockaddr*) &addr, strlen(addr.sun_path+1)+1 + sizeof(addr.sun_family) ); if (err) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket connect failed!\n" ); close( l->fd[0] ); D_FREE( l ); return ret; } D_INFO( "Voodoo/Link: Connected.\n" ); DUMP_SOCKET_OPTION( l->fd[0], SO_SNDLOWAT ); DUMP_SOCKET_OPTION( l->fd[0], SO_RCVLOWAT ); DUMP_SOCKET_OPTION( l->fd[0], SO_SNDBUF ); DUMP_SOCKET_OPTION( l->fd[0], SO_RCVBUF ); if (!raw) { link->code = 0x80008676; if (write( l->fd[1], &link->code, sizeof(link->code) ) != 4) { D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" ); close( l->fd[0] ); D_FREE( l ); return DR_IO; } } D_INFO( "Voodoo/Link: Sent link code (%s).\n", raw ? "raw" : "packet" ); if (pipe( l->wakeup_fds )) return errno2result( errno ); link->priv = l; link->Close = Close; link->Read = Read; link->Write = Write; link->SendReceive = SendReceive; link->WakeUp = WakeUp; link->WaitForData = WaitForData; return DR_OK; }
DirectResult voodoo_link_init_connect( VoodooLink *link, const char *hostname, int port, bool raw ) { int ret; struct sockaddr_in addr; Link *l; D_INFO( "Voodoo/Link: Connecting to '%s:%d'...\n", hostname, port ); StartWinsock(); l = D_CALLOC( 1, sizeof(Link) ); if (!l) return D_OOM(); l->socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (l->socket == INVALID_SOCKET) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket creation failed!\n" ); D_FREE( l ); return ret; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr( hostname ); addr.sin_port = htons( port ); ret = connect( l->socket, (const struct sockaddr*) &addr, sizeof(addr) ); if (ret < 0) { ret = errno2result( errno ); D_PERROR( "Voodoo/Link: Socket connect failed!\n" ); // FIXME: how to close the socket? D_FREE( l ); return ret; } direct_mutex_init( &l->lock ); l->event = WSACreateEvent(); if (!raw) { link->code = 0x80008676; if (send( l->socket, (const char*) &link->code, sizeof(link->code), 0 ) != 4) { D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" ); // FIXME: how to close the socket? D_FREE( l ); return DR_IO; } } link->priv = l; link->Close = Close; link->Read = Read; link->Write = Write; link->SendReceive = SendReceive; link->WakeUp = WakeUp; link->WaitForData = WaitForData; return DR_OK; }
DFBResult dfb_x11_image_init_handler( DFBX11 *x11, x11Image *image ) { Visual *visual; XImage *ximage; D_MAGIC_ASSERT( image, x11Image ); if (!x11->use_shm) return DFB_UNSUPPORTED; /* Lookup visual. */ visual = x11->visuals[DFB_PIXELFORMAT_INDEX(image->format)]; if (!visual) return DFB_UNSUPPORTED; image->visual = visual; XLockDisplay( x11->display ); ximage = XShmCreateImage( x11->display, image->visual, image->depth, ZPixmap, NULL, &image->seginfo, image->width, image->height ); if (!ximage) { D_ERROR( "X11/ShmImage: Error creating shared image (XShmCreateImage)!\n"); XUnlockDisplay( x11->display ); return DFB_FAILURE; } /* we firstly create our shared memory segment with the size we need, and correct permissions for the owner, the group and the world --> 0777 */ image->seginfo.shmid = shmget( IPC_PRIVATE, ximage->bytes_per_line * ximage->height, IPC_CREAT | 0777 ); if (image->seginfo.shmid < 0) goto error; /* Then, we have to attach the segment to our process, and we let the function search the correct memory place --> NULL. It's safest ! */ image->seginfo.shmaddr = shmat( image->seginfo.shmid, NULL, 0 ); if (!image->seginfo.shmaddr) goto error_shmat; ximage->data = image->seginfo.shmaddr; /* We set the buffer in Read and Write mode */ image->seginfo.readOnly = False; if (!XShmAttach( x11->display, &image->seginfo )) goto error_xshmattach; image->ximage = ximage; image->pitch = ximage->bytes_per_line; image->pixmap = XShmCreatePixmap( x11->display, DefaultRootWindow(x11->display), ximage->data, &image->seginfo, image->width, image->height, image->depth ); image->gc = XCreateGC( x11->display, image->pixmap, 0, NULL ); XUnlockDisplay( x11->display ); return DFB_OK; error_xshmattach: shmdt( image->seginfo.shmaddr ); error_shmat: shmctl( image->seginfo.shmid, IPC_RMID, NULL ); error: XDestroyImage( ximage ); XUnlockDisplay( x11->display ); return DFB_FAILURE; }
static int ik_btr_open_create(bool create, char *args) { bool inplace = false; uint64_t feats = 0; int rc; if (!daos_handle_is_inval(ik_toh)) { D_ERROR("Tree has been opened\n"); return -1; } if (create && args != NULL) { if (args[0] == '+') { feats = BTR_FEAT_UINT_KEY; args += 1; } if (args[0] == 'i') { /* inplace create/open */ inplace = true; if (args[1] != IK_SEP) { D_ERROR("wrong parameter format %s\n", args); return -1; } args += 2; } if (args[0] != 'o' || args[1] != IK_SEP_VAL) { D_ERROR("incorrect format for tree order: %s\n", args); return -1; } ik_order = atoi(&args[2]); if (ik_order < BTR_ORDER_MIN || ik_order > BTR_ORDER_MAX) { D_ERROR("Invalid tree order %d\n", ik_order); return -1; } } else if (!create) { inplace = (ik_root->tr_class != 0); if (TMMID_IS_NULL(ik_root_mmid) && !inplace) { D_ERROR("Please create tree first\n"); return -1; } } if (create) { D_PRINT("Create btree with order %d%s feats "DF_X64"\n", ik_order, inplace ? " inplace" : "", feats); if (inplace) { rc = dbtree_create_inplace(IK_TREE_CLASS, feats, ik_order, ik_uma, ik_root, &ik_toh); } else { rc = dbtree_create(IK_TREE_CLASS, feats, ik_order, ik_uma, &ik_root_mmid, &ik_toh); } } else { D_PRINT("Open btree%s\n", inplace ? " inplace" : ""); if (inplace) { rc = dbtree_open_inplace(ik_root, ik_uma, &ik_toh); } else { rc = dbtree_open(ik_root_mmid, ik_uma, &ik_toh); } } if (rc != 0) { D_ERROR("Tree %s failed: %d\n", create ? "create" : "open", rc); return -1; } return 0; }
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 DFBResult drmkmsInitScreen( CoreScreen *screen, CoreGraphicsDevice *device, void *driver_data, void *screen_data, DFBScreenDescription *description ) { DRMKMSData *drmkms = driver_data; DRMKMSDataShared *shared = drmkms->shared; drmModeRes *resources; drmModeConnector *connector = NULL; drmModeEncoder *encoder = NULL; uint32_t crtc = 0; int i, j, k, l, found; description->caps = DSCCAPS_ENCODERS | DSCCAPS_OUTPUTS; description->encoders = 0; shared->enabled_crtcs = 0; direct_snputs( description->name, "DRMKMS Screen", DFB_SCREEN_DESC_NAME_LENGTH ); resources = drmkms->resources; D_INFO( "DirectFB/DRMKMS: Got %d connectors, %d encoders\n", resources->count_connectors, resources->count_encoders ); for (i = 0; i < resources->count_connectors; i++) { crtc = 0; connector = drmModeGetConnector( drmkms->fd, resources->connectors[i] ); if (!connector) continue; if ((connector->connection == DRM_MODE_CONNECTED || connector->connection == DRM_MODE_UNKNOWNCONNECTION) && connector->count_modes > 0) { D_INFO( "DirectFB/DRMKMS: found connected connector id %d.\n", connector->connector_id ); if (connector->encoder_id) { D_INFO( "DirectFB/DRMKMS: connector %d is already bound to encoder %d.\n", connector->connector_id, connector->encoder_id ); encoder = drmModeGetEncoder(drmkms->fd, connector->encoder_id); } if (encoder) crtc = encoder->crtc_id; if (crtc) D_INFO( "DirectFB/DRMKMS: encoder %d is already bound to ctrc %d.\n", connector->encoder_id, encoder->crtc_id ); else { D_INFO( "DirectFB/DRMKMS: Seaching for appropriate encoder/crtc for connector %d.\n", connector->connector_id ); for (j = 0; j < resources->count_encoders; j++) { int busy = 0; encoder = drmModeGetEncoder( drmkms->fd, resources->encoders[j] ); if (encoder == NULL) continue; for (k=0; k<shared->enabled_crtcs; k++) { if (drmkms->encoder[k]->encoder_id == encoder->encoder_id) { D_INFO( "DirectFB/DRMKMS: encoder %d is already in use by connector %d\n", encoder->encoder_id, drmkms->connector[k]->connector_id ); busy = 1; } } if (busy) continue; found = 0; for (k = 0; k < resources->count_crtcs; k++) { busy = 0; if (!(encoder->possible_crtcs & (1 << k))) continue; for (l=0; l<shared->enabled_crtcs; l++) { if (drmkms->encoder[l]->crtc_id == resources->crtcs[k]) busy = 1; } if (busy) continue; crtc = resources->crtcs[k]; D_INFO( "DirectFB/DRMKMS: using encoder %d and crtc %d for connector %d.\n", encoder->encoder_id, crtc, connector->connector_id ); found = 1; break; } if (found) break; } } if (encoder && crtc) { drmkms->connector[shared->enabled_crtcs] = connector; drmkms->encoder[shared->enabled_crtcs] = encoder; drmkms->encoder[shared->enabled_crtcs]->crtc_id = crtc; shared->mode[shared->enabled_crtcs] = connector->modes[0]; shared->enabled_crtcs++; if (!shared->multihead && !shared->mirror_outputs) break; if (shared->multihead && shared->enabled_crtcs > 1) { dfb_layers_register( drmkms->screen, drmkms, drmkmsLayerFuncs ); } } else if (encoder) drmModeFreeEncoder( encoder ); encoder = NULL; } else drmModeFreeConnector( connector ); } if (!shared->enabled_crtcs) { D_ERROR( "DirectFB/DRMKMS: No currently active connector found.\n"); return DFB_INIT; } if (dfb_config->mode.width && dfb_config->mode.height) { drmModeModeInfo *mode = drmkms_find_mode( 0, dfb_config->mode.width, dfb_config->mode.height, 0 ); if (mode) shared->mode[0] = *mode; } if (shared->mirror_outputs || (dfb_config->mode.width && dfb_config->mode.height)) { for (int i=1; i<shared->enabled_crtcs; i++) shared->mode[i] = shared->mode[0]; } if (shared->clone_outputs) { if (drmkms->encoder[0]->possible_clones) { for (i = 0; i < resources->count_crtcs; i++) { if (drmkms->encoder[0]->possible_clones & (1 << i)) { shared->cloned_connectors[shared->cloned_count++] = resources->connectors[0]; shared->cloned_connectors[shared->cloned_count++] = resources->connectors[1]; D_INFO( "DirectFB/DRMKMS: cloning on connector %d and %d enabled \n", resources->connectors[0], resources->connectors[1]); break; } } if (shared->cloned_count < 2) { D_WARN( "DirectFB/DRMKMS: cloning is not possible on enough connectors, disabling.\n" ); shared->cloned_count = 0; shared->clone_outputs = false; } } else { D_WARN( "DirectFB/DRMKMS: cloning is not possible, disabling.\n" ); shared->clone_outputs = false; } } D_INFO( "DirectFB/DRMKMS: Default mode is %dx%d, we have %d modes in total\n", shared->mode[0].hdisplay, shared->mode[0].vdisplay, drmkms->connector[0]->count_modes ); drmkms->resources = resources; drmkms->saved_crtc = drmModeGetCrtc( drmkms->fd, drmkms->encoder[0]->crtc_id ); description->outputs = shared->enabled_crtcs; description->encoders = shared->enabled_crtcs; return DFB_OK; }