/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
// #define QT_OPENGL_CACHE_AS_VBOS
#include "qopenglgradientcache_p.h"
+#include "qopengltexturecache_p.h"
#include "qopenglpaintengine_p.h"
#include <string.h> //for memcpy
#include "qopenglengineshadermanager_p.h"
#include "qopengl2pexvertexarray_p.h"
-#include "qopengltriangulatingstroker_p.h"
#include "qopengltextureglyphcache_p.h"
#include <QDebug>
QT_BEGIN_NAMESPACE
-#if defined(Q_WS_WIN)
-extern Q_GUI_EXPORT bool qt_cleartype_enabled;
-#endif
-#ifdef Q_WS_MAC
-extern bool qt_applefontsmoothing_enabled;
-#endif
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
lastTextureUsed = id;
if (smoothPixmapTransform) {
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
- glTexParameterf(target, GL_TEXTURE_WRAP_S, wrapMode);
- glTexParameterf(target, GL_TEXTURE_WRAP_T, wrapMode);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
}
QImage texImage = qt_imageForBrush(style, false);
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- //ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, QOpenGLContext::InternalBindOption);
+ QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, texImage);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- QOpenGLTexture *tex = 0;//ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA,
- // QOpenGLContext::InternalBindOption |
- // QOpenGLContext::CanFlipNativePixmapBindOption);
+ QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushPixmap);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- textureInvertedY = tex->invertedY();
+ textureInvertedY = false;
}
brushTextureDirty = false;
}
QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y());
qreal m22 = -1;
qreal dy = height;
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
m22 = 1;
dy = 0;
}
GLfloat dx = transform.dx();
GLfloat dy = transform.dy();
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
hfactor *= -1;
dy -= height;
}
d->funcs.glDisableVertexAttribArray(i);
#ifndef QT_OPENGL_ES_2
- const QSurfaceFormat &fmt = d->device->format();
+ Q_ASSERT(QOpenGLContext::currentContext());
+ const QSurfaceFormat &fmt = d->device->context()->format();
if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1)
|| fmt.profile() == QSurfaceFormat::CompatibilityProfile)
{
d->unusedIBOSToClean << c->ibo;
#else
Q_UNUSED(engine);
- qFree(c->vertices);
- qFree(c->indices);
+ free(c->vertices);
+ free(c->indices);
#endif
delete c;
}
cache->vbo = 0;
Q_ASSERT(cache->ibo == 0);
#else
- qFree(cache->vertices);
+ free(cache->vertices);
Q_ASSERT(cache->indices == 0);
#endif
updateCache = true;
glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
cache->ibo = 0;
#else
- cache->vertices = (float *) qMalloc(floatSizeInBytes);
+ cache->vertices = (float *) malloc(floatSizeInBytes);
memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes);
cache->indices = 0;
#endif
glDeleteBuffers(1, &cache->vbo);
glDeleteBuffers(1, &cache->ibo);
#else
- qFree(cache->vertices);
- qFree(cache->indices);
+ free(cache->vertices);
+ free(cache->indices);
#endif
updateCache = true;
}
vertices[i] = float(inverseScale * polys.vertices.at(i));
funcs.glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
#else
- cache->vertices = (float *) qMalloc(sizeof(float) * polys.vertices.size());
+ cache->vertices = (float *) malloc(sizeof(float) * polys.vertices.size());
if (polys.indices.type() == QVertexIndexVector::UnsignedInt) {
- cache->indices = (quint32 *) qMalloc(sizeof(quint32) * polys.indices.size());
+ cache->indices = (quint32 *) malloc(sizeof(quint32) * polys.indices.size());
memcpy(cache->indices, polys.indices.data(), sizeof(quint32) * polys.indices.size());
} else {
- cache->indices = (quint16 *) qMalloc(sizeof(quint16) * polys.indices.size());
+ cache->indices = (quint16 *) malloc(sizeof(quint16) * polys.indices.size());
memcpy(cache->indices, polys.indices.data(), sizeof(quint16) * polys.indices.size());
}
for (int i = 0; i < polys.vertices.size(); ++i)
// Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable
path.makeCacheable();
- if (!device->format().stencilBufferSize()) {
+ if (device->context()->format().stencilBufferSize() == 0) {
// If there is no stencil buffer, triangulate the path instead.
QRectF bbox = path.controlPointRect();
d->transferMode(ImageDrawingMode);
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;
-// ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions);
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
- GLfloat top = texture->invertedY() ? (pixmap.height() - src.top()) : src.top();
- GLfloat bottom = texture->invertedY() ? (pixmap.height() - src.bottom()) : src.bottom();
- QOpenGLRect srcRect(src.left(), top, src.right(), bottom);
+ QOpenGLRect srcRect(src.left(), src.top(), src.right(), src.bottom());
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlpha();
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, texture->id());
+ state()->renderHints & QPainter::SmoothPixmapTransform, id);
d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
}
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;//ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions);
- GLuint id = texture->id();
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image);
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, id);
// don't try to cache huge fonts or vastly transformed fonts
QFontEngine *fontEngine = textItem->fontEngine();
- const qreal pixelSize = fontEngine->fontDef.pixelSize;
- if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) {
+ if (shouldDrawCachedGlyphs(fontEngine, s->matrix) || det < 0.25f || det > 4.f) {
QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat)
: d->glyphCacheType;
if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
- if (d->device->alphaRequested() || s->matrix.type() > QTransform::TxTranslate
+ if (d->device->context()->format().alphaBufferSize() > 0 || s->matrix.type() > QTransform::TxTranslate
|| (s->composition_mode != QPainter::CompositionMode_Source
&& s->composition_mode != QPainter::CompositionMode_SourceOver))
{
bool drawCached = txtype < QTransform::TxProject;
// don't try to cache huge fonts or vastly transformed fonts
- const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
- if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f)
+ if (shouldDrawCachedGlyphs(ti.fontEngine, s->matrix) || det < 0.25f || det > 4.f)
drawCached = false;
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
- if (d->device->alphaRequested() || txtype > QTransform::TxTranslate
+ if (d->device->context()->format().alphaBufferSize() > 0 || txtype > QTransform::TxTranslate
|| (state()->composition_mode != QPainter::CompositionMode_Source
&& state()->composition_mode != QPainter::CompositionMode_SourceOver))
{
}
-#if defined(Q_WS_WIN)
-static bool fontSmoothingApproximately(qreal target)
-{
- extern Q_GUI_EXPORT qreal qt_fontsmoothing_gamma; // qapplication_win.cpp
- return (qAbs(qt_fontsmoothing_gamma - target) < 0.2);
-}
-#endif
// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO
void *cacheKey = ctx->shareGroup();
bool recreateVertexArrays = false;
+ QFontEngine *fe = staticTextItem->fontEngine();
QOpenGLTextureGlyphCache *cache =
- (QOpenGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(cacheKey, glyphType, QTransform());
+ (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, QTransform());
if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) {
cache = new QOpenGLTextureGlyphCache(glyphType, QTransform());
- staticTextItem->fontEngine()->setGlyphCache(cacheKey, cache);
+ fe->setGlyphCache(cacheKey, cache);
recreateVertexArrays = true;
}
// cache so this text is performed before we test if the cache size has changed.
if (recreateVertexArrays) {
cache->setPaintEnginePrivate(this);
- if (!cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+ if (!cache->populate(fe, staticTextItem->numGlyphs,
staticTextItem->glyphs, staticTextItem->glyphPositions)) {
// No space for glyphs in cache. We need to reset it and try again.
cache->clear();
- cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+ cache->populate(fe, staticTextItem->numGlyphs,
staticTextItem->glyphs, staticTextItem->glyphPositions);
}
cache->fillInPendingGlyphs();
transferMode(TextDrawingMode);
- int margin = cache->glyphMargin();
+ int margin = fe->glyphMargin(glyphType);
GLfloat dx = 1.0 / cache->width();
GLfloat dy = 1.0 / cache->height();
vertexCoordinates->clear();
textureCoordinates->clear();
- bool supportsSubPixelPositions = staticTextItem->fontEngine()->supportsSubPixelPositions();
+ bool supportsSubPixelPositions = fe->supportsSubPixelPositions();
for (int i=0; i<staticTextItem->numGlyphs; ++i) {
QFixed subPixelPosition;
if (supportsSubPixelPositions)
- subPixelPosition = cache->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
+ subPixelPosition = fe->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition);
if (cache->filterMode() != filterMode) {
if (filterMode == QOpenGLTextureGlyphCache::Linear) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
cache->setFilterMode(filterMode);
}
bool srgbFrameBufferEnabled = false;
if (funcs.hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer)) {
-#if defined(Q_WS_MAC)
- if (glyphType == QFontEngineGlyphCache::Raster_RGBMask)
-#elif defined(Q_WS_WIN)
- if (glyphType != QFontEngineGlyphCache::Raster_RGBMask || fontSmoothingApproximately(2.1))
-#else
if (false)
-#endif
{
glEnable(GL_FRAMEBUFFER_SRGB);
srgbFrameBufferEnabled = true;
}
funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;//ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
- // QOpenGLContext::InternalBindOption
- // | QOpenGLContext::CanFlipNativePixmapBindOption);
-
- if (texture->invertedY()) {
- // Flip texture y-coordinate.
- QOpenGLPoint *data = textureCoordinateArray.data();
- for (int i = 0; i < 6 * fragmentCount; ++i)
- data[i].y = 1 - data[i].y;
- }
-
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
transferMode(ImageArrayDrawingMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id());
+ q->state()->renderHints & QPainter::SmoothPixmapTransform, id);
// Setup for texture drawing
currentBrush = noBrush;
{
Q_D(QOpenGL2PaintEngineEx);
-// qDebug("QOpenGL2PaintEngineEx::begin()");
- if (pdev->devType() == QInternal::OpenGL)
- d->device = static_cast<QOpenGLPaintDevice*>(pdev);
- else
- d->device = QOpenGLPaintDevice::getDevice(pdev);
+ Q_ASSERT(pdev->devType() == QInternal::OpenGL);
+ d->device = static_cast<QOpenGLPaintDevice*>(pdev);
if (!d->device)
return false;
- if (d->device->group() != QOpenGLContextGroup::currentContextGroup()) {
- qWarning("QPainter::begin(): OpenGL resource not valid in current context");
+ if (d->device->context() != QOpenGLContext::currentContext()) {
+ qWarning("QPainter::begin(): QOpenGLPaintDevice's context needs to be current");
return false;
}
d->ctx = QOpenGLContext::currentContext();
d->ctx->d_func()->active_engine = this;
- d->funcs.initializeGLFunctions();
+ d->funcs.initializeOpenGLFunctions();
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
d->vertexAttributeArraysEnabledState[i] = false;
d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
d->stencilClean = true;
- // Calling begin paint should make the correct context current. So, any
- // code which calls into GL or otherwise needs a current context *must*
- // go after beginPaint:
- d->device->beginPaint();
d->shaderManager = new QOpenGLEngineShaderManager(d->ctx);
glDisable(GL_STENCIL_TEST);
d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
#if !defined(QT_OPENGL_ES_2)
-#if defined(Q_WS_WIN)
- if (qt_cleartype_enabled
- && (fontSmoothingApproximately(1.0) || fontSmoothingApproximately(2.1)))
-#endif
-#if defined(Q_WS_MAC)
- if (qt_applefontsmoothing_enabled)
-#endif
d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
#endif
#if defined(QT_OPENGL_ES_2)
// OpenGL ES can't switch MSAA off, so if the gl paint device is
// multisampled, it's always multisampled.
- d->multisamplingAlwaysEnabled = d->device->format().samples() > 1;
+ d->multisamplingAlwaysEnabled = d->device->context()->format().samples() > 1;
#else
d->multisamplingAlwaysEnabled = false;
#endif
QOpenGLContext *ctx = d->ctx;
d->funcs.glUseProgram(0);
d->transferMode(BrushDrawingMode);
- d->device->endPaint();
ctx->d_func()->active_engine = 0;
d->needsSync = true;
}
- d->device->ensureActiveTarget();
-
if (d->needsSync) {
d->transferMode(BrushDrawingMode);
glViewport(0, 0, d->width, d->height);
const int left = rect.left();
const int width = rect.width();
int bottom = height - (rect.top() + rect.height());
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
bottom = rect.top();
}
const int height = rect.height();