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; }
static void manage_interlocks( CoreSurfaceAllocation *allocation, CoreSurfaceAccessorID accessor, CoreSurfaceAccessFlags access ) { int locks; locks = dfb_surface_allocation_locks( allocation ); #if 1 /* * Manage access interlocks. * * SOON FIXME: Clearing flags only when not locked yet. Otherwise nested GPU/CPU locks are a problem. */ /* Software read/write access... */ if (accessor == CSAID_CPU) { /* If hardware has written or is writing... */ if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ /* Software read access after hardware write requires flush of the (bus) read cache. */ dfb_gfxcard_flush_read_cache(); if (!locks) { /* ...clear hardware write access. */ allocation->accessed[CSAID_GPU] = (CoreSurfaceAccessFlags)(allocation->accessed[CSAID_GPU] & ~CSAF_WRITE); /* ...clear hardware read access (to avoid syncing twice). */ allocation->accessed[CSAID_GPU] = (CoreSurfaceAccessFlags)(allocation->accessed[CSAID_GPU] & ~CSAF_READ); } } /* Software write access... */ if (access & CSAF_WRITE) { /* ...if hardware has (to) read... */ if (allocation->accessed[CSAID_GPU] & CSAF_READ) { /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ /* ...clear hardware read access. */ if (!locks) allocation->accessed[CSAID_GPU] = (CoreSurfaceAccessFlags)(allocation->accessed[CSAID_GPU] & ~CSAF_READ); } } } /* Hardware read access... */ if (accessor == CSAID_GPU && access & CSAF_READ) { /* ...if software has written before... */ if (allocation->accessed[CSAID_CPU] & CSAF_WRITE) { /* ...flush texture cache. */ dfb_gfxcard_flush_texture_cache(); /* ...clear software write access. */ if (!locks) allocation->accessed[CSAID_CPU] = (CoreSurfaceAccessFlags)(allocation->accessed[CSAID_CPU] & ~CSAF_WRITE); } } if (! D_FLAGS_ARE_SET( allocation->accessed[accessor], access )) { /* FIXME: surface_enter */ } #endif /* Collect... */ allocation->accessed[accessor] = (CoreSurfaceAccessFlags)(allocation->accessed[accessor] | access); }