summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp6
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h5
-rw-r--r--src/opengl/gl2paintengineex/qglshader.cpp16
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp271
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h1
-rw-r--r--src/opengl/opengl.pro12
-rw-r--r--src/opengl/qgl.cpp187
-rw-r--r--src/opengl/qgl_p.h40
-rw-r--r--src/opengl/qglextensions.cpp24
-rw-r--r--src/opengl/qglextensions_p.h148
-rw-r--r--src/opengl/qglframebufferobject.cpp468
-rw-r--r--src/opengl/qglframebufferobject.h49
-rw-r--r--src/opengl/qglpixelbuffer.cpp10
-rw-r--r--src/opengl/qglpixmapfilter.cpp20
-rw-r--r--src/opengl/qpaintengine_opengl.cpp176
-rw-r--r--src/opengl/qpixmapdata_gl.cpp13
-rw-r--r--src/opengl/qpixmapdata_gl_p.h1
-rw-r--r--src/opengl/qwindowsurface_gl.cpp71
-rw-r--r--src/opengl/qwindowsurface_gl_p.h1
20 files changed, 1136 insertions, 384 deletions
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
index 0352d39..f237847 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
+++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
@@ -59,6 +59,12 @@ QGLRect QGL2PEXVertexArray::boundingRect() const
return QGLRect(minX, minY, maxX, maxY);
}
+void QGL2PEXVertexArray::addRect(const QRectF &rect)
+{
+ vertexArray << rect.topLeft() << rect.topRight() << rect.bottomRight()
+ << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
+}
+
void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale)
{
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
index c205022..a83f13e 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
@@ -62,7 +62,7 @@ public:
QGLPoint(GLfloat new_x, GLfloat new_y) :
x(new_x), y(new_y) {};
- QGLPoint(QPointF p) :
+ QGLPoint(const QPointF &p) :
x(p.x()), y(p.y()) {};
QGLPoint(const QPointF* p) :
@@ -77,7 +77,7 @@ public:
struct QGLRect
{
- QGLRect(QRectF r)
+ QGLRect(const QRectF &r)
: left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
QGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
@@ -98,6 +98,7 @@ public:
maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
boundingRectDirty(true) {}
+ void addRect(const QRectF &rect);
void addPath(const QVectorPath &path, GLfloat curveInverseScale);
void clear();
diff --git a/src/opengl/gl2paintengineex/qglshader.cpp b/src/opengl/gl2paintengineex/qglshader.cpp
index 634be84..4ac6e61 100644
--- a/src/opengl/gl2paintengineex/qglshader.cpp
+++ b/src/opengl/gl2paintengineex/qglshader.cpp
@@ -49,7 +49,11 @@
return false; \
ctx->makeCurrent(); \
-
+#if !defined(QT_OPENGL_ES_2)
+static const char *qglslDefines = "#define lowp\n#define mediump\n#define highp\n";
+#else
+static const char *qglslDefines = "";
+#endif
class QGLShaderPrivate
@@ -131,9 +135,13 @@ bool QGLShader::compile()
return false;
const QByteArray src_ba = d->source.toAscii();
- const char* src = src_ba.constData();
+ const char* src[2];
+ src[0] = qglslDefines;
+ src[1] = src_ba.constData();
+
- glShaderSource(d->shaderId, 1, &src, 0);
+ QGLContext *ctx = d->ctx;
+ glShaderSource(d->shaderId, 2, src, 0);
glCompileShader(d->shaderId);
@@ -160,6 +168,7 @@ QString QGLShader::log()
GLint logSize;
GLint logLength;
+ QGLContext *ctx = d->ctx;
glGetShaderiv(d->shaderId, GL_INFO_LOG_LENGTH, &logSize);
if (!logSize)
@@ -377,6 +386,7 @@ void QGLShaderProgram::use()
if (!d->valid)
return;
+ QGLContext *ctx = d->ctx;
glUseProgram(d->programId);
}
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
index 1625b84..4cbf3f6 100644
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ b/src/opengl/gl2paintengineex/qglshader_p.h
@@ -81,6 +81,7 @@ SAMPLER_2D_SHADOW.
#include <QtOpenGL>
+#include <private/qgl_p.h>
typedef struct {
GLfloat a;
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index a74f044..89ed1f7 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -86,6 +86,11 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
#include <QDebug>
+enum EngineMode {
+ ImageDrawingMode,
+ TextDrawingMode,
+ DefaultMode
+};
static const GLuint QT_VERTEX_COORDS_ATTR = 0;
static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
@@ -114,7 +119,10 @@ public:
void setBrush(const QBrush* brush);
- void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight);
+ void transferMode(EngineMode newMode);
+
+ void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize);
+ void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
void fill(const QVectorPath &path);
void drawOutline(const QVectorPath& path);
@@ -133,10 +141,11 @@ public:
inline QColor premultiplyColor(QColor c, GLfloat opacity);
QGL2PaintEngineEx* q;
-
- //### Move into QGLDrawable
+ QGLDrawable drawable;
int width, height;
- QGLContext* ctx;
+ QGLContext *ctx;
+
+ EngineMode mode;
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
@@ -153,7 +162,11 @@ public:
GLfloat inverseScale;
- QGL2PEXVertexArray pathVertexArray;
+ QGL2PEXVertexArray vertexCoordinateArray;
+ QGL2PEXVertexArray textureCoordinateArray;
+
+ GLfloat staticVertexCoordinateArray[8];
+ GLfloat staticTextureCoordinateArray[8];
GLfloat pmvMatrix[4][4];
@@ -400,8 +413,8 @@ void QGL2PaintEngineExPrivate::updateMatrix()
// Use the (3x3) transform for the Model~View matrix:
const QTransform& transform = q->state()->matrix;
GLfloat MV[4][4] = {
- {transform.m11(), transform.m21(), 0.0, transform.dx() + 0.5},
- {transform.m12(), transform.m22(), 0.0, transform.dy() + 0.5},
+ {transform.m11(), transform.m21(), 0.0, transform.dx()},
+ {transform.m12(), transform.m22(), 0.0, transform.dy()},
{0.0, 0.0, 1.0, 0.0},
{transform.m13(), transform.m23(), 0.0, transform.m33()}
};
@@ -411,7 +424,9 @@ void QGL2PaintEngineExPrivate::updateMatrix()
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
pmvMatrix[col][row] = 0.0;
- for (int n = 0; n < 4; ++n)
+
+ // P[row][n] is 0.0 for n < row
+ for (int n = row; n < 4; ++n)
pmvMatrix[col][row] += P[row][n] * MV[n][col];
}
}
@@ -485,15 +500,22 @@ void QGL2PaintEngineExPrivate::updateCompositionMode()
compositionModeDirty = false;
}
+static inline void setCoords(GLfloat *coords, const QGLRect &rect)
+{
+ coords[0] = rect.left;
+ coords[1] = rect.top;
+ coords[2] = rect.right;
+ coords[3] = rect.top;
+ coords[4] = rect.right;
+ coords[5] = rect.bottom;
+ coords[6] = rect.left;
+ coords[7] = rect.bottom;
+}
-void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight)
+void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize)
{
// qDebug("QGL2PaintEngineExPrivate::drawImage()");
-
- // We have a shader specifically for drawPixmap/drawImage...
- shaderManager->imageShader()->use();
-
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
if (compositionModeDirty)
updateCompositionMode();
@@ -506,66 +528,89 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s
imageShaderMatrixUniformDirty = false;
}
- shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
-
-// if (q->state()->opacity < 0.99f)
+ if (q->state()->opacity < 0.99f)
shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)q->state()->opacity;
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
+ GLfloat dx = 1.0 / textureSize.width();
+ GLfloat dy = 1.0 / textureSize.height();
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
+ QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
- GLfloat dx = 1.0 / txtWidth;
- GLfloat dy = 1.0 / txtHeight;
+ setCoords(staticVertexCoordinateArray, dest);
+ setCoords(staticTextureCoordinateArray, srcTextureRect);
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
- };
+void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
+{
+ if (newMode == mode)
+ return;
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ if (mode == TextDrawingMode || mode == ImageDrawingMode) {
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ }
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ if (newMode == TextDrawingMode) {
+ glEnable(GL_BLEND);
+ glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
-}
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+
+ shaderManager->textShader()->use();
+ shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
+ }
+
+ if (newMode == ImageDrawingMode) {
+ // We have a shader specifically for drawPixmap/drawImage...
+ shaderManager->imageShader()->use();
+ shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
+ shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)1.0;
+
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticVertexCoordinateArray);
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
+ glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ }
+
+ mode = newMode;
+}
void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
{
+ transferMode(DefaultMode);
+
// qDebug("QGL2PaintEngineExPrivate::drawOutline()");
if (matrixDirty)
updateMatrix();
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
if (path.hasImplicitClose()) {
// Close the path's outline
- pathVertexArray.lineToArray(path.points()[0], path.points()[1]);
- pathVertexArray.stops().last() += 1;
+ vertexCoordinateArray.lineToArray(path.points()[0], path.points()[1]);
+ vertexCoordinateArray.stops().last() += 1;
}
prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_LINE_STRIP);
+ drawVertexArrays(vertexCoordinateArray, GL_LINE_STRIP);
}
// Assumes everything is configured for the brush you want to use
void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
+ transferMode(DefaultMode);
+
if (matrixDirty)
updateMatrix();
@@ -579,26 +624,26 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
composite(rect);
}
else if (path.shape() == QVectorPath::EllipseHint) {
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_TRIANGLE_FAN);
+ drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
}
else {
// The path is too complicated & needs the stencil technique
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
- fillStencilWithVertexArray(pathVertexArray, path.hasWindingFill());
+ fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
// Stencil the brush onto the dest buffer
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
glEnable(GL_STENCIL_TEST);
prepareForDraw();
- composite(pathVertexArray.boundingRect());
+ composite(vertexCoordinateArray.boundingRect());
glDisable(GL_STENCIL_TEST);
- cleanStencilBuffer(pathVertexArray.boundingRect());
+ cleanStencilBuffer(vertexCoordinateArray.boundingRect());
}
}
@@ -749,8 +794,6 @@ void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray,
QGL2PaintEngineEx::QGL2PaintEngineEx()
: QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
{
- qDebug("QGL2PaintEngineEx::QGL2PaintEngineEx()");
-
}
QGL2PaintEngineEx::~QGL2PaintEngineEx()
@@ -761,8 +804,6 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QGL2PaintEngineEx);
- QTime startTime = QTime::currentTime();
-
d->setBrush(&brush);
d->fill(path);
d->setBrush(&(state()->brush)); // reset back to the state's brush
@@ -845,9 +886,10 @@ void QGL2PaintEngineEx::transformChanged()
void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ d->transferMode(ImageDrawingMode);
- d->ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLContext *ctx = d->ctx;
+ ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
//FIXME: we should use hasAlpha() instead, but that's SLOW at the moment
if ((state()->opacity < 0.99f) || pixmap.hasAlphaChannel())
@@ -855,26 +897,29 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
else
glDisable(GL_BLEND);
- d->drawTexture(dest, src, pixmap.width(), pixmap.height());
+ d->drawTexture(dest, src, pixmap.size());
}
void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
Qt::ImageConversionFlags)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ d->transferMode(ImageDrawingMode);
+
+ QGLContext *ctx = d->ctx;
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
if ((state()->opacity < 0.99f) || image.hasAlphaChannel())
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
- d->drawTexture(dest, src, image.width(), image.height());
+ d->drawTexture(dest, src, image.size());
}
void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
+ Q_D(QGL2PaintEngineEx);
QOpenGLPaintEngineState *s = state();
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
@@ -892,17 +937,19 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
drawCached = false;
if (drawCached) {
- drawCachedGlyphs(p, ti);
+ d->drawCachedGlyphs(p, ti);
return;
}
QPaintEngineEx::drawTextItem(p, ti);
}
-void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
+void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
{
- Q_D(QGL2PaintEngineEx);
- QOpenGLPaintEngineState *s = state();
+ Q_Q(QGL2PaintEngineEx);
+ QOpenGLPaintEngineState *s = q->state();
+
+ transferMode(TextDrawingMode);
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
@@ -926,66 +973,48 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t
const QImage &image = cache->image();
int margin = cache->glyphMargin();
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
-
- glEnable(GL_BLEND);
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
- d->shaderManager->textShader()->use();
- d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
- if (d->compositionModeDirty)
- d->updateCompositionMode();
+ if (compositionModeDirty)
+ updateCompositionMode();
- if (d->matrixDirty)
- d->updateMatrix();
+ if (matrixDirty)
+ updateMatrix();
- if (d->textShaderMatrixUniformDirty) {
- d->shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = d->pmvMatrix;
- d->textShaderMatrixUniformDirty = false;
+ if (textShaderMatrixUniformDirty) {
+ shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
+ textShaderMatrixUniformDirty = false;
}
- d->shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
- QColor col = d->premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
- d->shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
+ QColor col = premultiplyColor(s->pen.color(), (GLfloat)s->opacity);
+ shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
GLfloat dx = 1.0 / image.width();
GLfloat dy = 1.0 / image.height();
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ QGLPoint *oldVertexCoordinateDataPtr = vertexCoordinateArray.data();
+ QGLPoint *oldTextureCoordinateDataPtr = textureCoordinateArray.data();
+
+ vertexCoordinateArray.clear();
+ textureCoordinateArray.clear();
+
for (int i=0; i<glyphs.size(); ++i) {
const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
int x = positions[i].x.toInt() + c.baseLineX - margin;
int y = positions[i].y.toInt() - c.baseLineY - margin;
- QGLRect dest = QRectF(x, y, c.w, c.h);
- QGLRect src = QRectF(c.x, c.y, c.w, c.h);
-
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
-
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
-
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
-
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
- };
+ vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
+ textureCoordinateArray.addRect(QRectF(c.x*dx, 1 - c.y*dy, c.w * dx, -c.h * dy));
+ }
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
}
bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
@@ -994,11 +1023,16 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
// qDebug("QGL2PaintEngineEx::begin()");
- QGLWidget* widget = static_cast<QGLWidget*>(pdev);
- d->ctx = const_cast<QGLContext*>(widget->context());
- d->ctx->makeCurrent();
- d->width = widget->width();
- d->height = widget->height();
+ d->drawable.setDevice(pdev);
+ d->drawable.makeCurrent();
+ d->ctx = d->drawable.context();
+ QSize sz = d->drawable.size();
+ d->width = sz.width();
+ d->height = sz.height();
+ d->mode = DefaultMode;
+
+ qt_resolve_version_1_3_functions(d->ctx);
+ qt_resolve_glsl_extensions(d->ctx);
if (!d->shaderManager)
d->shaderManager = new QGLPEXShaderManager(d->ctx);
@@ -1021,13 +1055,18 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
glDisable(GL_DEPTH_TEST);
+ updateClipRegion(QRegion(), Qt::NoClip);
return true;
}
bool QGL2PaintEngineEx::end()
{
Q_D(QGL2PaintEngineEx);
- d->ctx->swapBuffers();
+ QGLContext *ctx = d->ctx;
+ glUseProgram(0);
+ d->transferMode(DefaultMode);
+ d->drawable.swapBuffers();
+ d->drawable.doneCurrent();
return false;
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index ce66e4b..9f84a25 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -100,7 +100,6 @@ public:
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
- void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
Type type() const { return OpenGL; }
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 48d7caf..af16312 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -34,12 +34,12 @@ SOURCES += qgl.cpp \
qglextensions.cpp \
qglpixmapfilter.cpp
-!contains(QT_CONFIG, opengles2) {
- HEADERS += qpaintengine_opengl_p.h
- SOURCES += qpaintengine_opengl.cpp
-}
+#!contains(QT_CONFIG, opengles2) {
+# HEADERS += qpaintengine_opengl_p.h
+# SOURCES += qpaintengine_opengl.cpp
+#}
-contains(QT_CONFIG, opengles2) {
+#contains(QT_CONFIG, opengles2) {
SOURCES += gl2paintengineex/qglgradientcache.cpp \
gl2paintengineex/qglpexshadermanager.cpp \
gl2paintengineex/qglshader.cpp \
@@ -51,7 +51,7 @@ contains(QT_CONFIG, opengles2) {
gl2paintengineex/qglshader_p.h \
gl2paintengineex/qgl2pexvertexarray_p.h \
gl2paintengineex/qpaintengineex_opengl2_p.h
-}
+#}
x11 {
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 4c152e2..fc11d90 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -65,15 +65,20 @@
#include "qimage.h"
#include "qgl_p.h"
-#if defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
#else
#include <private/qpaintengine_opengl_p.h>
#endif
+#include <qglpixelbuffer.h>
+#include <qglframebufferobject.h>
+
#include <private/qimage_p.h>
#include <private/qpixmapdata_p.h>
#include <private/qpixmapdata_gl_p.h>
+#include <private/qglpixelbuffer_p.h>
+#include <private/qwindowsurface_gl_p.h>
#include "qcolormap.h"
#include "qcache.h"
#include "qfile.h"
@@ -1883,14 +1888,14 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint
/*! \internal */
GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean)
{
-#if !defined(QT_OPENGL_ES_2)
- if (target == qt_gl_preferredTextureTarget() && pixmap.pixmapData()->classId() == QPixmapData::OpenGLClass) {
- const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pixmap.pixmapData());
+ Q_Q(QGLContext);
+ QPixmapData *pd = pixmap.pixmapData();
+ if (target == qt_gl_preferredTextureTarget() && pd->classId() == QPixmapData::OpenGLClass) {
+ const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
- if (data->isValidContext(QGLContext::currentContext()))
+ if (data->isValidContext(q))
return data->bind();
}
-#endif
const qint64 key = pixmap.cacheKey();
GLuint id;
@@ -2041,7 +2046,24 @@ void QGLContext::deleteTexture(QMacCompatGLuint id)
// qpaintengine_opengl.cpp
#if !defined(QT_OPENGL_ES_2)
-extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
+//extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
+void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
+{
+ qreal left = r.left();
+ qreal right = r.right();
+ qreal top = r.top();
+ qreal bottom = r.bottom();
+
+ array[0] = f2vt(left);
+ array[1] = f2vt(top);
+ array[2] = f2vt(right);
+ array[3] = f2vt(top);
+ array[4] = f2vt(right);
+ array[5] = f2vt(bottom);
+ array[6] = f2vt(left);
+ array[7] = f2vt(bottom);
+}
+
#else
void qt_add_rect_to_array(const QRectF &r, q_vertexType *array) {};
#endif
@@ -4039,14 +4061,14 @@ void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QM
}
#endif
-#if defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_engine)
#else
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
#endif
#ifdef Q_WS_QWS
-Q_OPENGL_EXPORT QOpenGLPaintEngine* qt_qgl_paint_engine()
+Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
{
#if !defined(QT_OPENGL_ES_2)
return qt_gl_engine();
@@ -4153,6 +4175,8 @@ void QGLExtensions::init_extensions()
glExtensions |= FramebufferObject;
glExtensions |= GenerateMipmap;
#endif
+ if (extensions.contains(QLatin1String("EXT_framebuffer_blit")))
+ glExtensions |= FramebufferBlit;
QGLContext cx(QGLFormat::defaultFormat());
if (glExtensions & TextureCompression) {
@@ -4202,4 +4226,149 @@ Q_OPENGL_EXPORT const QString qt_gl_library_name()
}
#endif
+void QGLDrawable::setDevice(QPaintDevice *pdev)
+{
+ wasBound = false;
+ widget = 0;
+ buffer = 0;
+ fbo = 0;
+#ifdef Q_WS_QWS
+ wsurf = 0;
+#endif
+ if (pdev->devType() == QInternal::Widget)
+ widget = static_cast<QGLWidget *>(pdev);
+ else if (pdev->devType() == QInternal::Pbuffer)
+ buffer = static_cast<QGLPixelBuffer *>(pdev);
+ else if (pdev->devType() == QInternal::FramebufferObject)
+ fbo = static_cast<QGLFramebufferObject *>(pdev);
+ else if (pdev->devType() == QInternal::UnknownDevice)
+#ifdef Q_WS_QWS
+ wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
+#else
+ wsurf = static_cast<QGLWindowSurface *>(pdev);
+#endif
+}
+
+void QGLDrawable::swapBuffers()
+{
+ if (widget) {
+ if (widget->autoBufferSwap())
+ widget->swapBuffers();
+ } else {
+ glFlush();
+ }
+}
+
+void QGLDrawable::makeCurrent()
+{
+ if (widget)
+ widget->makeCurrent();
+ else if (buffer)
+ buffer->makeCurrent();
+ else if (wsurf)
+ wsurf->context()->makeCurrent();
+ else if (fbo) {
+ wasBound = fbo->isBound();
+ if (!wasBound)
+ fbo->bind();
+ }
+}
+
+void QGLDrawable::doneCurrent()
+{
+ if (fbo && !wasBound)
+ fbo->release();
+}
+
+QSize QGLDrawable::size() const
+{
+ if (widget) {
+ return QSize(widget->d_func()->glcx->device()->width(),
+ widget->d_func()->glcx->device()->height());
+ } else if (buffer) {
+ return buffer->size();
+ } else if (fbo) {
+ return fbo->size();
+ } else if (wsurf) {
+#ifdef Q_WS_QWS
+ return wsurf->window()->frameSize();
+#else
+ return QSize(wsurf->width(), wsurf->height());
+#endif
+ }
+ return QSize();
+}
+
+QGLFormat QGLDrawable::format() const
+{
+ if (widget)
+ return widget->format();
+ else if (buffer)
+ return buffer->format();
+ else if (wsurf)
+ return wsurf->context()->format();
+ else if (fbo && QGLContext::currentContext()) {
+ QGLFormat fmt = QGLContext::currentContext()->format();
+ fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
+ fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
+ return fmt;
+ }
+
+ return QGLFormat();
+}
+
+GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
+{
+ if (widget)
+ return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
+ else if (buffer)
+ return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
+ else if (fbo && QGLContext::currentContext())
+ return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
+ else if (wsurf)
+ return wsurf->context()->d_func()->bindTexture(image, target, format, true);
+ return 0;
+}
+
+GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
+{
+ if (widget)
+ return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
+ else if (buffer)
+ return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
+ else if (fbo && QGLContext::currentContext())
+ return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
+ else if (wsurf)
+ return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
+ return 0;
+}
+
+QColor QGLDrawable::backgroundColor() const
+{
+ if (widget)
+ return widget->palette().brush(widget->backgroundRole()).color();
+ return QApplication::palette().brush(QPalette::Background).color();
+}
+
+QGLContext *QGLDrawable::context() const
+{
+ if (widget)
+ return widget->d_func()->glcx;
+ else if (buffer)
+ return buffer->d_func()->qctx;
+ else if (fbo)
+ return const_cast<QGLContext *>(QGLContext::currentContext());
+ else if (wsurf)
+ return wsurf->context();
+ return 0;
+}
+
+bool QGLDrawable::autoFillBackground() const
+{
+ if (widget)
+ return widget->autoFillBackground();
+ else
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index b15eebc..8ab73d8 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -282,6 +282,39 @@ Q_SIGNALS:
void aboutToDestroyContext(const QGLContext *context);
};
+class QGLPixelBuffer;
+class QGLFramebufferObject;
+class QWSGLWindowSurface;
+class QGLWindowSurface;
+class QGLDrawable {
+public:
+ QGLDrawable() : widget(0), buffer(0), fbo(0)
+ , wsurf(0)
+ {}
+ void setDevice(QPaintDevice *pdev);
+ void swapBuffers();
+ void makeCurrent();
+ void doneCurrent();
+ QSize size() const;
+ QGLFormat format() const;
+ GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
+ GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
+ QColor backgroundColor() const;
+ QGLContext *context() const;
+ bool autoFillBackground() const;
+
+private:
+ bool wasBound;
+ QGLWidget *widget;
+ QGLPixelBuffer *buffer;
+ QGLFramebufferObject *fbo;
+#ifdef Q_WS_QWS
+ QWSGLWindowSurface *wsurf;
+#else
+ QGLWindowSurface *wsurf;
+#endif
+};
+
// GL extension definitions
class QGLExtensions {
public:
@@ -297,7 +330,8 @@ public:
StencilWrap = 0x00000100,
PackedDepthStencil = 0x00000200,
NVFloatBuffer = 0x00000400,
- PixelBufferObject = 0x00000800
+ PixelBufferObject = 0x00000800,
+ FramebufferBlit = 0x00001000
};
Q_DECLARE_FLAGS(Extensions, Extension)
@@ -385,9 +419,13 @@ inline GLenum qt_gl_preferredTextureFormat()
inline GLenum qt_gl_preferredTextureTarget()
{
+#if 1 || defined(QT_OPENGL_ES_2)
+ return GL_TEXTURE_2D;
+#else
return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
? GL_TEXTURE_RECTANGLE_NV
: GL_TEXTURE_2D;
+#endif
}
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8357cf9..e6ac043 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -74,6 +74,9 @@ bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
glGetFramebufferAttachmentParameterivEXT =
(_glGetFramebufferAttachmentParameterivEXT) ctx->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT"));
glGenerateMipmapEXT = (_glGenerateMipmapEXT) ctx->getProcAddress(QLatin1String("glGenerateMipmapEXT"));
+ glBlitFramebufferEXT = (_glBlitFramebufferEXT) ctx->getProcAddress(QLatin1String("glBlitFramebufferEXT"));
+ glRenderbufferStorageMultisampleEXT =
+ (_glRenderbufferStorageMultisampleEXT) ctx->getProcAddress(QLatin1String("glRenderbufferStorageMultisampleEXT"));
return glIsRenderbufferEXT;
#else
Q_UNUSED(ctx);
@@ -176,10 +179,29 @@ bool qt_resolve_glsl_extensions(QGLContext *ctx)
glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
+ glGetActiveAttrib = (_glGetActiveAttrib) ctx->getProcAddress(QLatin1String("glGetActiveAttrib"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
+ glGetActiveUniform = (_glGetActiveUniform) ctx->getProcAddress(QLatin1String("glGetActiveUniform"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
+ glUniform1f = (_glUniform1f) ctx->getProcAddress(QLatin1String("glUniform1f"));
+ glUniform2f = (_glUniform2f) ctx->getProcAddress(QLatin1String("glUniform2f"));
+ glUniform4f = (_glUniform4f) ctx->getProcAddress(QLatin1String("glUniform4f"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
+ glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate"));
+
return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
+ glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv &&
+ glGetActiveAttrib && glGetAttribLocation && glGetActiveUniform && glGetProgramInfoLog &&
+ glUniform1f && glUniform2f && glUniform4f &&
+ glUniformMatrix2fv && glUniformMatrix3fv && glUniformMatrix4fv &&
+ glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glStencilOpSeparate;
}
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index a0517f5..cd35eb0 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -74,6 +74,10 @@
typedef ptrdiff_t GLsizeiptrARB;
#endif
+#ifndef GL_VERSION_2_0
+typedef char GLchar;
+#endif
+
// ARB_pixel_buffer_object
typedef void (APIENTRY *_glBindBufferARB) (GLenum, GLuint);
typedef void (APIENTRY *_glDeleteBuffersARB) (GLsizei, const GLuint *);
@@ -107,10 +111,10 @@ typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
+typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
@@ -118,6 +122,22 @@ typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
typedef void (APIENTRY *_glMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY *_glActiveTexture) (GLenum);
+typedef void (APIENTRY *_glGetActiveAttrib) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint program, const GLchar* name);
+typedef void (APIENTRY *_glGetActiveUniform) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
+typedef void (APIENTRY *_glUniform1f) (GLint location, GLfloat v0);
+typedef void (APIENTRY *_glUniform2f) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRY *_glUniform4f) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRY *_glUniformMatrix2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (APIENTRY *_glUniformMatrix3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (APIENTRY *_glUniformMatrix4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glVertexAttribPointer) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
+typedef void (APIENTRY *_glStencilOpSeparate) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+
+
// EXT_GL_framebuffer_object
typedef GLboolean (APIENTRY *_glIsRenderbufferEXT) (GLuint renderbuffer);
typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum target, GLuint renderbuffer);
@@ -142,6 +162,15 @@ typedef void (APIENTRY *_glGetFramebufferAttachmentParameterivEXT) (GLenum targe
GLint *params);
typedef void (APIENTRY *_glGenerateMipmapEXT) (GLenum target);
+// EXT_GL_framebuffer_blit
+typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1, int srcY1,
+ int dstX0, int dstY0, int dstX1, int dstY1,
+ GLbitfield mask, GLenum filter);
+
+// EXT_GL_framebuffer_multisample
+typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+
QT_BEGIN_NAMESPACE
struct QGLExtensionFuncs
@@ -200,6 +229,8 @@ struct QGLExtensionFuncs
qt_glGetFramebufferAttachmentParameterivEXT = 0;
qt_glGenerateMipmapEXT = 0;
#endif
+ qt_glBlitFramebufferEXT = 0;
+ qt_glRenderbufferStorageMultisampleEXT = 0;
qt_glBindBufferARB = 0;
qt_glDeleteBuffersARB = 0;
@@ -207,6 +238,21 @@ struct QGLExtensionFuncs
qt_glBufferDataARB = 0;
qt_glMapBufferARB = 0;
qt_glUnmapBufferARB = 0;
+
+ qt_glGetActiveAttrib = 0;
+ qt_glGetAttribLocation = 0;
+ qt_glGetActiveUniform = 0;
+ qt_glGetProgramInfoLog = 0;
+ qt_glUniform1f = 0;
+ qt_glUniform2f = 0;
+ qt_glUniform4f = 0;
+ qt_glUniformMatrix2fv = 0;
+ qt_glUniformMatrix3fv = 0;
+ qt_glUniformMatrix4fv = 0;
+ qt_glEnableVertexAttribArray = 0;
+ qt_glDisableVertexAttribArray = 0;
+ qt_glVertexAttribPointer = 0;
+ qt_glStencilOpSeparate = 0;
}
_glProgramStringARB qt_glProgramStringARB;
@@ -263,6 +309,8 @@ struct QGLExtensionFuncs
_glGetFramebufferAttachmentParameterivEXT qt_glGetFramebufferAttachmentParameterivEXT;
_glGenerateMipmapEXT qt_glGenerateMipmapEXT;
#endif
+ _glBlitFramebufferEXT qt_glBlitFramebufferEXT;
+ _glRenderbufferStorageMultisampleEXT qt_glRenderbufferStorageMultisampleEXT;
_glBindBufferARB qt_glBindBufferARB;
_glDeleteBuffersARB qt_glDeleteBuffersARB;
@@ -270,6 +318,21 @@ struct QGLExtensionFuncs
_glBufferDataARB qt_glBufferDataARB;
_glMapBufferARB qt_glMapBufferARB;
_glUnmapBufferARB qt_glUnmapBufferARB;
+
+ _glGetActiveAttrib qt_glGetActiveAttrib;
+ _glGetAttribLocation qt_glGetAttribLocation;
+ _glGetActiveUniform qt_glGetActiveUniform;
+ _glGetProgramInfoLog qt_glGetProgramInfoLog;
+ _glUniform1f qt_glUniform1f;
+ _glUniform2f qt_glUniform2f;
+ _glUniform4f qt_glUniform4f;
+ _glUniformMatrix2fv qt_glUniformMatrix2fv;
+ _glUniformMatrix3fv qt_glUniformMatrix3fv;
+ _glUniformMatrix4fv qt_glUniformMatrix4fv;
+ _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
+ _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
+ _glVertexAttribPointer qt_glVertexAttribPointer;
+ _glStencilOpSeparate qt_glStencilOpSeparate;
};
@@ -397,6 +460,28 @@ struct QGLExtensionFuncs
#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
#endif
+// GL_EXT_framebuffer_blit
+#ifndef GL_READ_FRAMEBUFFER_EXT
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#endif
+
+// GL_EXT_framebuffer_multisample
+#ifndef GL_RENDERBUFFER_SAMPLES_EXT
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#endif
+
+#ifndef GL_MAX_SAMPLES_EXT
+#define GL_MAX_SAMPLES_EXT 0x8D5
+#endif
+
+#ifndef GL_DRAW_FRAMEBUFFER_EXT
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#endif
+
#ifndef GL_EXT_packed_depth_stencil
#define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
@@ -416,6 +501,40 @@ struct QGLExtensionFuncs
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
#endif
+#ifndef GL_VERSION_1_4
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+
#define glProgramStringARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramStringARB
#define glBindProgramARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindProgramARB
#define glDeleteProgramsARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgramsARB
@@ -449,6 +568,8 @@ struct QGLExtensionFuncs
#define glFramebufferRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferRenderbufferEXT
#define glGetFramebufferAttachmentParameterivEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetFramebufferAttachmentParameterivEXT
#define glGenerateMipmapEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenerateMipmapEXT
+#define glBlitFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBlitFramebufferEXT
+#define glRenderbufferStorageMultisampleEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glRenderbufferStorageMultisampleEXT
#else // QT_OPENGL_ES_2
@@ -502,6 +623,25 @@ struct QGLExtensionFuncs
#define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
+#define glGetActiveAttrib QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetActiveAttrib
+#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
+#define glGetActiveUniform QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetActiveUniform
+#define glGetProgramInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramInfoLog
+#define glUniform1f QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1f
+#define glUniform2f QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2f
+#define glUniform4f QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4f
+#define glUniformMatrix2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2fv
+#define glUniformMatrix3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3fv
+#define glUniformMatrix4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4fv
+#define glEnableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glEnableVertexAttribArray
+#define glDisableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDisableVertexAttribArray
+#define glVertexAttribPointer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttribPointer
+#define glStencilOpSeparate QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glStencilOpSeparate
+
+#if !defined(QT_OPENGL_ES_2)
+#define glClearDepthf(x) glClearDepth(GLdouble(x))
+#endif
+
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 8524dfa..45d4788 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -43,7 +43,11 @@
#include <qdebug.h>
#include <private/qgl_p.h>
+#if 1 || defined(QT_OPENGL_ES_2)
+#include <private/qpaintengineex_opengl2_p.h>
+#else
#include <private/qpaintengine_opengl_p.h>
+#endif
#include <qglframebufferobject.h>
#include <qlibrary.h>
#include <qimage.h>
@@ -63,6 +67,216 @@ extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
} \
}
+class QGLFramebufferObjectFormatPrivate
+{
+public:
+ int samples;
+ QGLFramebufferObject::Attachment attachment;
+ GLenum target;
+ GLenum internal_format;
+};
+
+/*!
+ \class QGLFramebufferObjectFormat
+ \brief The QGLFramebufferObjectFormat class specifies the format of an OpenGL
+ framebuffer object.
+
+ \since 4.6
+
+ \ingroup multimedia
+
+ A framebuffer object has several characteristics:
+ \list
+ \i \link setSamples() Number of samples per pixels.\endlink
+ \i \link setAttachment() Depth and/or stencil attachments.\endlink
+ \i \link setTextureTarget() Texture target.\endlink
+ \i \link setInternalFormat() Internal format.\endlink
+ \endlist
+
+ Note that the desired attachments or number of samples per pixels might not
+ be supported by the hardware driver. Call QGLFramebufferObject::format()
+ after creating a QGLFramebufferObject to find the exact format that was
+ used to create the frame buffer object.
+
+ \sa QGLFramebufferObject
+*/
+
+/*!
+ \since 4.6
+
+ Creates a QGLFramebufferObjectFormat object with properties specifying
+ the format of an OpenGL framebuffer object.
+
+ A multisample framebuffer object is specified by setting \a samples
+ to a value different from zero. If the desired amount of samples per pixel is
+ not supported by the hardware then the maximum number of samples per pixel
+ will be used. Note that multisample framebuffer objects can not be bound as
+ textures. Also, the \c{GL_EXT_framebuffer_multisample} extension is required
+ to create a framebuffer with more than one sample per pixel.
+
+ For multisample framebuffer objects a color render buffer is created,
+ otherwise a texture with the texture target \a target is created.
+ The color render buffer or texture will have the internal format
+ \a internalFormat, and will be bound to the \c GL_COLOR_ATTACHMENT0
+ attachment in the framebuffer object.
+
+ The \a attachment parameter describes the depth/stencil buffer
+ configuration.
+
+ \sa samples(), attachment(), target(), internalFormat()
+*/
+
+QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(int samples,
+ QGLFramebufferObject::Attachment attachment,
+ GLenum target,
+ GLenum internalFormat)
+{
+ d = new QGLFramebufferObjectFormatPrivate;
+ d->samples = samples;
+ d->attachment = attachment;
+ d->target = target;
+ d->internal_format = internalFormat;
+}
+
+/*!
+ \since 4.6
+
+ Constructs a copy of \a other.
+*/
+
+QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other)
+{
+ d = new QGLFramebufferObjectFormatPrivate;
+ *d = *other.d;
+}
+
+/*!
+ \since 4.6
+
+ Assigns \a other to this object.
+*/
+
+QGLFramebufferObjectFormat::QGLFramebufferObjectFormat &
+QGLFramebufferObjectFormat::operator=(const QGLFramebufferObjectFormat &other)
+{
+ *d = *other.d;
+ return *this;
+}
+
+/*!
+ \since 4.6
+
+ Destroys the QGLFramebufferObjectFormat.
+*/
+QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()
+{
+ delete d;
+}
+
+/*!
+ \since 4.6
+
+ Sets the number of samples per pixel for a multisample framebuffer object
+ to \a samples.
+ A sample count of 0 represents a regular non-multisample framebuffer object.
+
+ \sa samples()
+*/
+void QGLFramebufferObjectFormat::setSamples(int samples)
+{
+ d->samples = samples;
+}
+
+/*!
+ \since 4.6
+
+ Returns the number of samples per pixel if a framebuffer object
+ is a multisample framebuffer object. Otherwise, returns 0.
+
+ \sa setSamples()
+*/
+int QGLFramebufferObjectFormat::samples() const
+{
+ return d->samples;
+}
+
+/*!
+ \since 4.6
+
+ Sets the attachments a framebuffer object should have to \a attachment.
+
+ \sa attachment()
+*/
+void QGLFramebufferObjectFormat::setAttachment(QGLFramebufferObject::Attachment attachment)
+{
+ d->attachment = attachment;
+}
+
+/*!
+ \since 4.6
+
+ Returns the status of the depth and stencil buffers attached to
+ a framebuffer object.
+
+ \sa setAttachment()
+*/
+QGLFramebufferObject::Attachment QGLFramebufferObjectFormat::attachment() const
+{
+ return d->attachment;
+}
+
+/*!
+ \since 4.6
+
+ Sets the texture target of the texture attached to a framebuffer object to
+ \a target. Ignored for multisample framebuffer objects.
+
+ \sa textureTarget(), samples()
+*/
+void QGLFramebufferObjectFormat::setTextureTarget(GLenum target)
+{
+ d->target = target;
+}
+
+/*!
+ \since 4.6
+
+ Returns the texture target of the texture attached to a framebuffer object.
+ Ignored for multisample framebuffer objects.
+
+ \sa setTextureTarget(), samples()
+*/
+GLenum QGLFramebufferObjectFormat::textureTarget() const
+{
+ return d->target;
+}
+
+/*!
+ \since 4.6
+
+ Sets the internal format of a framebuffer object's texture or multisample
+ framebuffer object's color buffer to \a internalFormat.
+
+ \sa internalFormat()
+*/
+void QGLFramebufferObjectFormat::setInternalFormat(GLenum internalFormat)
+{
+ d->internal_format = internalFormat;
+}
+
+/*!
+ \since 4.6
+
+ Returns the internal format of a framebuffer object's texture or
+ multisample framebuffer object's color buffer.
+
+ \sa setInternalFormat()
+*/
+GLenum QGLFramebufferObjectFormat::internalFormat() const
+{
+ return d->internal_format;
+}
+
class QGLFramebufferObjectPrivate
{
public:
@@ -70,13 +284,16 @@ public:
~QGLFramebufferObjectPrivate() {}
void init(const QSize& sz, QGLFramebufferObject::Attachment attachment,
- GLenum internal_format, GLenum texture_target);
+ GLenum internal_format, GLenum texture_target, int samples = 0);
bool checkFramebufferStatus() const;
GLuint texture;
GLuint fbo;
GLuint depth_stencil_buffer;
+ GLuint color_buffer;
GLenum target;
QSize size;
+ QGLFramebufferObjectFormat format;
+ int samples;
uint valid : 1;
uint bound : 1;
QGLFramebufferObject::Attachment fbo_attachment;
@@ -118,6 +335,9 @@ bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
+ qDebug("QGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
+ break;
default:
qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
break;
@@ -126,7 +346,7 @@ bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
}
void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::Attachment attachment,
- GLenum texture_target, GLenum internal_format)
+ GLenum texture_target, GLenum internal_format, int samples)
{
ctx = const_cast<QGLContext *>(QGLContext::currentContext());
bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
@@ -143,26 +363,56 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
QT_CHECK_GLERROR();
// init texture
- glGenTextures(1, &texture);
- glBindTexture(target, texture);
- glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ if (samples == 0) {
+ glGenTextures(1, &texture);
+ glBindTexture(target, texture);
+ glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#ifndef QT_OPENGL_ES
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#else
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- target, texture, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ target, texture, 0);
- QT_CHECK_GLERROR();
- valid = checkFramebufferStatus();
+ QT_CHECK_GLERROR();
+ valid = checkFramebufferStatus();
+
+ color_buffer = 0;
+ samples = 0;
+ } else {
+ GLint maxSamples;
+ glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
+
+ samples = qBound(1, samples, int(maxSamples));
+
+ glGenRenderbuffersEXT(1, &color_buffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, color_buffer);
+ if (glRenderbufferStorageMultisampleEXT) {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ internal_format, size.width(), size.height());
+ } else {
+ samples = 0;
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internal_format,
+ size.width(), size.height());
+ }
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, color_buffer);
+
+ QT_CHECK_GLERROR();
+ valid = checkFramebufferStatus();
+
+ if (valid)
+ glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples);
+ }
if (attachment == QGLFramebufferObject::CombinedDepthStencil
&& (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
@@ -171,7 +421,13 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+ if (samples != 0 && glRenderbufferStorageMultisampleEXT)
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+ else
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+
GLint i = 0;
glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
@@ -179,6 +435,7 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_stencil_buffer);
fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
+
valid = checkFramebufferStatus();
if (!valid)
glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
@@ -189,12 +446,23 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
+ if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
#ifdef QT_OPENGL_ES
#define GL_DEPTH_COMPONENT16 0x81A5
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH_COMPONENT16, size.width(), size.height());
#else
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH_COMPONENT, size.width(), size.height());
#endif
+ } else {
+#ifdef QT_OPENGL_ES
+#define GL_DEPTH_COMPONENT16 0x81A5
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
+#else
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
+#endif
+ }
GLint i = 0;
glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
@@ -209,10 +477,18 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
if (!valid) {
- glDeleteTextures(1, &texture);
+ if (color_buffer)
+ glDeleteRenderbuffersEXT(1, &color_buffer);
+ else
+ glDeleteTextures(1, &texture);
glDeleteFramebuffersEXT(1, &fbo);
}
QT_CHECK_GLERROR();
+
+ format.setTextureTarget(target);
+ format.setSamples(samples);
+ format.setAttachment(fbo_attachment);
+ format.setInternalFormat(internal_format);
}
/*!
@@ -260,13 +536,18 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
framebuffer objects more portable.
\endlist
- Note that primitives drawn to a QGLFramebufferObject with QPainter
- will only be antialiased if the QPainter::HighQualityAntialiasing
- render hint is set. This is because there is currently no support
- for the \c{GL_EXT_framebuffer_multisample} extension, which is
- required to do multisample based antialiasing. Also note that the
- QPainter::HighQualityAntialiasing render hint requires the
- \c{GL_ARB_fragment_program} extension to work in OpenGL.
+ Note that you need to create a QGLFramebufferObject with more than one
+ sample per pixel for primitives to be antialiased when drawing using a
+ QPainter, unless if the QPainter::HighQualityAntialiasing render hint is
+ set. The QPainter::HighQualityAntialiasing render hint will enable
+ antialiasing as long as the \c{GL_ARB_fragment_program} extension is
+ present. To create a multisample framebuffer object you should use one of
+ the constructors that take a QGLFramebufferObject parameter, and set the
+ QGLFramebufferObject::samples() property to a non-zero value.
+
+ If you want to use a framebuffer object with multisampling enabled
+ as a texture, you first need to copy from it to a regular framebuffer
+ object using QGLContext::blitFramebuffer().
\sa {Framebuffer Object Example}
*/
@@ -354,6 +635,32 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)
d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
}
+/*! \overload
+
+ Constructs an OpenGL framebuffer object of the given \a size based on the
+ supplied \a format.
+*/
+
+QGLFramebufferObject::QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format)
+ : d_ptr(new QGLFramebufferObjectPrivate)
+{
+ Q_D(QGLFramebufferObject);
+ d->init(size, format.attachment(), format.textureTarget(), format.internalFormat(), format.samples());
+}
+
+/*! \overload
+
+ Constructs an OpenGL framebuffer object of the given \a width and \a height
+ based on the supplied \a format.
+*/
+
+QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format)
+ : d_ptr(new QGLFramebufferObjectPrivate)
+{
+ Q_D(QGLFramebufferObject);
+ d->init(QSize(width, height), format.attachment(), format.textureTarget(), format.internalFormat(), format.samples());
+}
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
/*! \internal */
QGLFramebufferObject::QGLFramebufferObject(int width, int height, QMacCompatGLenum target)
@@ -441,6 +748,8 @@ QGLFramebufferObject::~QGLFramebufferObject()
|| qgl_share_reg()->checkSharing(d->ctx, QGLContext::currentContext())))
{
glDeleteTextures(1, &d->texture);
+ if (d->color_buffer)
+ glDeleteRenderbuffersEXT(1, &d->color_buffer);
if (d->depth_stencil_buffer)
glDeleteRenderbuffersEXT(1, &d->depth_stencil_buffer);
glDeleteFramebuffersEXT(1, &d->fbo);
@@ -536,6 +845,9 @@ bool QGLFramebufferObject::release()
Returns the texture id for the texture attached as the default
rendering target in this framebuffer object. This texture id can
be bound as a normal texture in your own GL code.
+
+ If a multisample framebuffer object is used then the value returned
+ from this function will be invalid.
*/
GLuint QGLFramebufferObject::texture() const
{
@@ -556,6 +868,15 @@ QSize QGLFramebufferObject::size() const
}
/*!
+ Returns the format of this framebuffer object.
+*/
+const QGLFramebufferObjectFormat &QGLFramebufferObject::format() const
+{
+ Q_D(const QGLFramebufferObject);
+ return d->format;
+}
+
+/*!
\fn QImage QGLFramebufferObject::toImage() const
Returns the contents of this framebuffer object as a QImage.
@@ -573,7 +894,9 @@ QImage QGLFramebufferObject::toImage() const
return image;
}
-#if !defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_paintengine)
+#else
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
#endif
@@ -595,7 +918,8 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
{
- QGLWidget dmy; // needed to detect and init the QGLExtensions object
+ if (!QGLContext::currentContext())
+ QGLWidget dmy; // needed to detect and init the QGLExtensions object
return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
}
@@ -746,4 +1070,86 @@ bool QGLFramebufferObject::isBound() const
return d->bound;
}
+/*!
+ \fn bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
+
+ \since 4.6
+
+ Returns true if the OpenGL \c{GL_EXT_framebuffer_blit} extension
+ is present on this system; otherwise returns false.
+*/
+bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
+{
+ if (!QGLContext::currentContext())
+ QGLWidget dmy; // needed to detect and init the QGLExtensions object
+ return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit);
+}
+
+/*!
+ \since 4.6
+
+ Blits from the \a sourceRect rectangle in the \a source framebuffer
+ object to the \a targetRect rectangle in the \a target framebuffer object.
+
+ If \a source or \a target is 0, the default framebuffer will be used
+ instead of a framebuffer object as source or target respectively.
+
+ The \a buffers parameter should be a mask consisting of any combination of
+ COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, and STENCIL_BUFFER_BIT. Any buffer type
+ that is not present both in the source and target buffers is ignored.
+
+ The \a sourceRect and \a targetRect rectangles may have different sizes;
+ in this case \a buffers should not contain DEPTH_BUFFER_BIT or
+ STENCIL_BUFFER_BIT. The \a filter parameter should be set to GL_LINEAR or
+ GL_NEAREST, and specifies whether linear or nearest interpolation should
+ be used when scaling is performed.
+
+ If \a source equals \a target a copy is performed within the same buffer.
+ Results are undefined if the source and target rectangles overlap and
+ have different sizes. The sizes must also be the same if any of the
+ framebuffer objects are multisample framebuffers.
+
+ Note that the scissor test will restrict the blit area if enabled.
+
+ This function will have no effect unless hasOpenGLFramebufferBlit() returns
+ true.
+*/
+void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
+ QGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers,
+ GLenum filter)
+{
+ if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit))
+ return;
+
+ const QGLContext *ctx = QGLContext::currentContext();
+ if (!ctx)
+ return;
+
+ const int height = ctx->device()->height();
+
+ const int sh = source ? source->height() : height;
+ const int th = target ? target->height() : height;
+
+ const int sx0 = sourceRect.left();
+ const int sx1 = sourceRect.right();
+ const int sy0 = sh - sourceRect.bottom() - 1;
+ const int sy1 = sh - sourceRect.top() - 1;
+
+ const int tx0 = targetRect.left();
+ const int tx1 = targetRect.right();
+ const int ty0 = th - targetRect.bottom() - 1;
+ const int ty1 = th - targetRect.top() - 1;
+
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source ? source->handle() : 0);
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, target ? target->handle() : 0);
+
+ glBlitFramebufferEXT(sx0, sy0, sx1, sy1,
+ tx0, ty0, tx1, ty1,
+ buffers, filter);
+
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h
index a9e1b2f..0a2a9d2 100644
--- a/src/opengl/qglframebufferobject.h
+++ b/src/opengl/qglframebufferobject.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(OpenGL)
class QGLFramebufferObjectPrivate;
+class QGLFramebufferObjectFormat;
class Q_OPENGL_EXPORT QGLFramebufferObject : public QPaintDevice
{
@@ -77,6 +78,9 @@ public:
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
#endif
+ QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format);
+ QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format);
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
QGLFramebufferObject(const QSize &size, QMacCompatGLenum target = GL_TEXTURE_2D);
QGLFramebufferObject(int width, int height, QMacCompatGLenum target = GL_TEXTURE_2D);
@@ -89,10 +93,13 @@ public:
virtual ~QGLFramebufferObject();
+ const QGLFramebufferObjectFormat &format() const;
+
bool isValid() const;
bool isBound() const;
bool bind();
bool release();
+
GLuint texture() const;
QSize size() const;
QImage toImage() const;
@@ -110,6 +117,12 @@ public:
void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D);
#endif
+ static bool hasOpenGLFramebufferBlit();
+ static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
+ QGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers = GL_COLOR_BUFFER_BIT,
+ GLenum filter = GL_NEAREST);
+
protected:
int metric(PaintDeviceMetric metric) const;
int devType() const { return QInternal::FramebufferObject; }
@@ -120,6 +133,42 @@ private:
friend class QGLDrawable;
};
+class QGLFramebufferObjectFormatPrivate;
+class Q_OPENGL_EXPORT QGLFramebufferObjectFormat
+{
+public:
+#if !defined(QT_OPENGL_ES) || defined(Q_QDOC)
+ QGLFramebufferObjectFormat(int samples = 0,
+ QGLFramebufferObject::Attachment attachment = QGLFramebufferObject::NoAttachment,
+ GLenum target = GL_TEXTURE_2D,
+ GLenum internalFormat = GL_RGBA8);
+#else
+ QGLFramebufferObjectFormat(int samples = 0,
+ QGLFramebufferObject::Attachment attachment = QGLFramebufferObject::NoAttachment,
+ GLenum target = GL_TEXTURE_2D,
+ GLenum internalFormat = GL_RGBA);
+#endif
+
+ QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other);
+ QGLFramebufferObjectFormat &operator=(const QGLFramebufferObjectFormat &other);
+ ~QGLFramebufferObjectFormat();
+
+ void setSamples(int samples);
+ int samples() const;
+
+ void setAttachment(QGLFramebufferObject::Attachment attachment);
+ QGLFramebufferObject::Attachment attachment() const;
+
+ void setTextureTarget(GLenum target);
+ GLenum textureTarget() const;
+
+ void setInternalFormat(GLenum internalFormat);
+ GLenum internalFormat() const;
+
+private:
+ QGLFramebufferObjectFormatPrivate *d;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 5f74f26..6a207c8 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -81,13 +81,15 @@
#include <private/qglpixelbuffer_p.h>
#include <qimage.h>
-#if !defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
+#include <private/qpaintengineex_opengl2_p.h>
+#else
#include <private/qpaintengine_opengl_p.h>
#endif
QT_BEGIN_NAMESPACE
-#if !defined(QT_OPENGL_ES_2)
+#if 0 && !defined(QT_OPENGL_ES_2)
extern void qgl_cleanup_glyph_cache(QGLContext *);
#else
void qgl_cleanup_glyph_cache(QGLContext *) {}
@@ -363,7 +365,9 @@ bool QGLPixelBuffer::isValid() const
return !d->invalid;
}
-#if !defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_paintengine)
+#else
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
#endif
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index ff23948..8a64515 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -138,13 +138,6 @@ void QGLSLProgram::disable()
glUseProgram(0);
}
-typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
-
int QGLSLProgram::getUniformLocation(const QString &name)
{
return glGetUniformLocation(m_program, name.toAscii().constData());
@@ -244,7 +237,18 @@ QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const
#if !defined(QT_OPENGL_ES_2)
extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
-extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
+//extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
+void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
+{
+ array[0] = f2vt(x1);
+ array[1] = f2vt(y1);
+ array[2] = f2vt(x2);
+ array[3] = f2vt(y1);
+ array[4] = f2vt(x2);
+ array[5] = f2vt(y2);
+ array[6] = f2vt(x1);
+ array[7] = f2vt(y2);
+}
#endif
static void qgl_drawTexture(const QRectF &rect, int tx_width, int tx_height, const QRectF & src)
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index 976a021..998492c 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -57,13 +57,11 @@
#include "qpen.h"
#include "qvarlengtharray.h"
#include <private/qpainter_p.h>
-#include <qglpixelbuffer.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qbezier_p.h>
#include <qglframebufferobject.h>
#include "private/qtessellator_p.h"
-#include "private/qwindowsurface_gl_p.h"
#include "util/fragmentprograms_p.h"
@@ -190,180 +188,6 @@ const QGLTrapezoid QGLTrapezoid::translated(const QPointF &delta) const
return trap;
}
-class QGLDrawable {
-public:
- QGLDrawable() : widget(0), buffer(0), fbo(0)
- , wsurf(0)
- {}
- inline void setDevice(QPaintDevice *pdev);
- inline void swapBuffers();
- inline void makeCurrent();
- inline void doneCurrent();
- inline QSize size() const;
- inline QGLFormat format() const;
- inline GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
- inline GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
- inline QColor backgroundColor() const;
- inline QGLContext *context() const;
- inline bool autoFillBackground() const;
-
-private:
- bool wasBound;
- QGLWidget *widget;
- QGLPixelBuffer *buffer;
- QGLFramebufferObject *fbo;
-#ifdef Q_WS_QWS
- QWSGLWindowSurface *wsurf;
-#else
- QGLWindowSurface *wsurf;
-#endif
-};
-
-void QGLDrawable::setDevice(QPaintDevice *pdev)
-{
- wasBound = false;
- widget = 0;
- buffer = 0;
- fbo = 0;
-#ifdef Q_WS_QWS
- wsurf = 0;
-#endif
- if (pdev->devType() == QInternal::Widget)
- widget = static_cast<QGLWidget *>(pdev);
- else if (pdev->devType() == QInternal::Pbuffer)
- buffer = static_cast<QGLPixelBuffer *>(pdev);
- else if (pdev->devType() == QInternal::FramebufferObject)
- fbo = static_cast<QGLFramebufferObject *>(pdev);
- else if (pdev->devType() == QInternal::UnknownDevice)
-#ifdef Q_WS_QWS
- wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
-#else
- wsurf = static_cast<QGLWindowSurface *>(pdev);
-#endif
-}
-
-inline void QGLDrawable::swapBuffers()
-{
- if (widget) {
- if (widget->autoBufferSwap())
- widget->swapBuffers();
- } else {
- glFlush();
- }
-}
-
-inline void QGLDrawable::makeCurrent()
-{
- if (widget)
- widget->makeCurrent();
- else if (buffer)
- buffer->makeCurrent();
- else if (wsurf)
- wsurf->context()->makeCurrent();
- else if (fbo) {
- wasBound = fbo->isBound();
- if (!wasBound)
- fbo->bind();
- }
-}
-
-inline void QGLDrawable::doneCurrent()
-{
- if (fbo && !wasBound)
- fbo->release();
-}
-
-inline QSize QGLDrawable::size() const
-{
- if (widget) {
- return QSize(widget->d_func()->glcx->device()->width(),
- widget->d_func()->glcx->device()->height());
- } else if (buffer) {
- return buffer->size();
- } else if (fbo) {
- return fbo->size();
- } else if (wsurf) {
-#ifdef Q_WS_QWS
- return wsurf->window()->frameSize();
-#else
- return QSize(wsurf->width(), wsurf->height());
-#endif
- }
- return QSize();
-}
-
-inline QGLFormat QGLDrawable::format() const
-{
- if (widget)
- return widget->format();
- else if (buffer)
- return buffer->format();
- else if (wsurf)
- return wsurf->context()->format();
- else if (fbo && QGLContext::currentContext()) {
- QGLFormat fmt = QGLContext::currentContext()->format();
- fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
- fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
- return fmt;
- }
-
- return QGLFormat();
-}
-
-inline GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
-{
- if (widget)
- return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
- else if (buffer)
- return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
- else if (fbo && QGLContext::currentContext())
- return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
- else if (wsurf)
- return wsurf->context()->d_func()->bindTexture(image, target, format, true);
- return 0;
-}
-
-inline GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
-{
- if (widget)
- return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
- else if (buffer)
- return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
- else if (fbo && QGLContext::currentContext())
- return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
- else if (wsurf)
- return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
- return 0;
-}
-
-inline QColor QGLDrawable::backgroundColor() const
-{
- if (widget)
- return widget->palette().brush(widget->backgroundRole()).color();
- return QApplication::palette().brush(QPalette::Background).color();
-}
-
-inline QGLContext *QGLDrawable::context() const
-{
- if (widget)
- return widget->d_func()->glcx;
- else if (buffer)
- return buffer->d_func()->qctx;
- else if (fbo)
- return const_cast<QGLContext *>(QGLContext::currentContext());
- else if (wsurf)
- return wsurf->context();
- return 0;
-}
-
-inline bool QGLDrawable::autoFillBackground() const
-{
- if (widget)
- return widget->autoFillBackground();
- else
- return false;
-}
-
class QOpenGLImmediateModeTessellator;
class QGLMaskGenerator;
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index b079557..ec71fa6 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -57,12 +57,14 @@ class QGLShareContextScope
public:
QGLShareContextScope(const QGLContext *ctx)
: m_oldContext(0)
- , m_ctx(const_cast<QGLContext *>(ctx))
{
- const QGLContext *currentContext = QGLContext::currentContext();
+ QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
if (currentContext != ctx && !qgl_share_reg()->checkSharing(ctx, currentContext)) {
- m_oldContext = const_cast<QGLContext *>(currentContext);
+ m_oldContext = currentContext;
+ m_ctx = const_cast<QGLContext *>(ctx);
m_ctx->makeCurrent();
+ } else {
+ m_ctx = currentContext;
}
}
@@ -127,6 +129,7 @@ QGLPixmapData::QGLPixmapData(PixelType type)
: QPixmapData(type, OpenGLClass)
, m_width(0)
, m_height(0)
+ , m_ctx(0)
, m_texture(0)
, m_dirty(false)
{
@@ -148,6 +151,9 @@ bool QGLPixmapData::isValid() const
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
{
+ if (ctx == m_ctx)
+ return true;
+
const QGLContext *share_ctx = qt_gl_share_widget()->context();
return ctx == share_ctx || qgl_share_reg()->checkSharing(ctx, share_ctx);
}
@@ -173,6 +179,7 @@ void QGLPixmapData::ensureCreated() const
m_dirty = false;
QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ m_ctx = ctx;
const GLenum format = qt_gl_preferredTextureFormat();
const GLenum target = qt_gl_preferredTextureTarget();
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index e450f01..97f4959 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -97,6 +97,7 @@ private:
int m_width;
int m_height;
+ mutable QGLContext *m_ctx;
mutable GLuint m_texture;
mutable bool m_dirty;
mutable QImage m_source;
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 3dd3064..b4a4565 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -69,7 +69,11 @@
#include <private/qglpixelbuffer_p.h>
#include <private/qgraphicssystem_gl_p.h>
+#if 1 || defined(QT_OPENGL_ES_2)
+#include <private/qpaintengineex_opengl2_p.h>
+#else
#include <private/qpaintengine_opengl_p.h>
+#endif
#ifndef GLX_ARB_multisample
#define GLX_SAMPLE_BUFFERS_ARB 100000
@@ -283,7 +287,9 @@ void QGLWindowSurface::hijackWindow(QWidget *widget)
qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size();
}
-#if !defined(QT_OPENGL_ES_2)
+#if 1 || defined(QT_OPENGL_ES_2)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_window_surface_paintengine)
+#else
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_window_surface_paintengine)
#endif
@@ -309,6 +315,8 @@ QGLContext *QGLWindowSurface::context() const
QPaintDevice *QGLWindowSurface::paintDevice()
{
+ updateGeometry();
+
if (d_ptr->pb)
return d_ptr->pb;
@@ -324,6 +332,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize,
void QGLWindowSurface::beginPaint(const QRegion &)
{
+ updateGeometry();
}
void QGLWindowSurface::endPaint(const QRegion &rgn)
@@ -427,36 +436,44 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
#ifdef Q_WS_MAC
ctx->updatePaintDevice();
#endif
- if (d_ptr->fbo)
- d_ptr->fbo->release();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ if (d_ptr->fbo && QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) {
+ QGLFramebufferObject::blitFramebuffer(0, rect, d_ptr->fbo, rect);
+ d_ptr->fbo->bind();
+ } else {
+ if (d_ptr->fbo)
+ d_ptr->fbo->release();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
#ifndef QT_OPENGL_ES
- glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
+ glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
#else
- glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
+ glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
#endif
- glViewport(0, 0, size.width(), size.height());
+ glViewport(0, 0, size.width(), size.height());
- glColor4f(1, 1, 1, 1);
- drawTexture(rect, texture, window()->size(), br);
+ glColor4f(1, 1, 1, 1);
+ drawTexture(rect, texture, window()->size(), br);
+
+ if (d_ptr->fbo)
+ d_ptr->fbo->bind();
+ }
if (ctx->format().doubleBuffer())
ctx->swapBuffers();
else
glFlush();
-
- if (d_ptr->fbo)
- d_ptr->fbo->bind();
}
-void QGLWindowSurface::setGeometry(const QRect &rect)
+void QGLWindowSurface::updateGeometry()
{
- QWindowSurface::setGeometry(rect);
+ QRect rect = QWindowSurface::geometry();
const GLenum target = qt_gl_preferredTextureTarget();
@@ -490,7 +507,7 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
qt_gl_share_widget());
if (d_ptr->pb->isValid()) {
- qDebug() << "PB Sample buffers:" << d_ptr->pb->format().sampleBuffers();
+ qDebug() << "Created Window Surface Pixelbuffer, Sample buffers:" << d_ptr->pb->format().sampleBuffers();
d_ptr->pb->makeCurrent();
glGenTextures(1, &d_ptr->pb_tex_id);
@@ -525,11 +542,20 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
ctx->d_ptr->internal_context = true;
ctx->makeCurrent();
delete d_ptr->fbo;
- d_ptr->fbo = new QGLFramebufferObject(rect.size(), QGLFramebufferObject::CombinedDepthStencil,
- GLenum(target), GLenum(GL_RGBA));
+ QGLFramebufferObjectFormat format;
+ format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalFormat(GL_RGBA);
+ format.setTextureTarget(target);
+
+ if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
+ format.setSamples(8);
+
+ d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);
d_ptr->fbo->bind();
if (d_ptr->fbo->isValid()) {
+ qDebug() << "Created Window Surface FBO" << rect.size()
+ << "with samples" << d_ptr->fbo->format().samples();
return;
} else {
qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back";
@@ -555,6 +581,11 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
d_ptr->ctx->d_ptr->internal_context = true;
}
+void QGLWindowSurface::setGeometry(const QRect &rect)
+{
+ QWindowSurface::setGeometry(rect);
+}
+
bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy)
{
// this code randomly fails currently for unknown reasons
diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h
index 0194378..d47e3e3 100644
--- a/src/opengl/qwindowsurface_gl_p.h
+++ b/src/opengl/qwindowsurface_gl_p.h
@@ -74,6 +74,7 @@ public:
QPaintDevice *paintDevice();
void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
void setGeometry(const QRect &rect);
+ void updateGeometry();
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &region);