00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00061 #include <qglpixelbuffer.h>
00062 #include <private/qglpixelbuffer_p.h>
00063 #include <private/qpaintengine_opengl_p.h>
00064 #include <qimage.h>
00065
00066
00067 void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
00068 {
00069 Q_Q(QGLPixelBuffer);
00070 if(init(size, format, shareWidget)) {
00071 req_size = size;
00072 req_format = format;
00073 req_shareWidget = shareWidget;
00074 invalid = false;
00075 qctx = new QGLContext(format);
00076 qctx->d_func()->sharing = (shareWidget != 0);
00077 qctx->d_func()->paintDevice = q;
00078 }
00079 }
00080
00094 QGLPixelBuffer::QGLPixelBuffer(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
00095 : d_ptr(new QGLPixelBufferPrivate)
00096 {
00097 Q_D(QGLPixelBuffer);
00098 d->common_init(size, format, shareWidget);
00099 }
00100
00101
00116 QGLPixelBuffer::QGLPixelBuffer(int width, int height, const QGLFormat &format, QGLWidget *shareWidget)
00117 : d_ptr(new QGLPixelBufferPrivate)
00118 {
00119 Q_D(QGLPixelBuffer);
00120 d->common_init(QSize(width, height), format, shareWidget);
00121 }
00122
00123
00128 QGLPixelBuffer::~QGLPixelBuffer()
00129 {
00130 Q_D(QGLPixelBuffer);
00131
00132
00133 extern void qgl_cleanup_glyph_cache(QGLContext *);
00134
00135 QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
00136 makeCurrent();
00137 qgl_cleanup_glyph_cache(d->qctx);
00138 if (current)
00139 current->makeCurrent();
00140 d->cleanup();
00141 delete d->qctx;
00142 delete d_ptr;
00143 }
00144
00168 #if defined(Q_WS_X11) || defined(Q_WS_WIN)
00169 GLuint QGLPixelBuffer::generateDynamicTexture() const
00170 {
00171 Q_D(const QGLPixelBuffer);
00172 GLuint texture;
00173 glGenTextures(1, &texture);
00174 glBindTexture(GL_TEXTURE_2D, texture);
00175 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_FLOAT, 0);
00176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00178 return texture;
00179 }
00180 #endif
00181
00255 void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
00256 {
00257 Q_D(const QGLPixelBuffer);
00258 if (d->invalid)
00259 return;
00260 glBindTexture(GL_TEXTURE_2D, texture_id);
00261 #ifndef Q_WS_QWS
00262 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0);
00263 #else
00264 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
00265 #endif
00266 }
00267
00271 QSize QGLPixelBuffer::size() const
00272 {
00273 Q_D(const QGLPixelBuffer);
00274 return d->req_size;
00275 }
00276
00280 QImage QGLPixelBuffer::toImage() const
00281 {
00282 Q_D(const QGLPixelBuffer);
00283 if (d->invalid)
00284 return QImage();
00285
00286 const_cast<QGLPixelBuffer *>(this)->makeCurrent();
00287 QImage::Format image_format = QImage::Format_RGB32;
00288 if (format().alpha())
00289 image_format = QImage::Format_ARGB32_Premultiplied;
00290 QImage img(d->req_size, image_format);
00291 int w = d->req_size.width();
00292 int h = d->req_size.height();
00293 glReadPixels(0, 0, d->req_size.width(), d->req_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
00294 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
00295
00296 uint *p = (uint*)img.bits();
00297 uint *end = p + w*h;
00298 if (1) {
00299 while (p < end) {
00300 uint a = *p << 24;
00301 *p = (*p >> 8) | a;
00302 p++;
00303 }
00304 } else {
00305 while (p < end) {
00306 *p = 0xFF000000 | (*p>>8);
00307 ++p;
00308 }
00309 }
00310 } else {
00311
00312 img = img.rgbSwapped();
00313 }
00314 return img.mirrored();
00315 }
00316
00320 Qt::HANDLE QGLPixelBuffer::handle() const
00321 {
00322 Q_D(const QGLPixelBuffer);
00323 if (d->invalid)
00324 return 0;
00325 return d->pbuf;
00326 }
00327
00331 bool QGLPixelBuffer::isValid() const
00332 {
00333 Q_D(const QGLPixelBuffer);
00334 return !d->invalid;
00335 }
00336
00337 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
00338
00339
00340 QPaintEngine *QGLPixelBuffer::paintEngine() const
00341 {
00342 return qt_buffer_paintengine();
00343 }
00344
00345 extern int qt_defaultDpi();
00346
00348 int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
00349 {
00350 Q_D(const QGLPixelBuffer);
00351
00352 float dpmx = qt_defaultDpi()*100./2.54;
00353 float dpmy = qt_defaultDpi()*100./2.54;
00354 int w = d->req_size.width();
00355 int h = d->req_size.height();
00356 switch (metric) {
00357 case PdmWidth:
00358 return w;
00359
00360 case PdmHeight:
00361 return h;
00362
00363 case PdmWidthMM:
00364 return qRound(w * 1000 / dpmx);
00365
00366 case PdmHeightMM:
00367 return qRound(h * 1000 / dpmy);
00368
00369 case PdmNumColors:
00370 return 0;
00371
00372 case PdmDepth:
00373 return 32;
00374
00375 case PdmDpiX:
00376 return (int)(dpmx * 0.0254);
00377
00378 case PdmDpiY:
00379 return (int)(dpmy * 0.0254);
00380
00381 case PdmPhysicalDpiX:
00382 return (int)(dpmx * 0.0254);
00383
00384 case PdmPhysicalDpiY:
00385 return (int)(dpmy * 0.0254);
00386
00387 default:
00388 qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
00389 break;
00390 }
00391 return 0;
00392 }
00393
00405 GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target)
00406 {
00407 Q_D(QGLPixelBuffer);
00408 #ifndef Q_WS_QWS
00409 return d->qctx->bindTexture(image, target, GL_RGBA8);
00410 #else
00411 return d->qctx->bindTexture(image, target, GL_RGBA);
00412 #endif
00413 }
00414
00415
00424 GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target)
00425 {
00426 Q_D(QGLPixelBuffer);
00427 #ifndef Q_WS_QWS
00428 return d->qctx->bindTexture(pixmap, target, GL_RGBA8);
00429 #else
00430 return d->qctx->bindTexture(pixmap, target, GL_RGBA);
00431 #endif
00432 }
00433
00443 GLuint QGLPixelBuffer::bindTexture(const QString &fileName)
00444 {
00445 Q_D(QGLPixelBuffer);
00446 return d->qctx->bindTexture(fileName);
00447 }
00448
00454 void QGLPixelBuffer::deleteTexture(GLuint texture_id)
00455 {
00456 Q_D(QGLPixelBuffer);
00457 d->qctx->deleteTexture(texture_id);
00458 }
00459
00464 QGLFormat QGLPixelBuffer::format() const
00465 {
00466 Q_D(const QGLPixelBuffer);
00467 return d->format;
00468 }
00469