/** * Callback called from _mesa_HashWalk() */ static void count_tex_size(GLuint key, void *data, void *userData) { const struct gl_texture_object *texObj = (const struct gl_texture_object *) data; GLuint *total = (GLuint *) userData; *total = *total + texture_size(texObj); }
/** * Compute total size (in bytes) of all textures for the given context. * For debugging purposes. */ GLuint _mesa_total_texture_memory(struct gl_context *ctx) { GLuint tgt, total = 0; _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total); /* plus, the default texture objects */ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { total += texture_size(ctx->Shared->DefaultTex[tgt]); } return total; }
/** Render a glyph for a character into bitmap and save it into the glyph page. * \param c The character to be loaded. * \param c \ref GlyphInfo for the character. */ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) { assert(gi.glyph_index > 0); assert(gi.font_number < m_face_ttf->getTotalFaces()); FT_Face cur_face = m_face_ttf->getFace(gi.font_number); FT_GlyphSlot slot = cur_face->glyph; // Same face may be shared across the different FontWithFace, // so reset dpi each time font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()), "setting DPI"); font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index, FT_LOAD_DEFAULT), "loading a glyph"); font_manager->checkFTError(shapeOutline(&(slot->outline)), "shaping outline"); font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL), "rendering a glyph to bitmap"); // Convert to an anti-aliased bitmap FT_Bitmap* bits = &(slot->bitmap); core::dimension2du texture_size(bits->width + 1, bits->rows + 1); if ((m_used_width + texture_size.Width > getGlyphPageSize() && m_used_height + m_current_height + texture_size.Height > getGlyphPageSize()) || m_used_height + texture_size.Height > getGlyphPageSize()) { // Add a new glyph page if current one is full createNewGlyphPage(); } // Determine the linebreak location if (m_used_width + texture_size.Width > getGlyphPageSize()) { m_used_width = 0; m_used_height += m_current_height; m_current_height = 0; } const unsigned int cur_tex = m_spritebank->getTextureCount() -1; #ifndef SERVER_ONLY video::ITexture* tex = m_spritebank->getTexture(cur_tex); glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName()); assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY); if (CVS->isARBTextureSwizzleUsable()) { glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height, bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE, bits->buffer); } else { const unsigned int size = bits->width * bits->rows; uint8_t* image_data = new uint8_t[size * 4]; memset(image_data, 255, size * 4); for (unsigned int i = 0; i < size; i++) image_data[4 * i + 3] = bits->buffer[i]; glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height, bits->width, bits->rows, GL_BGRA, GL_UNSIGNED_BYTE, image_data); delete[] image_data; } if (tex->hasMipMaps()) glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); #endif // Store the rectangle of current glyph gui::SGUISpriteFrame f; gui::SGUISprite s; core::rect<s32> rectangle(m_used_width, m_used_height, m_used_width + bits->width, m_used_height + bits->rows); f.rectNumber = m_spritebank->getPositions().size(); f.textureNumber = cur_tex; // Add frame to sprite s.Frames.push_back(f); s.frameTime = 0; m_spritebank->getPositions().push_back(rectangle); m_spritebank->getSprites().push_back(s); // Save glyph metrics FontArea a; a.advance_x = cur_face->glyph->advance.x / BEARING; a.bearing_x = cur_face->glyph->metrics.horiBearingX / BEARING; const int cur_height = (cur_face->glyph->metrics.height / BEARING); const int cur_offset_y = cur_height - (cur_face->glyph->metrics.horiBearingY / BEARING); a.offset_y = m_glyph_max_height - cur_height + cur_offset_y; a.offset_y_bt = -cur_offset_y; a.spriteno = f.rectNumber; m_character_area_map[c] = a; // Store used area m_used_width += texture_size.Width; if (m_current_height < texture_size.Height) m_current_height = texture_size.Height; } // insertGlyph