src/opengl/qglframebufferobject.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtOpenGL module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include <qdebug.h>
00025 #include <private/qgl_p.h>
00026 #include <private/qpaintengine_opengl_p.h>
00027 #include <qglframebufferobject.h>
00028 #include <qlibrary.h>
00029 #include <qimage.h>
00030 
00031 // #define DEPTH_BUFFER
00032 
00033 #ifndef GL_EXT_framebuffer_object
00034 #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT                    0x0506
00035 #define GL_MAX_RENDERBUFFER_SIZE_EXT                            0x84E8
00036 #define GL_FRAMEBUFFER_BINDING_EXT                              0x8CA6
00037 #define GL_RENDERBUFFER_BINDING_EXT                             0x8CA7
00038 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT               0x8CD0
00039 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT               0x8CD1
00040 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT             0x8CD2
00041 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT     0x8CD3
00042 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT        0x8CD4
00043 #define GL_FRAMEBUFFER_COMPLETE_EXT                             0x8CD5
00044 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT                0x8CD6
00045 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT        0x8CD7
00046 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT      0x8CD8
00047 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT                0x8CD9
00048 #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT                   0x8CDA
00049 #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT               0x8CDB
00050 #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT               0x8CDC
00051 #define GL_FRAMEBUFFER_UNSUPPORTED_EXT                          0x8CDD
00052 #define GL_MAX_COLOR_ATTACHMENTS_EXT                            0x8CDF
00053 #define GL_COLOR_ATTACHMENT0_EXT                                0x8CE0
00054 #define GL_COLOR_ATTACHMENT1_EXT                                0x8CE1
00055 #define GL_COLOR_ATTACHMENT2_EXT                                0x8CE2
00056 #define GL_COLOR_ATTACHMENT3_EXT                                0x8CE3
00057 #define GL_COLOR_ATTACHMENT4_EXT                                0x8CE4
00058 #define GL_COLOR_ATTACHMENT5_EXT                                0x8CE5
00059 #define GL_COLOR_ATTACHMENT6_EXT                                0x8CE6
00060 #define GL_COLOR_ATTACHMENT7_EXT                                0x8CE7
00061 #define GL_COLOR_ATTACHMENT8_EXT                                0x8CE8
00062 #define GL_COLOR_ATTACHMENT9_EXT                                0x8CE9
00063 #define GL_COLOR_ATTACHMENT10_EXT                               0x8CEA
00064 #define GL_COLOR_ATTACHMENT11_EXT                               0x8CEB
00065 #define GL_COLOR_ATTACHMENT12_EXT                               0x8CEC
00066 #define GL_COLOR_ATTACHMENT13_EXT                               0x8CED
00067 #define GL_COLOR_ATTACHMENT14_EXT                               0x8CEE
00068 #define GL_COLOR_ATTACHMENT15_EXT                               0x8CEF
00069 #define GL_DEPTH_ATTACHMENT_EXT                                 0x8D00
00070 #define GL_STENCIL_ATTACHMENT_EXT                               0x8D20
00071 #define GL_FRAMEBUFFER_EXT                                      0x8D40
00072 #define GL_RENDERBUFFER_EXT                                     0x8D41
00073 #define GL_RENDERBUFFER_WIDTH_EXT                               0x8D42
00074 #define GL_RENDERBUFFER_HEIGHT_EXT                              0x8D43
00075 #define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT                     0x8D44
00076 #define GL_STENCIL_INDEX_EXT                                    0x8D45
00077 #define GL_STENCIL_INDEX1_EXT                                   0x8D46
00078 #define GL_STENCIL_INDEX4_EXT                                   0x8D47
00079 #define GL_STENCIL_INDEX8_EXT                                   0x8D48
00080 #define GL_STENCIL_INDEX16_EXT                                  0x8D49
00081 #define GL_RENDERBUFFER_RED_SIZE_EXT                            0x8D50
00082 #define GL_RENDERBUFFER_GREEN_SIZE_EXT                          0x8D51
00083 #define GL_RENDERBUFFER_BLUE_SIZE_EXT                           0x8D52
00084 #define GL_RENDERBUFFER_ALPHA_SIZE_EXT                          0x8D53
00085 #define GL_RENDERBUFFER_DEPTH_SIZE_EXT                          0x8D54
00086 #define GL_RENDERBUFFER_STENCIL_SIZE_EXT                        0x8D55
00087 #endif
00088 
00089 // ### hm. should be part of the GL 1.2 spec..
00090 #ifndef GL_CLAMP_TO_EDGE
00091 #define GL_CLAMP_TO_EDGE                  0x812F
00092 #endif
00093 
00094 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
00095 
00096 #define QGL_FUNC_CONTEXT
00097 
00098 PFNGLISRENDERBUFFEREXTPROC qt_glIsRenderbufferEXT;
00099 PFNGLBINDRENDERBUFFEREXTPROC qt_glBindRenderbufferEXT;
00100 PFNGLDELETERENDERBUFFERSEXTPROC qt_glDeleteRenderbuffersEXT;
00101 PFNGLGENRENDERBUFFERSEXTPROC qt_glGenRenderbuffersEXT;
00102 PFNGLRENDERBUFFERSTORAGEEXTPROC qt_glRenderbufferStorageEXT;
00103 PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC qt_glGetRenderbufferParameterivEXT;
00104 PFNGLISFRAMEBUFFEREXTPROC qt_glIsFramebufferEXT;
00105 PFNGLBINDFRAMEBUFFEREXTPROC qt_glBindFramebufferEXT;
00106 PFNGLDELETEFRAMEBUFFERSEXTPROC qt_glDeleteFramebuffersEXT;
00107 PFNGLGENFRAMEBUFFERSEXTPROC qt_glGenFramebuffersEXT;
00108 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC qt_glCheckFramebufferStatusEXT;
00109 PFNGLFRAMEBUFFERTEXTURE1DEXTPROC qt_glFramebufferTexture1DEXT;
00110 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC qt_glFramebufferTexture2DEXT;
00111 PFNGLFRAMEBUFFERTEXTURE3DEXTPROC qt_glFramebufferTexture3DEXT;
00112 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC qt_glFramebufferRenderbufferEXT;
00113 PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC qt_glGetFramebufferAttachmentParameterivEXT;
00114 PFNGLGENERATEMIPMAPEXTPROC qt_glGenerateMipmapEXT;
00115 
00116 #define glIsRenderbufferEXT qt_glIsRenderbufferEXT
00117 #define glBindRenderbufferEXT qt_glBindRenderbufferEXT
00118 #define glDeleteRenderbuffersEXT qt_glDeleteRenderbuffersEXT
00119 #define glGenRenderbuffersEXT qt_glGenRenderbuffersEXT
00120 #define glRenderbufferStorageEXT qt_glRenderbufferStorageEXT
00121 #define glGetRenderbufferParameterivEXT qt_glGetRenderbufferParameterivEXT
00122 #define glIsFramebufferEXT qt_glIsFramebufferEXT
00123 #define glBindFramebufferEXT qt_glBindFramebufferEXT
00124 #define glDeleteFramebuffersEXT qt_glDeleteFramebuffersEXT
00125 #define glGenFramebuffersEXT qt_glGenFramebuffersEXT
00126 #define glCheckFramebufferStatusEXT qt_glCheckFramebufferStatusEXT
00127 #define glFramebufferTexture1DEXT qt_glFramebufferTexture1DEXT
00128 #define glFramebufferTexture2DEXT qt_glFramebufferTexture2DEXT
00129 #define glFramebufferTexture3DEXT qt_glFramebufferTexture3DEXT
00130 #define glFramebufferRenderbufferEXT qt_glFramebufferRenderbufferEXT
00131 #define glGetFramebufferAttachmentParameterivEXT qt_glGetFramebufferAttachmentParameterivEXT
00132 #define glGenerateMipmapEXT qt_glGenerateMipmapEXT
00133 
00134 static bool qt_resolve_framebufferobject_extensions(QGLContext *)
00135 {
00136     static bool resolved = false;
00137     if (resolved && qt_glIsRenderbufferEXT)
00138         return true;
00139     else if (resolved)
00140         return false;
00141 
00142 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
00143     QLibrary lib(QLatin1String("GL"));
00144 #else // Q_WS_MAC
00145     QLibrary lib(QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"));
00146 #endif
00147 
00148     qt_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) lib.resolve("glIsRenderbufferEXT");
00149     qt_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) lib.resolve("glBindRenderbufferEXT");
00150     qt_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) lib.resolve("glDeleteRenderbuffersEXT");
00151     qt_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) lib.resolve("glGenRenderbuffersEXT");
00152     qt_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) lib.resolve("glRenderbufferStorageEXT");
00153     qt_glGetRenderbufferParameterivEXT =
00154         (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) lib.resolve("glGetRenderbufferParameterivEXT");
00155     qt_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) lib.resolve("glIsFramebufferEXT");
00156     qt_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) lib.resolve("glBindFramebufferEXT");
00157     qt_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) lib.resolve("glDeleteFramebuffersEXT");
00158     qt_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) lib.resolve("glGenFramebuffersEXT");
00159     qt_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) lib.resolve("glCheckFramebufferStatusEXT");
00160     qt_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) lib.resolve("glFramebufferTexture1DEXT");
00161     qt_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) lib.resolve("glFramebufferTexture2DEXT");
00162     qt_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) lib.resolve("glFramebufferTexture3DEXT");
00163     qt_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) lib.resolve("glFramebufferRenderbufferEXT");
00164     qt_glGetFramebufferAttachmentParameterivEXT =
00165         (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) lib.resolve("glGetFramebufferAttachmentParameterivEXT");
00166     qt_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) lib.resolve("glGenerateMipmapEXT");
00167     resolved = true;
00168     return qt_glIsRenderbufferEXT;
00169 }
00170 #elif defined(Q_WS_WIN)
00171 
00172 #define QGL_FUNC_CONTEXT QGLContext *ctx = d_ptr->ctx;
00173 
00174 #define glIsRenderbufferEXT ctx->d_ptr->qt_glIsRenderbufferEXT
00175 #define glBindRenderbufferEXT ctx->d_ptr->qt_glBindRenderbufferEXT
00176 #define glDeleteRenderbuffersEXT ctx->d_ptr->qt_glDeleteRenderbuffersEXT
00177 #define glGenRenderbuffersEXT ctx->d_ptr->qt_glGenRenderbuffersEXT
00178 #define glRenderbufferStorageEXT ctx->d_ptr->qt_glRenderbufferStorageEXT
00179 #define glGetRenderbufferParameterivEXT ctx->d_ptr->qt_glGetRenderbufferParameterivEXT
00180 #define glIsFramebufferEXT ctx->d_ptr->qt_glIsFramebufferEXT
00181 #define glBindFramebufferEXT ctx->d_ptr->qt_glBindFramebufferEXT
00182 #define glDeleteFramebuffersEXT ctx->d_ptr->qt_glDeleteFramebuffersEXT
00183 #define glGenFramebuffersEXT ctx->d_ptr->qt_glGenFramebuffersEXT
00184 #define glCheckFramebufferStatusEXT ctx->d_ptr->qt_glCheckFramebufferStatusEXT
00185 #define glFramebufferTexture1DEXT ctx->d_ptr->qt_glFramebufferTexture1DEXT
00186 #define glFramebufferTexture2DEXT ctx->d_ptr->qt_glFramebufferTexture2DEXT
00187 #define glFramebufferTexture3DEXT ctx->d_ptr->qt_glFramebufferTexture3DEXT
00188 #define glFramebufferRenderbufferEXT ctx->d_ptr->qt_glFramebufferRenderbufferEXT
00189 #define glGetFramebufferAttachmentParameterivEXT ctx->d_ptr->qt_glGetFramebufferAttachmentParameterivEXT
00190 #define glGenerateMipmapEXT ctx->d_ptr->qt_glGenerateMipmapEXT
00191 
00192 bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
00193 {
00194     if (glIsRenderbufferEXT != 0)
00195   return true;
00196 
00197     if (ctx == 0) {
00198   qWarning("QGLFramebufferObject: Unable to resolve framebuffer object extensions -"
00199      " make sure there is a current context when creating the framebuffer object.");
00200   return false;
00201     }
00202 
00203     glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) wglGetProcAddress("glIsRenderbufferEXT");
00204     glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) wglGetProcAddress("glBindRenderbufferEXT");
00205     glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) wglGetProcAddress("glDeleteRenderbuffersEXT");
00206     glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) wglGetProcAddress("glGenRenderbuffersEXT");
00207     glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) wglGetProcAddress("glRenderbufferStorageEXT");
00208     glGetRenderbufferParameterivEXT =
00209         (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) wglGetProcAddress("glGetRenderbufferParameterivEXT");
00210     glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) wglGetProcAddress("glIsFramebufferEXT");
00211     glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) wglGetProcAddress("glBindFramebufferEXT");
00212     glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) wglGetProcAddress("glDeleteFramebuffersEXT");
00213     glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) wglGetProcAddress("glGenFramebuffersEXT");
00214     glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) wglGetProcAddress("glCheckFramebufferStatusEXT");
00215     glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) wglGetProcAddress("glFramebufferTexture1DEXT");
00216     glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) wglGetProcAddress("glFramebufferTexture2DEXT");
00217     glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) wglGetProcAddress("glFramebufferTexture3DEXT");
00218     glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) wglGetProcAddress("glFramebufferRenderbufferEXT");
00219     glGetFramebufferAttachmentParameterivEXT =
00220         (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT");
00221     glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) wglGetProcAddress("glGenerateMipmapEXT");
00222     return glIsRenderbufferEXT;
00223 }
00224 #endif
00225 
00226 #define QT_CHECK_GLERROR()                                \
00227 {                                                         \
00228     GLenum err = glGetError();                            \
00229     if (err != GL_NO_ERROR) {                             \
00230         qDebug("[%s line %d] GL Error: %d",               \
00231                __FILE__, __LINE__, err);                  \
00232     }                                                     \
00233 }
00234 
00235 class QGLFramebufferObjectPrivate
00236 {
00237 public:
00238     QGLFramebufferObjectPrivate() : valid(false), ctx(0) {}
00239     ~QGLFramebufferObjectPrivate() {}
00240 
00241     void init(const QSize& sz, GLenum texture_target);
00242     bool checkFramebufferStatus() const;
00243     GLuint texture;
00244     GLuint fbo;
00245     GLuint depth_buffer;
00246     GLenum target;
00247     QSize size;
00248     uint valid : 1;
00249     QGLContext *ctx; // for Windows extension ptrs
00250 };
00251 
00252 bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
00253 {
00254     GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00255     switch(status) {
00256     case GL_NO_ERROR:
00257     case GL_FRAMEBUFFER_COMPLETE_EXT:
00258         return true;
00259         break;
00260     case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00261         qDebug("QGLFramebufferObject: Unsupported framebuffer format.");
00262         break;
00263     case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00264         qDebug("QGLFramebufferObject: Framebuffer incomplete attachment.");
00265         break;
00266     case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00267         qDebug("QGLFramebufferObject: Framebuffer incomplete, missing attachment.");
00268         break;
00269 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
00270     case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
00271         qDebug("QGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");
00272         break;
00273 #endif
00274     case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00275         qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");
00276         break;
00277     case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00278         qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");
00279         break;
00280     case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00281         qDebug("QGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
00282         break;
00283     case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00284         qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
00285         break;
00286     default:
00287         qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
00288         break;
00289     }
00290     return false;
00291 }
00292 
00293 void QGLFramebufferObjectPrivate::init(const QSize &sz, GLenum texture_target)
00294 {
00295     ctx = const_cast<QGLContext *>(QGLContext::currentContext());
00296     bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
00297     if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
00298         return;
00299 
00300     size = sz;
00301     target = texture_target;
00302     // texture dimensions
00303 
00304     glGetError(); // reset error state
00305     glGenFramebuffersEXT(1, &fbo);
00306     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
00307 
00308     QT_CHECK_GLERROR();
00309     // init texture
00310     glGenTextures(1, &texture);
00311     glBindTexture(target, texture);
00312 #ifndef Q_WS_QWS
00313     glTexImage2D(target, 0, GL_RGBA8, size.width(), size.height(), 0,
00314                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00315 #else
00316     glTexImage2D(target, 0, GL_RGBA, size.width(), size.height(), 0,
00317                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00318 #endif
00319     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00320     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00321     glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00322     glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00323 
00324     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
00325                               target, texture, 0);
00326 
00327     QT_CHECK_GLERROR();
00328     valid = checkFramebufferStatus();
00329 
00330 #ifdef DEPTH_BUFFER
00331     // depth buffer
00332     glGenRenderbuffersEXT(1, &depth_buffer);
00333     Q_ASSERT(!glIsRenderbufferEXT(depth_buffer));
00334     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_buffer);
00335     Q_ASSERT(glIsRenderbufferEXT(depth_buffer));
00336     glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
00337     int i = 0;
00338     glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
00339     glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
00340                                  GL_RENDERBUFFER_EXT, depth_buffer);
00341 
00342 #endif
00343     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00344     checkFramebufferStatus();
00345     QT_CHECK_GLERROR();
00346 }
00347 
00422 QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
00423     : d_ptr(new QGLFramebufferObjectPrivate)
00424 {
00425     Q_D(QGLFramebufferObject);
00426     d->init(size, target);
00427 }
00428 
00429 
00437 QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)
00438     : d_ptr(new QGLFramebufferObjectPrivate)
00439 {
00440     Q_D(QGLFramebufferObject);
00441     d->init(QSize(width, height), target);
00442 }
00443 
00449 QGLFramebufferObject::~QGLFramebufferObject()
00450 {
00451     Q_D(QGLFramebufferObject);
00452     QGL_FUNC_CONTEXT;
00453 
00454     if (isValid()) {
00455   glDeleteTextures(1, &d->texture);
00456 #ifdef DEPTH_BUFFER
00457   glDeleteRenderbuffersEXT(1, &d->depth_buffer);
00458 #endif
00459   glDeleteFramebuffersEXT(1, &d->fbo);
00460     }
00461     delete d_ptr;
00462 }
00463 
00474 bool QGLFramebufferObject::isValid() const
00475 {
00476     Q_D(const QGLFramebufferObject);
00477     return d->valid;
00478 }
00479 
00487 bool QGLFramebufferObject::bind()
00488 {
00489     if (!isValid())
00490   return false;
00491     Q_D(QGLFramebufferObject);
00492     QGL_FUNC_CONTEXT;
00493     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->fbo);
00494     return d->checkFramebufferStatus();
00495 }
00496 
00504 bool QGLFramebufferObject::release()
00505 {
00506     if (!isValid())
00507   return false;
00508     Q_D(QGLFramebufferObject);
00509     QGL_FUNC_CONTEXT;
00510     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00511     return d->checkFramebufferStatus();
00512 }
00513 
00521 GLuint QGLFramebufferObject::texture() const
00522 {
00523     Q_D(const QGLFramebufferObject);
00524     return d->texture;
00525 }
00526 
00533 QSize QGLFramebufferObject::size() const
00534 {
00535     Q_D(const QGLFramebufferObject);
00536     return d->size;
00537 }
00538 
00544 QImage QGLFramebufferObject::toImage() const
00545 {
00546     Q_D(const QGLFramebufferObject);
00547     if (!d->valid)
00548         return QImage();
00549 
00550     const_cast<QGLFramebufferObject *>(this)->bind();
00551     QImage::Format image_format = QImage::Format_RGB32;
00552     if (d->ctx->format().alpha())
00553         image_format = QImage::Format_ARGB32_Premultiplied;
00554     QImage img(d->size, image_format);
00555     int w = d->size.width();
00556     int h = d->size.height();
00557     // ### fix the read format so that we don't have to do all the byte swapping
00558     glReadPixels(0, 0, d->size.width(), d->size.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
00559     if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
00560   // OpenGL gives RGBA; Qt wants ARGB
00561   uint *p = (uint*)img.bits();
00562   uint *end = p + w*h;
00563   if (1) {
00564       while (p < end) {
00565     uint a = *p << 24;
00566     *p = (*p >> 8) | a;
00567     p++;
00568       }
00569   } else {
00570       while (p < end) {
00571     *p = 0xFF000000 | (*p>>8);
00572     ++p;
00573       }
00574   }
00575     } else {
00576   // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
00577   img = img.rgbSwapped();
00578     }
00579     const_cast<QGLFramebufferObject *>(this)->release();
00580     return img.mirrored();
00581 }
00582 
00583 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
00584 
00585 
00586 QPaintEngine *QGLFramebufferObject::paintEngine() const
00587 {
00588     return qt_buffer_paintengine();
00589 }
00590 
00597 bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
00598 {
00599     QGLWidget dmy; // needed to detect and init the QGLExtensions object
00600     return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
00601 }
00602 
00603 extern int qt_defaultDpi();
00604 
00606 int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
00607 {
00608     Q_D(const QGLFramebufferObject);
00609 
00610     float dpmx = qt_defaultDpi()*100./2.54;
00611     float dpmy = qt_defaultDpi()*100./2.54;
00612     int w = d->size.width();
00613     int h = d->size.height();
00614     switch (metric) {
00615     case PdmWidth:
00616         return w;
00617 
00618     case PdmHeight:
00619         return h;
00620 
00621     case PdmWidthMM:
00622         return qRound(w * 1000 / dpmx);
00623 
00624     case PdmHeightMM:
00625         return qRound(h * 1000 / dpmy);
00626 
00627     case PdmNumColors:
00628         return 0;
00629 
00630     case PdmDepth:
00631         return 32;//d->depth;
00632 
00633     case PdmDpiX:
00634         return (int)(dpmx * 0.0254);
00635 
00636     case PdmDpiY:
00637         return (int)(dpmy * 0.0254);
00638 
00639     case PdmPhysicalDpiX:
00640         return (int)(dpmx * 0.0254);
00641 
00642     case PdmPhysicalDpiY:
00643         return (int)(dpmy * 0.0254);
00644 
00645     default:
00646         qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
00647         break;
00648     }
00649     return 0;
00650 }
00651 
00661 GLuint QGLFramebufferObject::handle() const
00662 {
00663     Q_D(const QGLFramebufferObject);
00664     return d->fbo;
00665 }
00666 

Generated on Thu Mar 15 11:57:23 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1