From e8f91c93de3599309d8fe11fd94318bfdc51d36c Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Thu, 12 Feb 2009 15:59:43 +0100 Subject: Merge branch 'gl2text' of ..\qt-main --- src/opengl/gl2paintengineex/qglshader.cpp | 16 ++- src/opengl/gl2paintengineex/qglshader_p.h | 1 + .../gl2paintengineex/qpaintengineex_opengl2.cpp | 6 ++ src/opengl/opengl.pro | 12 +-- src/opengl/qgl.cpp | 25 ++++- src/opengl/qglextensions.cpp | 21 +++- src/opengl/qglextensions_p.h | 111 ++++++++++++++++++++- src/opengl/qglframebufferobject.cpp | 8 +- src/opengl/qglpixelbuffer.cpp | 10 +- src/opengl/qglpixmapfilter.cpp | 20 ++-- src/opengl/qwindowsurface_gl.cpp | 8 +- 11 files changed, 207 insertions(+), 31 deletions(-) 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 +#include typedef struct { GLfloat a; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index a74f044..2948e62 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -845,6 +845,7 @@ void QGL2PaintEngineEx::transformChanged() void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src) { Q_D(QGL2PaintEngineEx); + QGLContext *ctx = d->ctx; glActiveTexture(QT_BRUSH_TEXTURE_UNIT); d->ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true); @@ -862,6 +863,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const Qt::ImageConversionFlags) { Q_D(QGL2PaintEngineEx); + QGLContext *ctx = d->ctx; glActiveTexture(QT_BRUSH_TEXTURE_UNIT); d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); @@ -926,6 +928,7 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t const QImage &image = cache->image(); int margin = cache->glyphMargin(); + QGLContext *ctx = d->ctx; glActiveTexture(QT_BRUSH_TEXTURE_UNIT); d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); @@ -1000,6 +1003,9 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->width = widget->width(); d->height = widget->height(); + qt_resolve_version_1_3_functions(d->ctx); + qt_resolve_glsl_extensions(d->ctx); + if (!d->shaderManager) d->shaderManager = new QGLPEXShaderManager(d->ctx); 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..386e9b8 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -65,7 +65,7 @@ #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 @@ -2041,7 +2041,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 +4056,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(); diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index 8357cf9..b054fe8 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -176,10 +176,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..fdf0bba 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); @@ -207,6 +227,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; @@ -270,6 +305,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; }; @@ -416,6 +466,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 @@ -502,6 +586,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..9134fc6 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -43,7 +43,11 @@ #include #include +#if 1 || defined(QT_OPENGL_ES_2) +#include +#else #include +#endif #include #include #include @@ -573,7 +577,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 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 #include -#if !defined(QT_OPENGL_ES_2) +#if 1 || defined(QT_OPENGL_ES_2) +#include +#else #include #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/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 3dd3064..bb4ffc5 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -69,7 +69,11 @@ #include #include +#if 1 || defined(QT_OPENGL_ES_2) +#include +#else #include +#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 -- cgit v0.12 From afdd536c50ba14ece1db63f5efab0328730f2e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 17 Feb 2009 14:10:06 +0100 Subject: Fixes: Move QGLDrawable into qgl_p.h so that we can use it in the GL 2 paint engine. RevBy: Tom Details: Now we can use the GL 2 paint engine on non-widget paint devices like pixel buffers, framebuffer objects, and GL window surfaces. Using -graphicssystem opengl works now. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 19 +-- src/opengl/qgl.cpp | 150 ++++++++++++++++++ src/opengl/qgl_p.h | 33 ++++ src/opengl/qpaintengine_opengl.cpp | 176 --------------------- 4 files changed, 193 insertions(+), 185 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2948e62..1cc2233 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -133,10 +133,9 @@ public: inline QColor premultiplyColor(QColor c, GLfloat opacity); QGL2PaintEngineEx* q; - - //### Move into QGLDrawable + QGLDrawable drawable; + QGLContext *ctx; int width, height; - QGLContext* ctx; // Dirty flags bool matrixDirty; // Implies matrix uniforms are also dirty @@ -997,11 +996,12 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) // qDebug("QGL2PaintEngineEx::begin()"); - QGLWidget* widget = static_cast(pdev); - d->ctx = const_cast(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(); qt_resolve_version_1_3_functions(d->ctx); qt_resolve_glsl_extensions(d->ctx); @@ -1033,7 +1033,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) bool QGL2PaintEngineEx::end() { Q_D(QGL2PaintEngineEx); - d->ctx->swapBuffers(); + d->drawable.swapBuffers(); + d->drawable.doneCurrent(); return false; } diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 386e9b8..7c42039 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -71,9 +71,14 @@ #include #endif +#include +#include + #include #include #include +#include +#include #include "qcolormap.h" #include "qcache.h" #include "qfile.h" @@ -4219,4 +4224,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(pdev); + else if (pdev->devType() == QInternal::Pbuffer) + buffer = static_cast(pdev); + else if (pdev->devType() == QInternal::FramebufferObject) + fbo = static_cast(pdev); + else if (pdev->devType() == QInternal::UnknownDevice) +#ifdef Q_WS_QWS + wsurf = static_cast(pdev)->windowSurface(); +#else + wsurf = static_cast(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::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::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::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..2eccc23 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: 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 -#include #include #include #include #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(pdev); - else if (pdev->devType() == QInternal::Pbuffer) - buffer = static_cast(pdev); - else if (pdev->devType() == QInternal::FramebufferObject) - fbo = static_cast(pdev); - else if (pdev->devType() == QInternal::UnknownDevice) -#ifdef Q_WS_QWS - wsurf = static_cast(pdev)->windowSurface(); -#else - wsurf = static_cast(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::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::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::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; -- cgit v0.12 From 842d514edd0ef6fa8d6e863dfe6ba696b95ba790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 17 Feb 2009 15:43:05 +0100 Subject: Get rid of warning introduced in the last commit. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 1cc2233..e211f10 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -134,8 +134,8 @@ public: QGL2PaintEngineEx* q; QGLDrawable drawable; - QGLContext *ctx; int width, height; + QGLContext *ctx; // Dirty flags bool matrixDirty; // Implies matrix uniforms are also dirty -- cgit v0.12 From a49ec03834b14063b4130c410d59df6e8c4db8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 17 Feb 2009 16:11:41 +0100 Subject: Fixes: Improve text rendering in GL 2 paint engine. Details: Avoid adding 0.5 to dx() / dy() which caused images / glyphs to get slight antialiasing and edge artifacts. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e211f10..0e41602 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -399,8 +399,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()} }; -- cgit v0.12 From 6513e4b9513dfc591c53744517f05aa3c522ace3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 18 Feb 2009 09:42:04 +0100 Subject: Fixes: GL 2 paint engine text rendering optimization. RevBy: Tom Details: Buffer vertex and texture coordinates so that we get away with just a single glDrawArrays call per text item. Also move drawCachedGlyphs() into the private class. --- src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp | 6 ++ src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h | 1 + .../gl2paintengineex/qpaintengineex_opengl2.cpp | 101 +++++++++------------ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 1 - 4 files changed, 52 insertions(+), 57 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(path.points()); diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h index c205022..65f6d42 100644 --- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h +++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h @@ -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/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 0e41602..ea0d7b1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -115,6 +115,7 @@ public: void setBrush(const QBrush* brush); void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight); + void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti); void fill(const QVectorPath &path); void drawOutline(const QVectorPath& path); @@ -152,7 +153,8 @@ public: GLfloat inverseScale; - QGL2PEXVertexArray pathVertexArray; + QGL2PEXVertexArray vertexCoordinateArray; + QGL2PEXVertexArray textureCoordinateArray; GLfloat pmvMatrix[4][4]; @@ -548,17 +550,17 @@ void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path) 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); } @@ -578,26 +580,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()); } } @@ -876,6 +878,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem) { + Q_D(QGL2PaintEngineEx); QOpenGLPaintEngineState *s = state(); const QTextItemInt &ti = static_cast(textItem); @@ -893,17 +896,17 @@ 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(); QVarLengthArray positions; QVarLengthArray glyphs; @@ -927,65 +930,51 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t const QImage &image = cache->image(); int margin = cache->glyphMargin(); - QGLContext *ctx = d->ctx; glActiveTexture(QT_BRUSH_TEXTURE_UNIT); - d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); glEnable(GL_BLEND); - d->shaderManager->textShader()->use(); - d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); + shaderManager->textShader()->use(); + 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; + shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT; + 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); + vertexCoordinateArray.clear(); + textureCoordinateArray.clear(); + for (int i=0; icoords.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); + 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)); + } - GLfloat textureCoords[] = { - srcTextureRect.left, srcTextureRect.top, - srcTextureRect.left, srcTextureRect.bottom, - srcTextureRect.right, srcTextureRect.bottom, - srcTextureRect.right, srcTextureRect.top - }; + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords); + 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()); + glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); } 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; } -- cgit v0.12 From d903f379470fb9f9159fbf37f2cfc02638cd05f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 18 Feb 2009 14:54:51 +0100 Subject: Fixes: Enable use of the GL pixmap backend in the GL 2 paint engine. --- src/opengl/qgl.cpp | 10 +++++----- src/opengl/qgl_p.h | 4 ++++ src/opengl/qpixmapdata_gl.cpp | 13 ++++++++++--- src/opengl/qpixmapdata_gl_p.h | 1 + 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 7c42039..558897d 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1888,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(pixmap.pixmapData()); + Q_Q(QGLContext); + QPixmapData *pd = pixmap.pixmapData(); + if (target == qt_gl_preferredTextureTarget() && pd->classId() == QPixmapData::OpenGLClass) { + const QGLPixmapData *data = static_cast(pd); - if (data->isValidContext(QGLContext::currentContext())) + if (data->isValidContext(q)) return data->bind(); } -#endif const qint64 key = pixmap.cacheKey(); GLuint id; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 2eccc23..76f3812 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -418,9 +418,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/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(ctx)) { - const QGLContext *currentContext = QGLContext::currentContext(); + QGLContext *currentContext = const_cast(QGLContext::currentContext()); if (currentContext != ctx && !qgl_share_reg()->checkSharing(ctx, currentContext)) { - m_oldContext = const_cast(currentContext); + m_oldContext = currentContext; + m_ctx = const_cast(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; -- cgit v0.12 From a3c964db2bee664b0e71e9ec1c5d8b2830659ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 18 Feb 2009 14:56:16 +0100 Subject: Fixes: Introduce mode transfer functions in the GL 2 paint engine. RevBy: Tom Details: Mode transfer lets us optimize the case where the same operation is done a lot of times in a row, for example image or text drawing, by being able to assume that most of the state has already been set up properly. --- src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h | 4 +- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 143 +++++++++++++-------- 2 files changed, 94 insertions(+), 53 deletions(-) diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h index 65f6d42..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) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ea0d7b1..88c33d4 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 +enum EngineMode { + ImageDrawingMode, + TextDrawingMode, + DefaultMode +}; static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; @@ -114,7 +119,9 @@ 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); @@ -138,6 +145,8 @@ public: int width, height; QGLContext *ctx; + EngineMode mode; + // Dirty flags bool matrixDirty; // Implies matrix uniforms are also dirty bool compositionModeDirty; @@ -156,6 +165,9 @@ public: QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; + GLfloat staticVertexCoordinateArray[8]; + GLfloat staticTextureCoordinateArray[8]; + GLfloat pmvMatrix[4][4]; QGLPEXShaderManager* shaderManager; @@ -486,14 +498,21 @@ 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); if (compositionModeDirty) @@ -507,45 +526,66 @@ 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(); @@ -567,6 +607,8 @@ void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path) // Assumes everything is configured for the brush you want to use void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) { + transferMode(DefaultMode); + if (matrixDirty) updateMatrix(); @@ -846,10 +888,10 @@ void QGL2PaintEngineEx::transformChanged() void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src) { Q_D(QGL2PaintEngineEx); - QGLContext *ctx = d->ctx; - 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()) @@ -857,23 +899,24 @@ 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); + d->transferMode(ImageDrawingMode); + QGLContext *ctx = d->ctx; - glActiveTexture(QT_BRUSH_TEXTURE_UNIT); - d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + 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) @@ -908,6 +951,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte Q_Q(QGL2PaintEngineEx); QOpenGLPaintEngineState *s = q->state(); + transferMode(TextDrawingMode); + QVarLengthArray positions; QVarLengthArray glyphs; QTransform matrix; @@ -930,12 +975,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte const QImage &image = cache->image(); int margin = cache->glyphMargin(); - glActiveTexture(QT_BRUSH_TEXTURE_UNIT); ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); - glEnable(GL_BLEND); - - shaderManager->textShader()->use(); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); if (compositionModeDirty) @@ -949,13 +990,15 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte textShaderMatrixUniformDirty = false; } - shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT; 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(); + QGLPoint *oldVertexCoordinateDataPtr = vertexCoordinateArray.data(); + QGLPoint *oldTextureCoordinateDataPtr = textureCoordinateArray.data(); + vertexCoordinateArray.clear(); textureCoordinateArray.clear(); @@ -968,15 +1011,12 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte textureCoordinateArray.addRect(QRectF(c.x*dx, 1 - c.y*dy, c.w * dx, -c.h * dy)); } - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + 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()); - 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()); glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); - - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); } bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) @@ -991,6 +1031,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) 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); -- cgit v0.12 From 7cee2659388388754d741ba4b46647c57d03c498 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 23 Feb 2009 13:54:07 +0100 Subject: Fixes: Make raster engine perform better on 0-opacity drawing RevBy: sroedal Task: came in from brisbane --- src/gui/painting/qdrawhelper_p.h | 3 ++- src/gui/painting/qpaintengine_raster.cpp | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index de97683..586ffe3 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -110,6 +110,7 @@ struct QSpanData; class QGradient; class QRasterBuffer; class QClipData; +class QRasterPaintEngineState; typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, @@ -293,7 +294,7 @@ struct QSpanData }; void init(QRasterBuffer *rb, const QRasterPaintEngine *pe); - void setup(const QBrush &brush, int alpha); + void setup(const QBrush &brush, int alpha, const QRasterPaintEngineState *s); void setupMatrix(const QTransform &matrix, int bilinear); void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect()); void adjustSpanMethods(); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index ba79b5b..92a196c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -483,12 +483,12 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) d->rasterizer->setClipRect(d->deviceRect); s->penData.init(d->rasterBuffer, this); - s->penData.setup(s->pen.brush(), s->intOpacity); + s->penData.setup(s->pen.brush(), s->intOpacity, s); s->stroker = &d->basicStroker; d->basicStroker.setClipRect(d->deviceRect); s->brushData.init(d->rasterBuffer, this); - s->brushData.setup(s->brush, s->intOpacity); + s->brushData.setup(s->brush, s->intOpacity, s); d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver; @@ -769,7 +769,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) s->strokeFlags = 0; s->penData.clip = d->clip(); - s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity); + s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s); if (s->strokeFlags & QRasterPaintEngine::DirtyTransform || pen.brush().transform().type() >= QTransform::TxNone) { @@ -869,7 +869,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush) QRasterPaintEngineState *s = state(); // must set clip prior to setup, as setup uses it... s->brushData.clip = d->clip(); - s->brushData.setup(brush, s->intOpacity); + s->brushData.setup(brush, s->intOpacity, s); if (s->fillFlags & DirtyTransform || brush.transform().type() >= QTransform::TxNone) d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix()); @@ -1024,6 +1024,10 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, { if (!clip.isValid()) return; + + if (alpha ==0) + return; + Q_ASSERT(img.depth() >= 8); int srcBPL = img.bytesPerLine(); @@ -1867,9 +1871,12 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) QRasterPaintEngineState *s = state(); d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); + if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + return; + } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); - fillRect(r, &d->solid_color_filler); } @@ -4906,7 +4913,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) extern QImage qt_imageForBrush(int brushStyle, bool invert); -void QSpanData::setup(const QBrush &brush, int alpha) +void QSpanData::setup(const QBrush &brush, int alpha, const QRasterPaintEngineState *s) { Qt::BrushStyle brushStyle = qbrush_style(brush); switch (brushStyle) { @@ -4914,6 +4921,10 @@ void QSpanData::setup(const QBrush &brush, int alpha) type = Solid; QColor c = qbrush_color(brush); solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha)); + if ((solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + type = None; + } break; } -- cgit v0.12 From 6ab74831766cdd5cf4e94eee8a60099436e61202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 9 Mar 2009 13:07:18 +0100 Subject: Fixes: Extreme amount of pixel buffers created in embeddeddialogs demo. Details: As a window surface is created even for embedded widgets, don't create the GL resources required by the surface until they are actually needed. RevBy: Tom --- src/opengl/qwindowsurface_gl.cpp | 14 +++++++++++--- src/opengl/qwindowsurface_gl_p.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index bb4ffc5..08c2aab 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -315,6 +315,8 @@ QGLContext *QGLWindowSurface::context() const QPaintDevice *QGLWindowSurface::paintDevice() { + updateGeometry(); + if (d_ptr->pb) return d_ptr->pb; @@ -330,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) @@ -460,9 +463,9 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & 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(); @@ -496,7 +499,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); @@ -561,6 +564,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 ®ion, const QPoint &offset); void setGeometry(const QRect &rect); + void updateGeometry(); bool scroll(const QRegion &area, int dx, int dy); void beginPaint(const QRegion ®ion); -- cgit v0.12 From 570ef6dbc4526d39ef8d2b7e29ddedcfa67b061f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 9 Mar 2009 15:01:48 +0100 Subject: Fixes: Clipping bug in GL 2 paint engine (embeddeddialogs demo). RevBy: Tom --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 88c33d4..9eeef1b 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1057,6 +1057,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) glDisable(GL_DEPTH_TEST); + updateClipRegion(QRegion(), Qt::NoClip); return true; } -- cgit v0.12 From 0f95b04c91e559ca62698234dcd82445c5ee8ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 9 Mar 2009 15:01:16 +0100 Subject: Fixes: Small optimizations in GL 2 paint engine... RevBy: Tom --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 9eeef1b..ce9f976 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -424,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]; } } @@ -804,8 +806,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 -- cgit v0.12 From 4feeae36f1dc18795646e648f9987795706d21f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 9 Mar 2009 13:09:25 +0100 Subject: Fixes: Get rid of GL 2 paint engine debug message... RevBy: Tom --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ce9f976..6e24bdc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -794,8 +794,6 @@ void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray, QGL2PaintEngineEx::QGL2PaintEngineEx() : QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this))) { - qDebug("QGL2PaintEngineEx::QGL2PaintEngineEx()"); - } QGL2PaintEngineEx::~QGL2PaintEngineEx() -- cgit v0.12 From 56fc9b853f8d19999c81ed13a9f2fcd0e95241e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 11 Mar 2009 09:16:37 +0100 Subject: Fixes: Respect the SmoothPixmapTransform render hint in the GL2 paint engine. RevBy: Tom --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 6e24bdc..dbf18b1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -515,7 +515,7 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect) void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize) { // qDebug("QGL2PaintEngineExPrivate::drawImage()"); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); if (compositionModeDirty) updateCompositionMode(); -- cgit v0.12 From 4d4580b5f43adb22b6ba95f49698efcd5dbdfeae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 11 Mar 2009 10:37:13 +0100 Subject: Fixes: Make FBO window surface work with GL 2 paint engine. RevBy: Trond Details: Need to make sure clipping/scissoring etc is turned off and that we are in a good state. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 3 +++ src/opengl/qwindowsurface_gl.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index dbf18b1..89ed1f7 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1062,6 +1062,9 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) bool QGL2PaintEngineEx::end() { Q_D(QGL2PaintEngineEx); + QGLContext *ctx = d->ctx; + glUseProgram(0); + d->transferMode(DefaultMode); d->drawable.swapBuffers(); d->drawable.doneCurrent(); return false; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 08c2aab..5cd4366 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -439,6 +439,9 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & if (d_ptr->fbo) d_ptr->fbo->release(); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -539,6 +542,7 @@ void QGLWindowSurface::updateGeometry() d_ptr->fbo->bind(); if (d_ptr->fbo->isValid()) { + qDebug() << "Created Window Surface FBO" << rect.size(); return; } else { qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back"; -- cgit v0.12 From 1ada6800efbbca276441b3b170b1ccfa0c09c20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 12 Mar 2009 09:00:34 +0100 Subject: Fixes: Add blitting and multisample API to QGLFramebufferObject. RevBy: Trond Details: Support GL_EXT_framebuffer_multisample and GL_EXT_framebuffer_blit in the QGLFramebufferObject API. --- src/opengl/qgl.cpp | 2 + src/opengl/qgl_p.h | 3 +- src/opengl/qglextensions.cpp | 3 + src/opengl/qglextensions_p.h | 37 +++ src/opengl/qglframebufferobject.cpp | 456 +++++++++++++++++++++++++++++++++--- src/opengl/qglframebufferobject.h | 49 ++++ 6 files changed, 520 insertions(+), 30 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 558897d..fc11d90 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4175,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) { diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 76f3812..8ab73d8 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -330,7 +330,8 @@ public: StencilWrap = 0x00000100, PackedDepthStencil = 0x00000200, NVFloatBuffer = 0x00000400, - PixelBufferObject = 0x00000800 + PixelBufferObject = 0x00000800, + FramebufferBlit = 0x00001000 }; Q_DECLARE_FLAGS(Extensions, Extension) diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index b054fe8..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); diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index fdf0bba..cd35eb0 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -162,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 @@ -220,6 +229,8 @@ struct QGLExtensionFuncs qt_glGetFramebufferAttachmentParameterivEXT = 0; qt_glGenerateMipmapEXT = 0; #endif + qt_glBlitFramebufferEXT = 0; + qt_glRenderbufferStorageMultisampleEXT = 0; qt_glBindBufferARB = 0; qt_glDeleteBuffersARB = 0; @@ -298,6 +309,8 @@ struct QGLExtensionFuncs _glGetFramebufferAttachmentParameterivEXT qt_glGetFramebufferAttachmentParameterivEXT; _glGenerateMipmapEXT qt_glGenerateMipmapEXT; #endif + _glBlitFramebufferEXT qt_glBlitFramebufferEXT; + _glRenderbufferStorageMultisampleEXT qt_glRenderbufferStorageMultisampleEXT; _glBindBufferARB qt_glBindBufferARB; _glDeleteBuffersARB qt_glDeleteBuffersARB; @@ -447,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 @@ -533,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 diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 9134fc6..297ef84 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -67,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: @@ -74,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; @@ -122,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; @@ -130,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::currentContext()); bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); @@ -147,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)) { @@ -175,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, @@ -183,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); @@ -193,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, @@ -213,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); } /*! @@ -264,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} */ @@ -358,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) @@ -445,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); @@ -540,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 { @@ -560,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. @@ -752,4 +1069,85 @@ 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() +{ + 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 -- cgit v0.12 From ee8949183917ae7494cbf0121922d0b68384f90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 11 Mar 2009 12:23:51 +0100 Subject: Fixes: Use the new framebuffer blit/multisample API in the window surface. RevBy: Trond --- src/opengl/qwindowsurface_gl.cpp | 49 +++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 5cd4366..b4a4565 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -436,34 +436,39 @@ 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_PROJECTION); - glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + 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::updateGeometry() @@ -537,12 +542,20 @@ void QGLWindowSurface::updateGeometry() 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(); + 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"; -- cgit v0.12 From b469889f6f9b49f2e52948e3419958b0d8bfc994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 11 Mar 2009 18:46:13 +0100 Subject: Fixes: Prevent QGLFramebufferObject from resetting the current context. RevBy: Trond Details: If there is already an active context we don't need a dummy widget. --- src/opengl/qglframebufferobject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 297ef84..45d4788 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -918,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); } @@ -1079,7 +1080,8 @@ bool QGLFramebufferObject::isBound() const */ bool QGLFramebufferObject::hasOpenGLFramebufferBlit() { - 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::FramebufferBlit); } -- cgit v0.12 From 860498a1e63bff2b5a52accda92256c36ba5c23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 11 Mar 2009 18:47:47 +0100 Subject: Fixes: Use the blit/multisample FBO API in the framebuffer object example. RevBy: Trond --- examples/opengl/framebufferobject/glwidget.cpp | 28 ++++++++++++++++++++++---- examples/opengl/framebufferobject/glwidget.h | 3 ++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/examples/opengl/framebufferobject/glwidget.cpp b/examples/opengl/framebufferobject/glwidget.cpp index d3591d6..3cb3929 100644 --- a/examples/opengl/framebufferobject/glwidget.cpp +++ b/examples/opengl/framebufferobject/glwidget.cpp @@ -53,7 +53,18 @@ GLWidget::GLWidget(QWidget *parent) { setWindowTitle(tr("OpenGL framebuffer objects")); makeCurrent(); - fbo = new QGLFramebufferObject(1024, 1024); + + if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) { + QGLFramebufferObjectFormat format; + format.setSamples(4); + + render_fbo = new QGLFramebufferObject(512, 512, format); + texture_fbo = new QGLFramebufferObject(512, 512); + } else { + render_fbo = new QGLFramebufferObject(1024, 1024); + texture_fbo = render_fbo; + } + rot_x = rot_y = rot_z = 0.0f; scale = 0.1f; anim = new QTimeLine(750, this); @@ -113,7 +124,9 @@ GLWidget::~GLWidget() { delete[] wave; glDeleteLists(tile_list, 1); - delete fbo; + delete texture_fbo; + if (render_fbo != texture_fbo) + delete render_fbo; } void GLWidget::paintEvent(QPaintEvent *) @@ -129,10 +142,16 @@ void GLWidget::draw() saveGLState(); // render the 'bubbles.svg' file into our framebuffer object - QPainter fbo_painter(fbo); + QPainter fbo_painter(render_fbo); svg_renderer->render(&fbo_painter); fbo_painter.end(); + if (render_fbo != texture_fbo) { + QRect rect(0, 0, render_fbo->width(), render_fbo->height()); + QGLFramebufferObject::blitFramebuffer(texture_fbo, rect, + render_fbo, rect); + } + // draw into the GL widget glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); @@ -145,8 +164,9 @@ void GLWidget::draw() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, fbo->texture()); + glBindTexture(GL_TEXTURE_2D, texture_fbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); glEnable(GL_MULTISAMPLE); glEnable(GL_CULL_FACE); diff --git a/examples/opengl/framebufferobject/glwidget.h b/examples/opengl/framebufferobject/glwidget.h index b64cfa8..d97ef78 100644 --- a/examples/opengl/framebufferobject/glwidget.h +++ b/examples/opengl/framebufferobject/glwidget.h @@ -77,6 +77,7 @@ private: QImage logo; QTimeLine *anim; QSvgRenderer *svg_renderer; - QGLFramebufferObject *fbo; + QGLFramebufferObject *render_fbo; + QGLFramebufferObject *texture_fbo; }; -- cgit v0.12 From 855aa89e0ba99f8a0f75d7b31930bab2cefb93f8 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 4 Mar 2009 14:43:58 +0100 Subject: Fixes: make the toNormalizedFillRect function slightly faster RevBy: sroedal --- src/gui/painting/qpaintengine_raster.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 92a196c..3cf618c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1706,12 +1706,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - const int x1 = qRound(rect.x() + aliasedCoordinateDelta); - const int y1 = qRound(rect.y() + aliasedCoordinateDelta); - const int x2 = qRound(rect.right() + aliasedCoordinateDelta); - const int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + int x1 = int(rect.x() + aliasedCoordinateDelta); + int y1 = int(rect.y() + aliasedCoordinateDelta); + int x2 = int(rect.right() + aliasedCoordinateDelta); + int y2 = int(rect.bottom() + aliasedCoordinateDelta); - return QRect(x1, y1, x2 - x1, y2 - y1).normalized(); + if (x2 < x1) + qSwap(x1, x2); + if (y2 < y1) + qSwap(y1, y2); + + return QRect(x1, y1, x2 - x1, y2 - y1); } /*! -- cgit v0.12