static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz) { #ifdef QT_OPENGL_ES_2 QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height())); if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height()) return rounded; #endif return sz; }
void QSGPainterNode::updateFBOSize() { int fboWidth; int fboHeight; if (m_fastFBOResizing) { fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.width())); fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.height())); } else { QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize(); fboWidth = qMax(minimumFBOSize.width(), m_size.width()); fboHeight = qMax(minimumFBOSize.height(), m_size.height()); } m_fboSize = QSize(fboWidth, fboHeight); }
static inline QSize npotAdjustedSize(const QSize &size) { static bool checked = false; static bool npotSupported = false; if (!checked) { npotSupported = QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); checked = true; } if (npotSupported) { return QSize(qMax(QT_MINIMUM_FBO_SIZE, size.width()), qMax(QT_MINIMUM_FBO_SIZE, size.height())); } return QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width())), qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height()))); }
void QTextureGlyphCache::fillInPendingGlyphs() { if (m_pendingGlyphs.isEmpty()) return; int requiredHeight = m_h; int requiredWidth = m_w; // Use a minimum size to avoid a lot of initial reallocations { QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); while (iter != m_pendingGlyphs.end()) { Coord c = iter.value(); requiredHeight = qMax(requiredHeight, c.y + c.h); requiredWidth = qMax(requiredWidth, c.x + c.w); ++iter; } } if (isNull() || requiredHeight > m_h || requiredWidth > m_w) { if (isNull()) createCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight)); else resizeCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight)); } { QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); while (iter != m_pendingGlyphs.end()) { GlyphAndSubPixelPosition key = iter.key(); fillTexture(iter.value(), key.glyph, key.subPixelPosition); ++iter; } } m_pendingGlyphs.clear(); }
bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions) { #ifdef CACHE_DEBUG printf("Populating with %d glyphs\n", numGlyphs); qDebug() << " -> current transformation: " << m_transform; #endif m_current_fontengine = fontEngine; const int margin = m_current_fontengine->glyphMargin(m_type); const int paddingDoubled = glyphPadding() * 2; bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); if (fontEngine->m_subPixelPositionCount == 0) { if (!supportsSubPixelPositions) { fontEngine->m_subPixelPositionCount = 1; } else { int i = 0; while (fontEngine->m_subPixelPositionCount == 0 && i < numGlyphs) fontEngine->m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]); } } QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates; int rowHeight = 0; QFontEngine::GlyphFormat format; switch (m_type) { case Raster_A8: format = QFontEngine::Format_A8; break; case Raster_RGBMask: format = QFontEngine::Format_A32; break; default: format = QFontEngine::Format_Mono; break; } // check each glyph for its metrics and get the required rowHeight. for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; QFixed subPixelPosition; if (supportsSubPixelPositions) { QFixed x = positions != 0 ? positions[i].x : QFixed(); subPixelPosition = fontEngine->subPixelPositionForX(x); } if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, format); #ifdef CACHE_DEBUG printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", glyph, metrics.width.toReal(), metrics.height.toReal(), metrics.xoff.toReal(), metrics.yoff.toReal(), metrics.x.toReal(), metrics.y.toReal()); #endif GlyphAndSubPixelPosition key(glyph, subPixelPosition); int glyph_width = metrics.width.ceil().toInt(); int glyph_height = metrics.height.ceil().toInt(); if (glyph_height == 0 || glyph_width == 0) { // Avoid multiple calls to boundingBox() for non-printable characters Coord c = { 0, 0, 0, 0, 0, 0 }; coords.insert(key, c); continue; } glyph_width += margin * 2 + 4; glyph_height += margin * 2 + 4; // align to 8-bit boundary if (m_type == QFontEngineGlyphCache::Raster_Mono) glyph_width = (glyph_width+7)&~7; Coord c = { 0, 0, // will be filled in later glyph_width, glyph_height, // texture coords metrics.x.truncate(), -metrics.y.truncate() }; // baseline for horizontal scripts listItemCoordinates.insert(key, c); rowHeight = qMax(rowHeight, glyph_height); } if (listItemCoordinates.isEmpty()) return true; rowHeight += margin * 2 + paddingDoubled; if (m_w == 0) { if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH) m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; else m_w = qt_next_power_of_two(fontEngine->maxCharWidth()); } // now actually use the coords and paint the wanted glyps into cache. QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = listItemCoordinates.begin(); int requiredWidth = m_w; while (iter != listItemCoordinates.end()) { Coord c = iter.value(); m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2); if (m_cx + c.w > requiredWidth) { int new_width = requiredWidth*2; while (new_width < m_cx + c.w) new_width *= 2; if (new_width <= maxTextureWidth()) { requiredWidth = new_width; } else { // no room on the current line, start new glyph strip m_cx = 0; m_cy += m_currentRowHeight + paddingDoubled; m_currentRowHeight = c.h + margin * 2; // New row } } if (maxTextureHeight() > 0 && m_cy + c.h > maxTextureHeight()) { // We can't make a cache of the required size, so we bail out return false; } c.x = m_cx; c.y = m_cy; coords.insert(iter.key(), c); m_pendingGlyphs.insert(iter.key(), c); m_cx += c.w + paddingDoubled; ++iter; } return true; }