source: trunk/src/opengl/qpixmapdata_gl.cpp@ 780

Last change on this file since 780 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 20.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qpixmap.h"
43#include "qglframebufferobject.h"
44
45#include <private/qpaintengine_raster_p.h>
46
47#include "qpixmapdata_gl_p.h"
48
49#include <private/qgl_p.h>
50#include <private/qdrawhelper_p.h>
51#include <private/qimage_p.h>
52
53#include <private/qpaintengineex_opengl2_p.h>
54
55#include <qdesktopwidget.h>
56#include <qfile.h>
57#include <qimagereader.h>
58
59QT_BEGIN_NAMESPACE
60
61extern QGLWidget* qt_gl_share_widget();
62
63/*!
64 \class QGLFramebufferObjectPool
65 \since 4.6
66
67 \brief The QGLFramebufferObject class provides a pool of framebuffer
68 objects for offscreen rendering purposes.
69
70 When requesting an FBO of a given size and format, an FBO of the same
71 format and a size at least as big as the requested size will be returned.
72
73 \internal
74*/
75
76static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
77{
78 return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
79}
80
81extern int qt_next_power_of_two(int v);
82
83static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
84{
85#ifdef QT_OPENGL_ES_2
86 QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
87 if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
88 return rounded;
89#endif
90 return sz;
91}
92
93
94QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
95{
96 QGLFramebufferObject *chosen = 0;
97 QGLFramebufferObject *candidate = 0;
98 for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
99 QGLFramebufferObject *fbo = m_fbos.at(i);
100
101 if (strictSize) {
102 if (fbo->size() == requestSize && fbo->format() == requestFormat) {
103 chosen = fbo;
104 break;
105 } else {
106 continue;
107 }
108 }
109
110 if (fbo->format() == requestFormat) {
111 // choose the fbo with a matching format and the closest size
112 if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
113 candidate = fbo;
114 }
115
116 if (candidate) {
117 m_fbos.removeOne(candidate);
118
119 const QSize fboSize = candidate->size();
120 QSize sz = fboSize;
121
122 if (sz.width() < requestSize.width())
123 sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
124 if (sz.height() < requestSize.height())
125 sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
126
127 // wasting too much space?
128 if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
129 sz = requestSize;
130
131 if (sz != fboSize) {
132 delete candidate;
133 candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
134 }
135
136 chosen = candidate;
137 }
138 }
139
140 if (!chosen) {
141 if (strictSize)
142 chosen = new QGLFramebufferObject(requestSize, requestFormat);
143 else
144 chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
145 }
146
147 if (!chosen->isValid()) {
148 delete chosen;
149 chosen = 0;
150 }
151
152 return chosen;
153}
154
155void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
156{
157 if (fbo)
158 m_fbos << fbo;
159}
160
161
162QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
163{
164 return data->paintEngine();
165}
166
167void QGLPixmapGLPaintDevice::beginPaint()
168{
169 if (!data->isValid())
170 return;
171
172 // QGLPaintDevice::beginPaint will store the current binding and replace
173 // it with m_thisFBO:
174 m_thisFBO = data->m_renderFbo->handle();
175 QGLPaintDevice::beginPaint();
176
177 Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
178
179 // QPixmap::fill() is deferred until now, where we actually need to do the fill:
180 if (data->needsFill()) {
181 const QColor &c = data->fillColor();
182 float alpha = c.alphaF();
183 glDisable(GL_SCISSOR_TEST);
184 glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
185 glClear(GL_COLOR_BUFFER_BIT);
186 }
187 else if (!data->isUninitialized()) {
188 // If the pixmap (GL Texture) has valid content (it has been
189 // uploaded from an image or rendered into before), we need to
190 // copy it from the texture to the render FBO.
191
192 glDisable(GL_DEPTH_TEST);
193 glDisable(GL_SCISSOR_TEST);
194 glDisable(GL_BLEND);
195
196#if !defined(QT_OPENGL_ES_2)
197 glMatrixMode(GL_MODELVIEW);
198 glLoadIdentity();
199
200 glMatrixMode(GL_PROJECTION);
201 glLoadIdentity();
202 glOrtho(0, data->width(), data->height(), 0, -999999, 999999);
203#endif
204
205 glViewport(0, 0, data->width(), data->height());
206
207 // Pass false to bind so it doesn't copy the FBO into the texture!
208 context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false));
209 }
210}
211
212void QGLPixmapGLPaintDevice::endPaint()
213{
214 if (!data->isValid())
215 return;
216
217 data->copyBackFromRenderFbo(false);
218
219 // Base's endPaint will restore the previous FBO binding
220 QGLPaintDevice::endPaint();
221
222 qgl_fbo_pool()->release(data->m_renderFbo);
223 data->m_renderFbo = 0;
224}
225
226QGLContext* QGLPixmapGLPaintDevice::context() const
227{
228 data->ensureCreated();
229 return data->m_ctx;
230}
231
232QSize QGLPixmapGLPaintDevice::size() const
233{
234 return data->size();
235}
236
237bool QGLPixmapGLPaintDevice::alphaRequested() const
238{
239 return data->m_hasAlpha;
240}
241
242void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
243{
244 data = d;
245}
246
247static int qt_gl_pixmap_serial = 0;
248
249QGLPixmapData::QGLPixmapData(PixelType type)
250 : QPixmapData(type, OpenGLClass)
251 , m_renderFbo(0)
252 , m_engine(0)
253 , m_ctx(0)
254 , m_dirty(false)
255 , m_hasFillColor(false)
256 , m_hasAlpha(false)
257{
258 setSerialNumber(++qt_gl_pixmap_serial);
259 m_glDevice.setPixmapData(this);
260}
261
262QGLPixmapData::~QGLPixmapData()
263{
264 QGLWidget *shareWidget = qt_gl_share_widget();
265 if (!shareWidget)
266 return;
267
268 delete m_engine;
269
270 if (m_texture.id) {
271 QGLShareContextScope ctx(shareWidget->context());
272 glDeleteTextures(1, &m_texture.id);
273 }
274}
275
276QPixmapData *QGLPixmapData::createCompatiblePixmapData() const
277{
278 return new QGLPixmapData(pixelType());
279}
280
281bool QGLPixmapData::isValid() const
282{
283 return w > 0 && h > 0;
284}
285
286bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
287{
288 if (ctx == m_ctx)
289 return true;
290
291 const QGLContext *share_ctx = qt_gl_share_widget()->context();
292 return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx);
293}
294
295void QGLPixmapData::resize(int width, int height)
296{
297 if (width == w && height == h)
298 return;
299
300 if (width <= 0 || height <= 0) {
301 width = 0;
302 height = 0;
303 }
304
305 w = width;
306 h = height;
307 is_null = (w <= 0 || h <= 0);
308 d = pixelType() == QPixmapData::PixmapType ? 32 : 1;
309
310 if (m_texture.id) {
311 QGLShareContextScope ctx(qt_gl_share_widget()->context());
312 glDeleteTextures(1, &m_texture.id);
313 m_texture.id = 0;
314 }
315
316 m_source = QImage();
317 m_dirty = isValid();
318 setSerialNumber(++qt_gl_pixmap_serial);
319}
320
321void QGLPixmapData::ensureCreated() const
322{
323 if (!m_dirty)
324 return;
325
326 m_dirty = false;
327
328 QGLShareContextScope ctx(qt_gl_share_widget()->context());
329 m_ctx = ctx;
330
331 const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
332#ifdef QT_OPENGL_ES_2
333 const GLenum external_format = internal_format;
334#else
335 const GLenum external_format = qt_gl_preferredTextureFormat();
336#endif
337 const GLenum target = GL_TEXTURE_2D;
338
339 if (!m_texture.id) {
340 glGenTextures(1, &m_texture.id);
341 glBindTexture(target, m_texture.id);
342 glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0);
343 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
344 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
345 }
346
347 if (!m_source.isNull()) {
348 if (external_format == GL_RGB) {
349 const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true);
350
351 glBindTexture(target, m_texture.id);
352 glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
353 GL_UNSIGNED_BYTE, tx.bits());
354 } else {
355 const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
356
357 glBindTexture(target, m_texture.id);
358 glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
359 GL_UNSIGNED_BYTE, tx.bits());
360 }
361
362 if (useFramebufferObjects())
363 m_source = QImage();
364 }
365
366 m_texture.options &= ~QGLContext::MemoryManagedBindOption;
367}
368
369void QGLPixmapData::fromImage(const QImage &image,
370 Qt::ImageConversionFlags /*flags*/)
371{
372 if (image.size() == QSize(w, h))
373 setSerialNumber(++qt_gl_pixmap_serial);
374 resize(image.width(), image.height());
375
376 if (pixelType() == BitmapType) {
377 m_source = image.convertToFormat(QImage::Format_MonoLSB);
378
379 } else {
380 QImage::Format format = QImage::Format_RGB32;
381 if (qApp->desktop()->depth() == 16)
382 format = QImage::Format_RGB16;
383
384 if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
385 format = QImage::Format_ARGB32_Premultiplied;;
386
387 m_source = image.convertToFormat(format);
388 }
389
390 m_dirty = true;
391 m_hasFillColor = false;
392
393 m_hasAlpha = m_source.hasAlphaChannel();
394 w = image.width();
395 h = image.height();
396 is_null = (w <= 0 || h <= 0);
397 d = m_source.depth();
398
399 if (m_texture.id) {
400 QGLShareContextScope ctx(qt_gl_share_widget()->context());
401 glDeleteTextures(1, &m_texture.id);
402 m_texture.id = 0;
403 }
404}
405
406bool QGLPixmapData::fromFile(const QString &filename, const char *format,
407 Qt::ImageConversionFlags flags)
408{
409 if (pixelType() == QPixmapData::BitmapType)
410 return QPixmapData::fromFile(filename, format, flags);
411 QFile file(filename);
412 if (!file.open(QIODevice::ReadOnly))
413 return false;
414 QByteArray data = file.peek(64);
415 bool alpha;
416 if (m_texture.canBindCompressedTexture
417 (data.constData(), data.size(), format, &alpha)) {
418 resize(0, 0);
419 data = file.readAll();
420 file.close();
421 QGLShareContextScope ctx(qt_gl_share_widget()->context());
422 QSize size = m_texture.bindCompressedTexture
423 (data.constData(), data.size(), format);
424 if (!size.isEmpty()) {
425 w = size.width();
426 h = size.height();
427 is_null = false;
428 d = 32;
429 m_hasAlpha = alpha;
430 m_source = QImage();
431 m_dirty = isValid();
432 return true;
433 }
434 return false;
435 }
436 fromImage(QImageReader(&file, format).read(), flags);
437 return !isNull();
438}
439
440bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
441 Qt::ImageConversionFlags flags)
442{
443 bool alpha;
444 const char *buf = reinterpret_cast<const char *>(buffer);
445 if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
446 resize(0, 0);
447 QGLShareContextScope ctx(qt_gl_share_widget()->context());
448 QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
449 if (!size.isEmpty()) {
450 w = size.width();
451 h = size.height();
452 is_null = false;
453 d = 32;
454 m_hasAlpha = alpha;
455 m_source = QImage();
456 m_dirty = isValid();
457 return true;
458 }
459 }
460 return QPixmapData::fromData(buffer, len, format, flags);
461}
462
463bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
464{
465 Q_UNUSED(dx);
466 Q_UNUSED(dy);
467 Q_UNUSED(rect);
468 return false;
469}
470
471void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
472{
473 if (data->classId() != QPixmapData::OpenGLClass) {
474 QPixmapData::copy(data, rect);
475 return;
476 }
477
478 // can be optimized to do a framebuffer blit or similar ...
479 QPixmapData::copy(data, rect);
480}
481
482void QGLPixmapData::fill(const QColor &color)
483{
484 if (!isValid())
485 return;
486
487 bool hasAlpha = color.alpha() != 255;
488 if (hasAlpha && !m_hasAlpha) {
489 if (m_texture.id) {
490 glDeleteTextures(1, &m_texture.id);
491 m_texture.id = 0;
492 m_dirty = true;
493 }
494 m_hasAlpha = color.alpha() != 255;
495 }
496
497 if (useFramebufferObjects()) {
498 m_source = QImage();
499 m_hasFillColor = true;
500 m_fillColor = color;
501 } else {
502
503 if (m_source.isNull()) {
504 m_fillColor = color;
505 m_hasFillColor = true;
506
507 } else if (m_source.depth() == 32) {
508 m_source.fill(PREMUL(color.rgba()));
509
510 } else if (m_source.depth() == 1) {
511 if (color == Qt::color1)
512 m_source.fill(1);
513 else
514 m_source.fill(0);
515 }
516 }
517}
518
519bool QGLPixmapData::hasAlphaChannel() const
520{
521 return m_hasAlpha;
522}
523
524QImage QGLPixmapData::fillImage(const QColor &color) const
525{
526 QImage img;
527 if (pixelType() == BitmapType) {
528 img = QImage(w, h, QImage::Format_MonoLSB);
529
530 img.setColorCount(2);
531 img.setColor(0, QColor(Qt::color0).rgba());
532 img.setColor(1, QColor(Qt::color1).rgba());
533
534 if (color == Qt::color1)
535 img.fill(1);
536 else
537 img.fill(0);
538 } else {
539 img = QImage(w, h,
540 m_hasAlpha
541 ? QImage::Format_ARGB32_Premultiplied
542 : QImage::Format_RGB32);
543 img.fill(PREMUL(color.rgba()));
544 }
545 return img;
546}
547
548extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha);
549
550QImage QGLPixmapData::toImage() const
551{
552 if (!isValid())
553 return QImage();
554
555 if (m_renderFbo) {
556 copyBackFromRenderFbo(true);
557 } else if (!m_source.isNull()) {
558 return m_source;
559 } else if (m_dirty || m_hasFillColor) {
560 return fillImage(m_fillColor);
561 } else {
562 ensureCreated();
563 }
564
565 QGLShareContextScope ctx(qt_gl_share_widget()->context());
566 glBindTexture(GL_TEXTURE_2D, m_texture.id);
567 return qt_gl_read_texture(QSize(w, h), true, true);
568}
569
570struct TextureBuffer
571{
572 QGLFramebufferObject *fbo;
573 QGL2PaintEngineEx *engine;
574};
575
576Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
577QGLFramebufferObjectPool* qgl_fbo_pool()
578{
579 return _qgl_fbo_pool();
580}
581
582void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
583{
584 if (!isValid())
585 return;
586
587 m_hasFillColor = false;
588
589 const QGLContext *share_ctx = qt_gl_share_widget()->context();
590 QGLShareContextScope ctx(share_ctx);
591
592 ensureCreated();
593
594 if (!ctx->d_ptr->fbo)
595 glGenFramebuffers(1, &ctx->d_ptr->fbo);
596
597 glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
598 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
599 GL_TEXTURE_2D, m_texture.id, 0);
600
601 const int x0 = 0;
602 const int x1 = w;
603 const int y0 = 0;
604 const int y1 = h;
605
606 if (!m_renderFbo->isBound())
607 glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
608
609 glDisable(GL_SCISSOR_TEST);
610
611 glBlitFramebufferEXT(x0, y0, x1, y1,
612 x0, y0, x1, y1,
613 GL_COLOR_BUFFER_BIT,
614 GL_NEAREST);
615
616 if (keepCurrentFboBound) {
617 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
618 } else {
619 glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle());
620 ctx->d_ptr->current_fbo = m_renderFbo->handle();
621 }
622}
623
624bool QGLPixmapData::useFramebufferObjects()
625{
626 return QGLFramebufferObject::hasOpenGLFramebufferObjects()
627 && QGLFramebufferObject::hasOpenGLFramebufferBlit()
628 && qt_gl_preferGL2Engine();
629}
630
631QPaintEngine* QGLPixmapData::paintEngine() const
632{
633 if (!isValid())
634 return 0;
635
636 if (m_renderFbo)
637 return m_engine;
638
639 if (useFramebufferObjects()) {
640 extern QGLWidget* qt_gl_share_widget();
641
642 if (!QGLContext::currentContext())
643 qt_gl_share_widget()->makeCurrent();
644 QGLShareContextScope ctx(qt_gl_share_widget()->context());
645
646 QGLFramebufferObjectFormat format;
647 format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
648 format.setSamples(4);
649 format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));
650
651 m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
652
653 if (m_renderFbo) {
654 if (!m_engine)
655 m_engine = new QGL2PaintEngineEx;
656 return m_engine;
657 }
658
659 qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
660 }
661
662 m_dirty = true;
663 if (m_source.size() != size())
664 m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied);
665 if (m_hasFillColor) {
666 m_source.fill(PREMUL(m_fillColor.rgba()));
667 m_hasFillColor = false;
668 }
669 return m_source.paintEngine();
670}
671
672extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format);
673
674// If copyBack is true, bind will copy the contents of the render
675// FBO to the texture (which is not bound to the texture, as it's
676// a multisample FBO).
677GLuint QGLPixmapData::bind(bool copyBack) const
678{
679 if (m_renderFbo && copyBack) {
680 copyBackFromRenderFbo(true);
681 } else {
682 ensureCreated();
683 }
684
685 GLuint id = m_texture.id;
686 glBindTexture(GL_TEXTURE_2D, id);
687
688 if (m_hasFillColor) {
689 if (!useFramebufferObjects()) {
690 m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
691 m_source.fill(PREMUL(m_fillColor.rgba()));
692 }
693
694 m_hasFillColor = false;
695
696 GLenum format = qt_gl_preferredTextureFormat();
697 QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
698 tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
699 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits());
700 }
701
702 return id;
703}
704
705QGLTexture* QGLPixmapData::texture() const
706{
707 return &m_texture;
708}
709
710extern int qt_defaultDpiX();
711extern int qt_defaultDpiY();
712
713int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
714{
715 if (w == 0)
716 return 0;
717
718 switch (metric) {
719 case QPaintDevice::PdmWidth:
720 return w;
721 case QPaintDevice::PdmHeight:
722 return h;
723 case QPaintDevice::PdmNumColors:
724 return 0;
725 case QPaintDevice::PdmDepth:
726 return d;
727 case QPaintDevice::PdmWidthMM:
728 return qRound(w * 25.4 / qt_defaultDpiX());
729 case QPaintDevice::PdmHeightMM:
730 return qRound(h * 25.4 / qt_defaultDpiY());
731 case QPaintDevice::PdmDpiX:
732 case QPaintDevice::PdmPhysicalDpiX:
733 return qt_defaultDpiX();
734 case QPaintDevice::PdmDpiY:
735 case QPaintDevice::PdmPhysicalDpiY:
736 return qt_defaultDpiY();
737 default:
738 qWarning("QGLPixmapData::metric(): Invalid metric");
739 return 0;
740 }
741}
742
743QGLPaintDevice *QGLPixmapData::glDevice() const
744{
745 return &m_glDevice;
746}
747
748QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.