static void dump_outputs( IDirectFBScreen *screen, int num ) { int i, n; DFBResult ret; DFBScreenOutputDescription *descs; DFBScreenOutputConfig conf; descs = (DFBScreenOutputDescription*) D_CALLOC( num, sizeof(*descs) ); if (!descs) { D_OOM(); return; } ret = screen->GetOutputDescriptions( screen, descs ); if (ret) { DirectFBError( "IDirectFBScreen::GetOutputDescriptions", ret ); D_FREE( descs ); return; } for (i=0; i<num; i++) { printf( " Output (%d) %s\n", i, descs[i].name ); /* Caps */ printf( " Caps: " ); for (n=0; output_caps[n].capability; n++) { if (descs[i].caps & output_caps[n].capability) printf( "%s ", output_caps[n].name ); } printf( "\n" ); /* Connectors */ if (descs[i].caps & DSOCAPS_CONNECTORS) { printf( " Connectors: " ); for (n=0; connectors[n].connector; n++) { if (descs[i].all_connectors & connectors[n].connector) printf( "%s ", connectors[n].name ); } printf( "\n" ); } /* Output Resolutions */ if (descs[i].caps & DSOCAPS_RESOLUTION) { printf( " Resolutions: " ); for (n=0; resolutions[n].resolution; n++) { if (descs[i].all_resolutions & resolutions[n].resolution) printf( "%s ", resolutions[n].name ); } printf( "\n" ); } /* Signals */ printf( " Signals: " ); for (n=0; signals[n].signal; n++) { if (descs[i].all_signals & signals[n].signal) printf( "%s ", signals[n].name ); } printf( "\n" ); ret = screen->GetOutputConfiguration( screen, i, &conf ); if (ret) { DirectFBError( "IDirectFBScreen::GetOutputConfiguration", ret ); D_FREE( descs ); return; } if (conf.flags & DSOCONF_ENCODER) printf( " Encoder: %d (current)\n", conf.encoder ); printf( "\n" ); } printf( "\n" ); D_FREE( descs ); }
/* fill device info structure */ snprintf( info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "H3600 Touchscreen" ); snprintf( info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "Unknown" ); info->prefered_id = DIDID_MOUSE; info->desc.type = DIDTF_MOUSE; info->desc.caps = DICAPS_AXES | DICAPS_BUTTONS; info->desc.max_axis = DIAI_Y; info->desc.max_button = DIBI_LEFT; /* allocate and fill private data */ data = D_CALLOC( 1, sizeof(H3600TSData) ); data->fd = fd; data->device = device; /* start input thread */ data->thread = direct_thread_create( DTT_INPUT, h3600tsEventThread, data, "H3600 TS Input" ); /* set private data pointer */ *driver_data = data; return DFB_OK; } /* * Fetch one entry from the device's keymap if supported.
static void dump_mixers( IDirectFBScreen *screen, int num ) { int i, n; DFBResult ret; DFBScreenMixerDescription *descs; descs = (DFBScreenMixerDescription*) D_CALLOC( num, sizeof(*descs) ); if (!descs) { D_OOM(); return; } ret = screen->GetMixerDescriptions( screen, descs ); if (ret) { DirectFBError( "IDirectFBScreen::GetMixerDescriptions", ret ); D_FREE( descs ); return; } for (i=0; i<num; i++) { printf( " Mixer (%d) %s\n", i, descs[i].name ); /* Caps */ printf( " Caps: " ); for (n=0; mixer_caps[n].capability; n++) { if (descs[i].caps & mixer_caps[n].capability) printf( "%s ", mixer_caps[n].name ); } printf( "\n" ); /* Full mode layers */ if (descs[i].caps & DSMCAPS_FULL) { printf( " Layers (full mode): " ); for (n=0; n<DFB_DISPLAYLAYER_IDS_MAX; n++) { if (DFB_DISPLAYLAYER_IDS_HAVE( descs[i].layers, n )) printf( "(%02x) ", n ); } printf( "\n" ); } /* Sub mode layers */ if (descs[i].caps & DSMCAPS_SUB_LAYERS) { printf( " Layers (sub mode): %2d of ", descs[i].sub_num ); for (n=0; n<DFB_DISPLAYLAYER_IDS_MAX; n++) { if (DFB_DISPLAYLAYER_IDS_HAVE( descs[i].sub_layers, n )) printf( "(%02x) ", n ); } printf( "\n" ); } printf( "\n" ); } printf( "\n" ); D_FREE( descs ); }
static void dump_encoders( IDirectFBScreen *screen, int num ) { int i, n; DFBResult ret; DFBScreenEncoderDescription *descs; DFBScreenEncoderConfig conf; descs = (DFBScreenEncoderDescription*) D_CALLOC( num, sizeof(*descs) ); if (!descs) { D_OOM(); return; } ret = screen->GetEncoderDescriptions( screen, descs ); if (ret) { DirectFBError( "IDirectFBScreen::GetEncoderDescriptions", ret ); D_FREE( descs ); return; } for (i=0; i<num; i++) { printf( " Encoder (%d) %s\n", i, descs[i].name ); /* Type */ printf( " Type: " ); for (n=0; encoder_type[n].type; n++) { if (descs[i].type & encoder_type[n].type) printf( "%s ", encoder_type[n].name ); } printf( "\n" ); /* Caps */ printf( " Caps: " ); for (n=0; encoder_caps[n].capability; n++) { if (descs[i].caps & encoder_caps[n].capability) printf( "%s ", encoder_caps[n].name ); } printf( "\n" ); /* TV Norms */ if (descs[i].caps & DSECAPS_TV_STANDARDS) { printf( " TV Standards: " ); for (n=0; tv_standards[n].standard; n++) { if (descs[i].tv_standards & tv_standards[n].standard) printf( "%s ", tv_standards[n].name ); } printf( "\n" ); } /* Output signals */ if (descs[i].caps & DSECAPS_OUT_SIGNALS) { printf( " Output Signals: " ); for (n=0; signals[n].signal; n++) { if (descs[i].out_signals & signals[n].signal) printf( "%s ", signals[n].name ); } printf( "\n" ); } /* Output Resolutions */ if (descs[i].caps & DSECAPS_RESOLUTION) { printf( " Output Resolutions: " ); for (n=0; resolutions[n].resolution; n++) { if (descs[i].all_resolutions & resolutions[n].resolution) printf( "%s ", resolutions[n].name ); } printf( "\n" ); } /* Output connectors */ if (descs[i].caps & DSECAPS_CONNECTORS) { printf( " Output Connectors: " ); for (n=0; connectors[n].connector; n++) { if (descs[i].all_connectors & connectors[n].connector) printf( "%s ", connectors[n].name ); } printf( "\n" ); } /* Picture Framing */ if (descs[i].caps & DSECAPS_FRAMING) { printf( " Framing: " ); for (n=0; framings[n].framing; n++) { if (descs[i].all_framing & framings[n].framing) printf( "%s ", framings[n].name ); } printf( "\n" ); } ret = screen->GetEncoderConfiguration( screen, i, &conf ); if (ret) { DirectFBError( "IDirectFBScreen::GetEncoderConfiguration", ret ); D_FREE( descs ); return; } if (conf.flags & DSECONF_MIXER) printf( " Mixer: %d (current)\n", conf.mixer ); printf( "\n" ); } printf( "\n" ); D_FREE( descs ); }
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" ); pipe( l->wakeup_fds ); link->priv = l; link->Close = Close; link->Read = Read; link->Write = Write; link->SendReceive = SendReceive; link->WakeUp = WakeUp; link->WaitForData = WaitForData; return DR_OK; }
static DFBEnumerationResult display_layer_callback( DFBDisplayLayerID id, DFBDisplayLayerDescription desc, void *arg ) { int i; /* Name */ printf( " Layer (%02x) %-30s", id, desc.name ); switch (id) { case DLID_PRIMARY: printf( " (primary layer)" ); break; default: break; } printf( "\n" ); /* Type */ printf( " Type: " ); for (i=0; layer_types[i].type; i++) { if (desc.type & layer_types[i].type) printf( "%s ", layer_types[i].name ); } printf( "\n" ); /* Caps */ printf( " Caps: " ); for (i=0; layer_caps[i].capability; i++) { if (desc.caps & layer_caps[i].capability) printf( "%s ", layer_caps[i].name ); } printf( "\n" ); /* Sources */ if (desc.caps & DLCAPS_SOURCES) { DFBResult ret; IDirectFBDisplayLayer *layer; ret = dfb->GetDisplayLayer( dfb, id, &layer ); if (ret) { DirectFBError( "DirectFB::GetDisplayLayer() failed", ret ); } else { DFBDisplayLayerSourceDescription *descs; descs = (DFBDisplayLayerSourceDescription*) D_CALLOC( desc.sources, sizeof(*descs) ); if (descs) { ret = layer->GetSourceDescriptions( layer, descs ); if (ret) { DirectFBError( "DirectFBDisplayLayer::GetSourceDescriptions() failed", ret ); } else { printf( " Sources: " ); for (i=0; i<desc.sources; i++) { if (i > 0) printf( ", %s", descs[i].name ); else printf( "%s", descs[i].name ); } printf( "\n" ); } D_FREE( descs ); } else D_OOM(); layer->Release( layer ); } } printf( "\n" ); return DFENUM_OK; }
DFBResult dfb_vt_initialize( void ) { DFBResult ret; struct vt_stat vs; D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); dfb_vt = D_CALLOC( 1, sizeof(VirtualTerminal) ); if (!dfb_vt) return D_OOM(); setsid(); dfb_vt->fd0 = open( "/dev/tty0", O_RDONLY | O_NOCTTY ); if (dfb_vt->fd0 < 0) { if (errno == ENOENT) { dfb_vt->fd0 = open( "/dev/vc/0", O_RDONLY | O_NOCTTY ); if (dfb_vt->fd0 < 0) { if (errno == ENOENT) { D_PERROR( "DirectFB/core/vt: Couldn't open " "neither `/dev/tty0' nor `/dev/vc/0'!\n" ); } else { D_PERROR( "DirectFB/core/vt: " "Error opening `/dev/vc/0'!\n" ); } D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } } else { D_PERROR( "DirectFB/core/vt: Error opening `/dev/tty0'!\n"); D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } } if (ioctl( dfb_vt->fd0, VT_GETSTATE, &vs ) < 0) { D_PERROR( "DirectFB/core/vt: VT_GETSTATE failed!\n" ); close( dfb_vt->fd0 ); D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } dfb_vt->prev = vs.v_active; if (!dfb_config->vt_switch) { if (dfb_config->vt_num != -1) dfb_vt->num = dfb_config->vt_num; else dfb_vt->num = dfb_vt->prev; /* move vt to framebuffer */ dfb_vt->old_fb = vt_get_fb( dfb_vt->num ); vt_set_fb( dfb_vt->num, -1 ); } else { if (dfb_config->vt_num == -1) { int n; n = ioctl( dfb_vt->fd0, VT_OPENQRY, &dfb_vt->num ); if (n < 0 || dfb_vt->num == -1) { D_PERROR( "DirectFB/core/vt: Cannot allocate VT!\n" ); close( dfb_vt->fd0 ); D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } } else { dfb_vt->num = dfb_config->vt_num; } /* move vt to framebuffer */ dfb_vt->old_fb = vt_get_fb( dfb_vt->num ); vt_set_fb( dfb_vt->num, -1 ); /* switch to vt */ while (ioctl( dfb_vt->fd0, VT_ACTIVATE, dfb_vt->num ) < 0) { if (errno == EINTR) continue; D_PERROR( "DirectFB/core/vt: VT_ACTIVATE failed!\n" ); close( dfb_vt->fd0 ); D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } while (ioctl( dfb_vt->fd0, VT_WAITACTIVE, dfb_vt->num ) < 0) { if (errno == EINTR) continue; D_PERROR( "DirectFB/core/vt: VT_WAITACTIVE failed!\n" ); close( dfb_vt->fd0 ); D_FREE( dfb_vt ); dfb_vt = NULL; return DFB_INIT; } usleep( 40000 ); } ret = vt_init_switching(); if (ret) { if (dfb_config->vt_switch) { D_DEBUG_AT( VT, " -> switching back...\n" ); ioctl( dfb_vt->fd0, VT_ACTIVATE, dfb_vt->prev ); ioctl( dfb_vt->fd0, VT_WAITACTIVE, dfb_vt->prev ); D_DEBUG_AT( VT, " -> ...switched back\n" ); ioctl( dfb_vt->fd0, VT_DISALLOCATE, dfb_vt->num ); } close( dfb_vt->fd0 ); D_FREE( dfb_vt ); dfb_vt = NULL; return ret; } vt_start_flushing(); dfb_fbdev->vt = dfb_vt; return DFB_OK; }
static int do_face( const Face *face ) { int i, ret; int align = DFB_PIXELFORMAT_ALIGNMENT( m_format ); int num_glyphs = 0; int num_rows = 1; int row_index = 0; int row_offset = 0; int next_face = sizeof(DGIFFFaceHeader); int total_height = 0; Entity::vector glyph_vector; unsigned int glyph_count = 0; DGIFFFaceHeader header; DGIFFGlyphInfo *glyphs; DGIFFGlyphRow *rows; void **row_data; DFBSurfaceDescription *descs; D_DEBUG_AT( mkdgiff, "%s( %p )\n", __FUNCTION__, face ); get_entities( face->buf, face->length, glyph_vector ); glyph_count = glyph_vector.size(); /* Clear to not leak any data into file. */ memset( &header, 0, sizeof(header) ); /* Allocate glyph info array. */ glyphs = (DGIFFGlyphInfo*) D_CALLOC( glyph_count, sizeof(DGIFFGlyphInfo) ); rows = (DGIFFGlyphRow*) D_CALLOC( glyph_count, sizeof(DGIFFGlyphRow) ); /* WORST case :) */ row_data = (void**) D_CALLOC( glyph_count, sizeof(void*) ); /* WORST case :) */ descs = (DFBSurfaceDescription*) D_CALLOC( glyph_count, sizeof(DFBSurfaceDescription) ); /* WORST case :) */ for (Entity::vector::const_iterator iter = glyph_vector.begin(); iter != glyph_vector.end(); iter++) { const Glyph *glyph = dynamic_cast<const Glyph*>( *iter ); glyph->Dump(); DGIFFGlyphInfo *info = &glyphs[num_glyphs]; DGIFFGlyphRow *row = &rows[num_rows - 1]; D_DEBUG_AT( mkdgiff, " -> code %3u\n", glyph->unicode ); ret = load_image( glyph->file.c_str(), &descs[num_glyphs] ); if (ret) continue; info->unicode = glyph->unicode; info->width = descs[num_glyphs].width; info->height = descs[num_glyphs].height; info->left = glyph->left; info->top = glyph->top; info->advance = glyph->advance; num_glyphs++; if (row->width > 0 && row->width + info->width > MAX_ROW_WIDTH) { num_rows++; row++; } row->width += (info->width + align) & ~align; if (row->height < info->height) row->height = info->height; } for (i=0; i<num_rows; i++) { DGIFFGlyphRow *row = &rows[i]; D_DEBUG_AT( mkdgiff, " -> row %d, width %d, height %d\n", i, row->width, row->height ); total_height += row->height; row->pitch = (DFB_BYTES_PER_LINE( m_format, row->width ) + 7) & ~7; row_data[i] = D_CALLOC( row->height, row->pitch ); next_face += row->height * row->pitch; } D_DEBUG_AT( mkdgiff, " -> %d glyphs, %d rows, total height %d\n", num_glyphs, num_rows, total_height ); next_face += num_glyphs * sizeof(DGIFFGlyphInfo); next_face += num_rows * sizeof(DGIFFGlyphRow); for (i=0; i<num_glyphs; i++) { DGIFFGlyphInfo *glyph = &glyphs[i]; D_DEBUG_AT( mkdgiff, " -> writing character 0x%x (%d)\n", glyph->unicode, i ); if (row_offset > 0 && row_offset + glyph->width > MAX_ROW_WIDTH) { row_index++; row_offset = 0; } D_DEBUG_AT( mkdgiff, " -> row offset %d\n", row_offset ); write_glyph( glyph, descs[i], (char*) row_data[row_index] + DFB_BYTES_PER_LINE( m_format, row_offset ), rows[row_index].pitch ); glyph->row = row_index; glyph->offset = row_offset; row_offset += (glyph->width + align) & ~align; } D_ASSERT( row_index == num_rows - 1 ); header.next_face = next_face; header.size = face->size; header.ascender = face->ascender; header.descender = face->descender; header.height = face->height; header.max_advance = face->maxadvance; header.pixelformat = m_format; header.num_glyphs = num_glyphs; header.num_rows = num_rows; header.blittingflags = face->blittingflags; D_DEBUG_AT( mkdgiff, " -> ascender %d, descender %d\n", header.ascender, header.descender ); D_DEBUG_AT( mkdgiff, " -> height %d, max advance %d\n", header.height, header.max_advance ); fwrite( &header, sizeof(header), 1, stdout ); fwrite( glyphs, sizeof(*glyphs), num_glyphs, stdout ); for (i=0; i<num_rows; i++) { DGIFFGlyphRow *row = &rows[i]; fwrite( row, sizeof(*row), 1, stdout ); fwrite( row_data[i], row->pitch, row->height, stdout ); } for (i=0; i<num_rows; i++) { if (row_data[i]) D_FREE( row_data[i] ); } D_FREE( row_data ); D_FREE( rows ); D_FREE( glyphs ); return 0; }
DFBResult dfb_font_get_glyph_data( CoreFont *font, unichar glyph, CoreGlyphData **ret_data ) { DFBResult ret; CoreGlyphData *data; D_MAGIC_ASSERT( font, CoreFont ); D_ASSERT( ret_data != NULL ); if ((data = direct_tree_lookup (font->glyph_infos, (void *)glyph)) != NULL) { *ret_data = data; return DFB_OK; } data = (CoreGlyphData *) D_CALLOC(1, sizeof (CoreGlyphData)); if (!data) return DFB_NOSYSTEMMEMORY; if (font->GetGlyphInfo && font->GetGlyphInfo (font, glyph, data) == DFB_OK && data->width > 0 && data->height > 0) { if (font->next_x + data->width > font->row_width) { CoreSurface *surface; if (font->row_width == 0) { int width = 8192 / font->height; if (width > 2048) width = 2048; if (width < font->maxadvance) width = font->maxadvance; font->row_width = (width + 7) & ~7; } ret = dfb_surface_create( font->core, font->row_width, MAX( font->height + 1, 8 ), font->pixel_format, CSP_VIDEOLOW, DSCAPS_NONE, NULL, &surface ); if (ret) { D_ERROR( "DirectFB/core/fonts: " "Could not create glyph surface! (%s)\n", DirectFBErrorString( ret ) ); D_FREE( data ); return ret; } font->next_x = 0; font->rows++; font->surfaces = D_REALLOC( font->surfaces, sizeof(void *) * font->rows ); font->surfaces[font->rows - 1] = surface; } if (font->RenderGlyph(font, glyph, data, font->surfaces[font->rows - 1]) == DFB_OK) { int align = DFB_PIXELFORMAT_ALIGNMENT(font->pixel_format); data->surface = font->surfaces[font->rows - 1]; data->start = font->next_x; font->next_x += (data->width + align) & ~align; dfb_gfxcard_flush_texture_cache(); } else { data->start = data->width = data->height = 0; } } else { data->start = data->width = data->height = 0; } direct_tree_insert (font->glyph_infos, (void *) glyph, data); *ret_data = data; return DFB_OK; }
DirectTree * direct_tree_new() { return D_CALLOC( 1, sizeof (DirectTree) ); }
DirectResult voodoo_manager_create( int fd, VoodooClient *client, VoodooServer *server, VoodooManager **ret_manager ) { DirectResult ret; VoodooManager *manager; int val; unsigned int len; static const int tos = IPTOS_LOWDELAY; D_ASSERT( fd >= 0 ); D_ASSERT( (client != NULL) ^ (server != NULL) ); D_ASSERT( ret_manager != NULL ); /* Allocate manager structure. */ manager = D_CALLOC( 1, sizeof(VoodooManager) ); if (!manager) { D_WARN( "out of memory" ); return DR_NOLOCALMEMORY; } D_DEBUG( "Voodoo/Manager: Creating manager at %p.\n", manager ); if (setsockopt( fd, SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0) D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" ); if (setsockopt( fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0) D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" ); DUMP_SOCKET_OPTION( SO_SNDLOWAT ); DUMP_SOCKET_OPTION( SO_RCVLOWAT ); DUMP_SOCKET_OPTION( SO_SNDBUF ); DUMP_SOCKET_OPTION( SO_RCVBUF ); /* Create the hash table for dispatcher instances. */ ret = direct_hash_create( 251, &manager->instances.local ); if (ret) { D_FREE( manager ); return ret; } /* Create the hash table for requestor instances. */ ret = direct_hash_create( 251, &manager->instances.remote ); if (ret) { direct_hash_destroy( manager->instances.local ); D_FREE( manager ); return ret; } /* Store file descriptor. */ manager->fd = fd; /* Store client or server. */ manager->client = client; manager->server = server; /* Initialize all locks. */ direct_util_recursive_pthread_mutex_init( &manager->instances.lock ); direct_util_recursive_pthread_mutex_init( &manager->response.lock ); direct_util_recursive_pthread_mutex_init( &manager->input.lock ); direct_util_recursive_pthread_mutex_init( &manager->output.lock ); /* Initialize all wait conditions. */ pthread_cond_init( &manager->response.wait, NULL ); pthread_cond_init( &manager->input.wait, NULL ); pthread_cond_init( &manager->output.wait, NULL ); /* Set default buffer limit. */ manager->input.max = IN_BUF_MAX; D_MAGIC_SET( manager, VoodooManager ); /* Create all threads. */ manager->dispatcher = direct_thread_create( DTT_MESSAGING, manager_dispatch_loop, manager, "Voodoo Dispatch" ); manager->input.thread = direct_thread_create( DTT_INPUT, manager_input_loop, manager, "Voodoo Input" ); manager->output.thread = direct_thread_create( DTT_OUTPUT, manager_output_loop, manager, "Voodoo Output" ); /* Return the new manager. */ *ret_manager = manager; 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(); } shared->outputs = direct_config_get_int_value_with_default( "x11-outputs", 1 ); shared->layers = direct_config_get_int_value_with_default( "x11-layers", 5 ); /* 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_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 ); dfb_surface_pool_initialize( core, &x11WindowPoolFuncs, &shared->x11window_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 core_arena_add_shared_field( core, "x11", shared ); return DFB_OK; }
DirectThread * direct_thread_create( DirectThreadType thread_type, DirectThreadMainFunc thread_main, void *arg, const char *name ) { DirectThread *thread; pthread_attr_t attr; struct sched_param param; int policy; int priority; size_t stack_size; D_ASSERT( thread_main != NULL ); D_ASSERT( name != NULL ); D_DEBUG_AT( Direct_Thread, "%s( %s, %p(%p), '%s' )\n", __FUNCTION__, direct_thread_type_name(thread_type), thread_main, arg, name ); /* Create the key for the TSD (thread specific data). */ pthread_mutex_lock( &key_lock ); if (thread_key == -1) pthread_key_create( &thread_key, NULL ); pthread_mutex_unlock( &key_lock ); /* Allocate thread structure. */ thread = D_CALLOC( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return NULL; } /* Write thread information to structure. */ thread->name = D_STRDUP( name ); thread->type = thread_type; thread->main = thread_main; thread->arg = arg; /* Initialize to -1 for synchronization. */ thread->thread = (pthread_t) -1; thread->tid = (pid_t) -1; /* Initialize mutex and condition. */ direct_util_recursive_pthread_mutex_init( &thread->lock ); pthread_cond_init( &thread->cond, NULL ); D_MAGIC_SET( thread, DirectThread ); /* Initialize scheduling and other parameters. */ pthread_attr_init( &attr ); pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); /* Select scheduler. */ switch (direct_config->thread_scheduler) { case DCTS_FIFO: policy = SCHED_FIFO; break; case DCTS_RR: policy = SCHED_RR; break; default: policy = SCHED_OTHER; break; } if (pthread_attr_setschedpolicy( &attr, policy )) D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) ); /* Read (back) value. */ pthread_attr_getschedpolicy( &attr, &policy ); /* Select priority. */ switch (thread->type) { case DTT_CLEANUP: case DTT_INPUT: case DTT_OUTPUT: case DTT_MESSAGING: case DTT_CRITICAL: priority = thread->type * direct_config->thread_priority_scale / 100; break; default: priority = direct_config->thread_priority; break; } D_DEBUG_AT( Direct_ThreadInit, " -> %s (%d) [%d;%d]\n", direct_thread_policy_name(policy), priority, sched_get_priority_min( policy ), sched_get_priority_max( policy ) ); if (priority < sched_get_priority_min( policy )) priority = sched_get_priority_min( policy ); if (priority > sched_get_priority_max( policy )) priority = sched_get_priority_max( policy ); param.sched_priority = priority; if (pthread_attr_setschedparam( &attr, ¶m )) D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority ); /* Select stack size? */ if (direct_config->thread_stack_size > 0) { if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size )) D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size ); } /* Read (back) value. */ pthread_attr_getstacksize( &attr, &stack_size ); /* Lock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" ); pthread_mutex_lock( &thread->lock ); /* Create and run the thread. */ D_DEBUG_AT( Direct_ThreadInit, " -> creating...\n" ); pthread_create( &thread->thread, &attr, direct_thread_main, thread ); pthread_attr_destroy( &attr ); pthread_getschedparam( thread->thread, &policy, ¶m ); D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n", name, thread->tid, direct_thread_type_name(thread_type), direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler), param.sched_priority, priority, stack_size ); #ifdef DIRECT_THREAD_WAIT_INIT /* Wait for completion of the thread's initialization. */ while (!thread->init) { D_DEBUG_AT( Direct_ThreadInit, " -> waiting...\n" ); pthread_cond_wait( &thread->cond, &thread->lock ); } D_DEBUG_AT( Direct_ThreadInit, " -> ...thread is running.\n" ); #endif /* Unlock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" ); pthread_mutex_unlock( &thread->lock ); D_DEBUG_AT( Direct_ThreadInit, " -> returning %p\n", thread ); return thread; }
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; }
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" ); pipe( l->wakeup_fds ); 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_core_create( CoreDFB **ret_core ) { int ret; #if FUSION_BUILD_MULTI char buf[16]; #endif CoreDFB *core = NULL; CoreDFBShared *shared = NULL; D_ASSERT( ret_core != NULL ); D_ASSERT( dfb_config != NULL ); D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); pthread_mutex_lock( &core_dfb_lock ); D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 ); if (core_dfb) { D_MAGIC_ASSERT( core_dfb, CoreDFB ); core_dfb->refs++; *ret_core = core_dfb; pthread_mutex_unlock( &core_dfb_lock ); return DFB_OK; } direct_initialize(); D_INFO( "DirectFB/Core: %s Application Core. ("BUILDTIME") %s%s\n", FUSION_BUILD_MULTI ? "Multi" : "Single", DIRECT_BUILD_DEBUG ? "[ DEBUG ]" : "", DIRECT_BUILD_TRACE ? "[ TRACE ]" : "" ); #if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) if (!dfb_lib_handle) #ifdef RTLD_GLOBAL dfb_lib_handle = dlopen(SOPATH, RTLD_GLOBAL|RTLD_LAZY); #else /* RTLD_GLOBAL is not defined on OpenBSD */ dfb_lib_handle = dlopen(SOPATH, RTLD_LAZY); #endif #endif ret = dfb_system_lookup(); if (ret) goto error; /* Allocate local core structure. */ core = D_CALLOC( 1, sizeof(CoreDFB) ); if (!core) { ret = D_OOM(); goto error; } core->refs = 1; core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core ); #if FUSION_BUILD_MULTI dfb_system_thread_init(); #endif direct_find_best_memcpy(); D_MAGIC_SET( core, CoreDFB ); core_dfb = core; ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world ); if (ret) goto error; core->fusion_id = fusion_id( core->world ); #if FUSION_BUILD_MULTI D_DEBUG_AT( DirectFB_Core, "world %d, fusion id %d\n", fusion_world_index(core->world), core->fusion_id ); snprintf( buf, sizeof(buf), "%d", fusion_world_index(core->world) ); setenv( "DIRECTFB_SESSION", buf, true ); #endif if (dfb_config->sync) { D_INFO( "DirectFB/Core: calling sync()...\n" ); sync(); } direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler ); if (fusion_arena_enter( core->world, "DirectFB/Core", dfb_core_arena_initialize, dfb_core_arena_join, core, &core->arena, &ret ) || ret) { ret = ret ? ret : DFB_FUSION; goto error; } shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); if (dfb_config->block_all_signals) direct_signals_block_all(); if (dfb_config->deinit_check) direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler ); fusion_skirmish_prevail( &shared->lock ); if (!core->master) { while (!shared->active) fusion_skirmish_wait( &shared->lock, 0 ); } fusion_skirmish_dismiss( &shared->lock ); *ret_core = core; pthread_mutex_unlock( &core_dfb_lock ); D_DEBUG_AT( DirectFB_Core, "Core successfully created.\n" ); return DFB_OK; error: if (core) { if (core->world) fusion_exit( core->world, false ); if (core->init_handler) direct_thread_remove_init_handler( core->init_handler ); if (core->signal_handler) direct_signal_handler_remove( core->signal_handler ); D_MAGIC_CLEAR( core ); D_FREE( core ); core_dfb = NULL; } pthread_mutex_unlock( &core_dfb_lock ); direct_shutdown(); return ret; }
DirectResult voodoo_play_get_broadcast( VoodooPlayAddress **ret_addr, size_t *ret_num ) { size_t num = 0; size_t i = 0; VoodooPlayAddress *addr; int ret; int fd; char *ptr, lastname[IFNAMSIZ]; struct ifreq req[16]; struct ifconf conf; D_ASSERT( ret_addr != NULL ); D_ASSERT( ret_num != NULL ); conf.ifc_buf = (char*) req; conf.ifc_len = sizeof(req); fd = socket( AF_INET, SOCK_DGRAM, 0 ); if (fd < 0) { D_PERROR( "Voodoo/Unix: socket( AF_INET, SOCK_DGRAM, 0 ) failed!\n" ); return DR_FAILURE; } ret = ioctl( fd, SIOCGIFCONF, &conf ); if (ret) { D_PERROR( "Voodoo/Player: ioctl( SIOCGIFCONF ) failed!\n" ); close( fd ); return DR_FAILURE; } lastname[0] = 0; for (ptr = conf.ifc_buf; ptr < conf.ifc_buf + conf.ifc_len; ) { struct ifreq ifrcopy, *ifr = (struct ifreq *)ptr; struct sockaddr_in *saddr = (struct sockaddr_in*) &ifr->ifr_broadaddr; #ifdef MACOS ptr += sizeof(ifr->ifr_name) + MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); // for next one in buffer #else ptr += sizeof(req[0]); #endif if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { continue; /* already processed this interface */ } memcpy(lastname, ifr->ifr_name, IFNAMSIZ); ifrcopy = *ifr; ioctl( fd, SIOCGIFFLAGS, &ifrcopy); if ((ifrcopy.ifr_flags & IFF_UP) == 0) continue; // ignore if interface not up ret = ioctl( fd, SIOCGIFBRDADDR, ifr ); if (ret) continue; if (!saddr->sin_addr.s_addr) { ret = ioctl( fd, SIOCGIFDSTADDR, ifr ); if (ret) continue; } num++; } addr = D_CALLOC( num, sizeof(VoodooPlayAddress) ); if (!addr) { close( fd ); return D_OOM(); } for (ptr = conf.ifc_buf; ptr < conf.ifc_buf + conf.ifc_len; ) { char buf[100]; struct ifreq ifrcopy, *ifr = (struct ifreq *)ptr; struct sockaddr_in *saddr = (struct sockaddr_in*) &ifr->ifr_broadaddr; #ifdef MACOS ptr += sizeof(ifr->ifr_name) + MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); // for next one in buffer #else ptr += sizeof(req[0]); #endif if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { continue; /* already processed this interface */ } memcpy(lastname, ifr->ifr_name, IFNAMSIZ); ifrcopy = *ifr; ioctl( fd, SIOCGIFFLAGS, &ifrcopy); if ((ifrcopy.ifr_flags & IFF_UP) == 0) { D_INFO( "Voodoo/Player: %-16s is not up.\n", ifrcopy.ifr_name ); continue; // ignore if interface not up } ret = ioctl( fd, SIOCGIFBRDADDR, ifr ); if (ret) { D_PERROR( "Voodoo/Player: ioctl( SIOCGIFBRDADDR ) %-16s failed!\n", ifr->ifr_name ); continue; } if (saddr->sin_addr.s_addr) { inet_ntop( AF_INET, &saddr->sin_addr, buf, sizeof(buf) ); D_INFO( "Voodoo/Player: %-16s (%s)\n", ifr->ifr_name, buf ); } else { ret = ioctl( fd, SIOCGIFDSTADDR, ifr ); if (ret) { D_PERROR( "Voodoo/Player: ioctl( SIOCGIFDSTADDR ) failed!\n" ); continue; } inet_ntop( AF_INET, &saddr->sin_addr, buf, sizeof(buf) ); D_INFO( "Voodoo/Player: %-16s (%s) (P-t-P)\n", ifr->ifr_name, buf ); } voodoo_play_from_inet_addr( &addr[i++], saddr->sin_addr.s_addr ); } close( fd ); *ret_addr = addr; *ret_num = num; return DR_OK; }