Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtOpenGL module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
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 | #include <private/qnativeimagehandleprovider_p.h> |
53 | #include <private/qfont_p.h> |
54 | |
55 | #include <private/qpaintengineex_opengl2_p.h> |
56 | |
57 | #include <qdesktopwidget.h> |
58 | #include <qfile.h> |
59 | #include <qimagereader.h> |
60 | #include <qbuffer.h> |
61 | |
62 | #include <fbs.h> |
63 | |
64 | #include "qgltexturepool_p.h" |
65 | |
66 | QT_BEGIN_NAMESPACE |
67 | |
68 | Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); |
69 | |
70 | class QGLSgImageTextureCleanup |
71 | { |
72 | public: |
73 | QGLSgImageTextureCleanup(const QGLContext *context = 0) {} |
74 | |
75 | ~QGLSgImageTextureCleanup() |
76 | { |
77 | QList<qint64> keys = m_cache.keys(); |
78 | while(keys.size() > 0) { |
79 | QGLPixmapData *data = m_cache.take(keys.takeAt(0)); |
80 | if (data) |
81 | data->destroyTexture(); |
82 | } |
83 | } |
84 | |
85 | static QGLSgImageTextureCleanup *cleanupForContext(const QGLContext *context); |
86 | |
87 | void insert(quint64 key, QGLPixmapData *data) |
88 | { |
89 | m_cache.insert(key, data); |
90 | } |
91 | |
92 | void remove(quint64 key) |
93 | { |
94 | m_cache.take(key); |
95 | } |
96 | |
97 | private: |
98 | |
99 | QCache<qint64, QGLPixmapData> m_cache; |
100 | }; |
101 | |
102 | #if QT_VERSION >= 0x040800 |
103 | Q_GLOBAL_STATIC(QGLContextGroupResource<QGLSgImageTextureCleanup>, qt_sgimage_texture_cleanup) |
104 | #else |
105 | static void qt_sgimage_texture_cleanup_free(void *data) |
106 | { |
107 | delete reinterpret_cast<QGLSgImageTextureCleanup *>(data); |
108 | } |
109 | Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_sgimage_texture_cleanup, (qt_sgimage_texture_cleanup_free)) |
110 | #endif |
111 | |
112 | QGLSgImageTextureCleanup *QGLSgImageTextureCleanup::cleanupForContext(const QGLContext *context) |
113 | { |
114 | QGLSgImageTextureCleanup *p = reinterpret_cast<QGLSgImageTextureCleanup *>(qt_sgimage_texture_cleanup()->value(context)); |
115 | #if QT_VERSION < 0x040800 |
116 | if (!p) { |
117 | QGLShareContextScope scope(context); |
118 | qt_sgimage_texture_cleanup()->insert(context, p = new QGLSgImageTextureCleanup); |
119 | } |
120 | #endif |
121 | return p; |
122 | } |
123 | |
124 | int qt_gl_pixmap_serial = 0; |
125 | |
126 | QGLPixmapData::QGLPixmapData(PixelType type) |
127 | : QPixmapData(type, OpenGLClass) |
128 | , m_renderFbo(0) |
129 | , m_engine(0) |
130 | , m_ctx(0) |
131 | , nativeImageHandleProvider(0) |
132 | , nativeImageHandle(0) |
133 | #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE |
134 | , m_sgImage(0) |
135 | #endif |
136 | , m_dirty(false) |
137 | , m_hasFillColor(false) |
138 | , m_hasAlpha(false) |
139 | { |
140 | setSerialNumber(++qt_gl_pixmap_serial); |
141 | } |
142 | |
143 | QGLPixmapData::~QGLPixmapData() |
144 | { |
145 | #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE |
146 | if (m_sgImage) { |
147 | if (m_texture.id) { |
148 | QGLSgImageTextureCleanup::cleanupForContext(m_ctx)->remove(m_texture.id); |
149 | destroyTexture(); |
150 | } |
151 | |
152 | m_sgImage->Close(); |
153 | delete m_sgImage; |
154 | m_sgImage = 0; |
155 | } |
156 | #endif |
157 | delete m_engine; |
158 | } |
159 | |
160 | QPixmapData *QGLPixmapData::createCompatiblePixmapData() const |
161 | { |
162 | return new QGLPixmapData(pixelType()); |
163 | } |
164 | |
165 | bool QGLPixmapData::isValid() const |
166 | { |
167 | return w > 0 && h > 0; |
168 | } |
169 | |
170 | bool QGLPixmapData::isValidContext(const QGLContext *ctx) const |
171 | { |
172 | // On Symbian, we usually want to treat QGLPixmapData as |
173 | // raster pixmap data because that's well known and tested |
174 | // execution path which is used on other platforms as well. |
175 | // That's why if source pixels are valid we return false |
176 | // to simulate raster pixmaps. Only QPixmaps created from |
177 | // SgImage will enable usage of QGLPixmapData. |
178 | #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE |
179 | if (m_sgImage) { |
180 | // SgImage texture |
181 | if (ctx == m_ctx) |
182 | return true; |
183 | |
184 | const QGLContext *share_ctx = qt_gl_share_widget()->context(); |
185 | return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); |
186 | } |
187 | #endif |
188 | return false; |
189 | } |
190 | |
191 | void QGLPixmapData::resize(int width, int height) |
192 | { |
193 | if (width == w && height == h) |
194 | return; |
195 | |
196 | if (width <= 0 || height <= 0) { |
197 | width = 0; |
198 | height = 0; |
199 | } |
200 | |
201 | w = width; |
202 | h = height; |
203 | is_null = (w <= 0 || h <= 0); |
204 | d = pixelType() == QPixmapData::PixmapType ? 32 : 1; |
205 | |
206 | destroyTexture(); |
207 | |
208 | m_source = QVolatileImage(); |
209 | m_dirty = isValid(); |
210 | setSerialNumber(++qt_gl_pixmap_serial); |
211 | } |
212 | |
213 | void QGLPixmapData::ensureCreated() const |
214 | { |
215 | if (!m_dirty) |
216 | return; |
217 | |
218 | m_dirty = false; |
219 | |
220 | if (nativeImageHandleProvider && !nativeImageHandle) |
221 | const_cast<QGLPixmapData *>(this)->createFromNativeImageHandleProvider(); |
222 | |
223 | QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
224 | m_ctx = ctx; |
225 | |
226 | #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE |
227 | if (m_sgImage) { |
228 | qt_resolve_eglimage_gl_extensions(ctx); // ensure initialized |
229 | |
230 | bool textureIsBound = false; |
231 | GLuint newTextureId; |
232 | |
233 | EGLint imgAttr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; |
234 | EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display() |
235 | , EGL_NO_CONTEXT |
236 | , EGL_NATIVE_PIXMAP_KHR |
237 | , (EGLClientBuffer)m_sgImage |
238 | , imgAttr); |
239 | |
240 | glGenTextures(1, &newTextureId); |
241 | glBindTexture( GL_TEXTURE_2D, newTextureId); |
242 | |
243 | if (image != EGL_NO_IMAGE_KHR) { |
244 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
245 | GLint err = glGetError(); |
246 | if (err == GL_NO_ERROR) |
247 | textureIsBound = true; |
248 | |
249 | QEgl::eglDestroyImageKHR(QEgl::display(), image); |
250 | } |
251 | |
252 | if (textureIsBound) { |
253 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
254 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
255 | |
256 | m_texture.id = newTextureId; |
257 | m_texture.boundPixmap = const_cast<QGLPixmapData*>(this); |
258 | QGLSgImageTextureCleanup::cleanupForContext(m_ctx)->insert(m_texture.id, const_cast<QGLPixmapData*>(this)); |
259 | } else { |
260 | qWarning("QGLPixmapData: Failed to create texture from a SgImage image of size %dx%d", w, h); |
261 | glDeleteTextures(1, &newTextureId); |
262 | } |
263 | } |
264 | #endif |
265 | } |
266 | |
267 | |
268 | void QGLPixmapData::fromImage(const QImage &image, |
269 | Qt::ImageConversionFlags flags) |
270 | { |
271 | QImage img = image; |
272 | createPixmapForImage(img, flags, false); |
273 | } |
274 | |
275 | void QGLPixmapData::fromImageReader(QImageReader *imageReader, |
276 | Qt::ImageConversionFlags flags) |
277 | { |
278 | QImage image = imageReader->read(); |
279 | if (image.isNull()) |
280 | return; |
281 | |
282 | createPixmapForImage(image, flags, true); |
283 | } |
284 | |
285 | bool QGLPixmapData::fromFile(const QString &filename, const char *format, |
286 | Qt::ImageConversionFlags flags) |
287 | { |
288 | if (pixelType() == QPixmapData::BitmapType) |
289 | return QPixmapData::fromFile(filename, format, flags); |
290 | QFile file(filename); |
291 | if (file.open(QIODevice::ReadOnly)) { |
292 | QByteArray data = file.peek(64); |
293 | bool alpha; |
294 | if (m_texture.canBindCompressedTexture |
295 | (data.constData(), data.size(), format, &alpha)) { |
296 | resize(0, 0); |
297 | data = file.readAll(); |
298 | file.close(); |
299 | QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
300 | QSize size = m_texture.bindCompressedTexture |
301 | (data.constData(), data.size(), format); |
302 | if (!size.isEmpty()) { |
303 | w = size.width(); |
304 | h = size.height(); |
305 | is_null = false; |
306 | d = 32; |
307 | m_hasAlpha = alpha; |
308 | m_source = QVolatileImage(); |
309 | m_dirty = isValid(); |
310 | return true; |
311 | } |
312 | return false; |
313 | } |
314 | } |
315 | |
316 | QImage image = QImageReader(filename, format).read(); |
317 | if (image.isNull()) |
318 | return false; |
319 | |
320 | createPixmapForImage(image, flags, true); |
321 | |
322 | return !isNull(); |
323 | } |
324 | |
325 | bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, |
326 | Qt::ImageConversionFlags flags) |
327 | { |
328 | bool alpha; |
329 | const char *buf = reinterpret_cast<const char *>(buffer); |
330 | if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { |
331 | resize(0, 0); |
332 | QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
333 | QSize size = m_texture.bindCompressedTexture(buf, int(len), format); |
334 | if (!size.isEmpty()) { |
335 | w = size.width(); |
336 | h = size.height(); |
337 | is_null = false; |
338 | d = 32; |
339 | m_hasAlpha = alpha; |
340 | m_source = QVolatileImage(); |
341 | m_dirty = isValid(); |
342 | return true; |
343 | } |
344 | } |
345 | |
346 | QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); |
347 | QBuffer b(&a); |
348 | b.open(QIODevice::ReadOnly); |
349 | QImage image = QImageReader(&b, format).read(); |
350 | if (image.isNull()) |
351 | return false; |
352 | |
353 | createPixmapForImage(image, flags, true); |
354 | |
355 | return !isNull(); |
356 | } |
357 | |
358 | QImage::Format QGLPixmapData::idealFormat(QImage &image, Qt::ImageConversionFlags flags) |
359 | { |
360 | QImage::Format format = QImage::Format_RGB32; |
361 | if (qApp->desktop()->depth() == 16) |
362 | format = QImage::Format_RGB16; |
363 | |
364 | if (image.hasAlphaChannel() |
365 | && ((flags & Qt::NoOpaqueDetection) |
366 | || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) |
367 | format = QImage::Format_ARGB32_Premultiplied; |
368 | |
369 | return format; |
370 | } |
371 | |
372 | void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) |
373 | { |
374 | if (image.size() == QSize(w, h)) |
375 | setSerialNumber(++qt_gl_pixmap_serial); |
376 | |
377 | resize(image.width(), image.height()); |
378 | |
379 | if (pixelType() == BitmapType) { |
380 | QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB); |
381 | if (image.format() == QImage::Format_MonoLSB) |
382 | convertedImage.detach(); |
383 | |
384 | m_source = QVolatileImage(convertedImage); |
385 | |
386 | } else { |
387 | QImage::Format format = idealFormat(image, flags); |
388 | |
389 | if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { |
390 | m_source = QVolatileImage(image); |
391 | } else { |
392 | QImage convertedImage = image.convertToFormat(format); |
393 | |
394 | // convertToFormat won't detach the image if format stays the same. |
395 | if (image.format() == format) |
396 | convertedImage.detach(); |
397 | |
398 | m_source = QVolatileImage(convertedImage); |
399 | } |
400 | } |
401 | |
402 | m_dirty = true; |
403 | m_hasFillColor = false; |
404 | |
405 | m_hasAlpha = m_source.hasAlphaChannel(); |
406 | w = image.width(); |
407 | h = image.height(); |
408 | is_null = (w <= 0 || h <= 0); |
409 | d = m_source.depth(); |
410 | |
411 | destroyTexture(); |
412 | } |
413 | |
414 | bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) |
415 | { |
416 | Q_UNUSED(dx); |
417 | Q_UNUSED(dy); |
418 | Q_UNUSED(rect); |
419 | return false; |
420 | } |
421 | |
422 | void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) |
423 | { |
424 | QPixmapData::copy(data, rect); |
425 | } |
426 | |
427 | void QGLPixmapData::fill(const QColor &color) |
428 | { |
429 | if (!isValid()) |
430 | return; |
431 | |
432 | bool hasAlpha = color.alpha() != 255; |
433 | if (hasAlpha && !m_hasAlpha) { |
434 | if (m_texture.id) { |
435 | destroyTexture(); |
436 | m_dirty = true; |
437 | } |
438 | m_hasAlpha = color.alpha() != 255; |
439 | } |
440 | |
441 | forceToImage(); |
442 | |
443 | if (m_source.depth() == 32) { |
444 | m_source.fill(PREMUL(color.rgba())); |
445 | |
446 | } else if (m_source.depth() == 1) { |
447 | if (color == Qt::color1) |
448 | m_source.fill(1); |
449 | else |
450 | m_source.fill(0); |
451 | } |
452 | } |
453 | |
454 | bool QGLPixmapData::hasAlphaChannel() const |
455 | { |
456 | return m_hasAlpha; |
457 | } |
458 | |
459 | QImage QGLPixmapData::fillImage(const QColor &color) const |
460 | { |
461 | QImage img; |
462 | if (pixelType() == BitmapType) { |
463 | img = QImage(w, h, QImage::Format_MonoLSB); |
464 | |
465 | img.setColorCount(2); |
466 | img.setColor(0, QColor(Qt::color0).rgba()); |
467 | img.setColor(1, QColor(Qt::color1).rgba()); |
468 | |
469 | if (color == Qt::color1) |
470 | img.fill(1); |
471 | else |
472 | img.fill(0); |
473 | } else { |
474 | img = QImage(w, h, |
475 | m_hasAlpha |
476 | ? QImage::Format_ARGB32_Premultiplied |
477 | : QImage::Format_RGB32); |
478 | img.fill(PREMUL(color.rgba())); |
479 | } |
480 | return img; |
481 | } |
482 | |
483 | extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); |
484 | |
485 | QImage QGLPixmapData::toImage() const |
486 | { |
487 | if (!isValid()) |
488 | return QImage(); |
489 | |
490 | if (!m_source.isNull()) { |
491 | // QVolatileImage::toImage() will make a copy always so no check |
492 | // for active painting is needed. |
493 | QImage img = m_source.toImage(); |
494 | if (img.format() == QImage::Format_MonoLSB) { |
495 | img.setColorCount(2); |
496 | img.setColor(0, QColor(Qt::color0).rgba()); |
497 | img.setColor(1, QColor(Qt::color1).rgba()); |
498 | } |
499 | return img; |
500 | } else if (m_dirty || m_hasFillColor) { |
501 | return fillImage(m_fillColor); |
502 | } else { |
503 | ensureCreated(); |
504 | } |
505 | |
506 | QGLShareContextScope ctx(qt_gl_share_widget()->context()); |
507 | glBindTexture(GL_TEXTURE_2D, m_texture.id); |
508 | return qt_gl_read_texture(QSize(w, h), true, true); |
509 | } |
510 | |
511 | void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const |
512 | { |
513 | // We don't use FBOs on Symbian |
514 | } |
515 | |
516 | bool QGLPixmapData::useFramebufferObjects() const |
517 | { |
518 | // We don't use FBOs on Symbian for now |
519 | return false; |
520 | } |
521 | |
522 | QPaintEngine* QGLPixmapData::paintEngine() const |
523 | { |
524 | if (!isValid()) |
525 | return 0; |
526 | |
527 | // If the application wants to paint into the QPixmap, we first |
528 | // force it to QImage format and then paint into that. |
529 | // This is simpler than juggling multiple GL contexts. |
530 | const_cast<QGLPixmapData *>(this)->forceToImage(); |
531 | |
532 | if (m_hasFillColor) { |
533 | m_source.fill(PREMUL(m_fillColor.rgba())); |
534 | m_hasFillColor = false; |
535 | } |
536 | return m_source.paintEngine(); |
537 | } |
538 | |
539 | extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format); |
540 | |
541 | GLuint QGLPixmapData::bind(bool copyBack) const |
542 | { |
543 | ensureCreated(); |
544 | |
545 | GLuint id = m_texture.id; |
546 | glBindTexture(GL_TEXTURE_2D, id); |
547 | |
548 | if (m_hasFillColor) { |
549 | m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); |
550 | m_source.fill(PREMUL(m_fillColor.rgba())); |
551 | |
552 | m_hasFillColor = false; |
553 | |
554 | GLenum format = qt_gl_preferredTextureFormat(); |
555 | QImage tx(w, h, QImage::Format_ARGB32_Premultiplied); |
556 | tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format)); |
557 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits()); |
558 | } |
559 | |
560 | return id; |
561 | } |
562 | |
563 | QGLTexture* QGLPixmapData::texture() const |
564 | { |
565 | return &m_texture; |
566 | } |
567 | |
568 | Q_GUI_EXPORT int qt_defaultDpiX(); |
569 | Q_GUI_EXPORT int qt_defaultDpiY(); |
570 | |
571 | int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const |
572 | { |
573 | if (w == 0) |
574 | return 0; |
575 | |
576 | switch (metric) { |
577 | case QPaintDevice::PdmWidth: |
578 | return w; |
579 | case QPaintDevice::PdmHeight: |
580 | return h; |
581 | case QPaintDevice::PdmNumColors: |
582 | return 0; |
583 | case QPaintDevice::PdmDepth: |
584 | return d; |
585 | case QPaintDevice::PdmWidthMM: |
586 | return qRound(w * 25.4 / qt_defaultDpiX()); |
587 | case QPaintDevice::PdmHeightMM: |
588 | return qRound(h * 25.4 / qt_defaultDpiY()); |
589 | case QPaintDevice::PdmDpiX: |
590 | case QPaintDevice::PdmPhysicalDpiX: |
591 | return qt_defaultDpiX(); |
592 | case QPaintDevice::PdmDpiY: |
593 | case QPaintDevice::PdmPhysicalDpiY: |
594 | return qt_defaultDpiY(); |
595 | default: |
596 | qWarning("QGLPixmapData::metric(): Invalid metric"); |
597 | return 0; |
598 | } |
599 | } |
600 | |
601 | // Force the pixmap data to be backed by some valid data. |
602 | void QGLPixmapData::forceToImage() |
603 | { |
604 | if (!isValid()) |
605 | return; |
606 | |
607 | if (m_source.isNull()) { |
608 | QImage::Format format = QImage::Format_ARGB32_Premultiplied; |
609 | if (pixelType() == BitmapType) |
610 | format = QImage::Format_MonoLSB; |
611 | m_source = QVolatileImage(w, h, format); |
612 | } |
613 | |
614 | m_dirty = true; |
615 | } |
616 | |
617 | void QGLPixmapData::destroyTexture() |
618 | { |
619 | if (m_texture.id) { |
620 | QGLWidget *shareWidget = qt_gl_share_widget(); |
621 | if (shareWidget) { |
622 | m_texture.options |= QGLContext::MemoryManagedBindOption; |
623 | m_texture.freeTexture(); |
624 | m_texture.options &= ~QGLContext::MemoryManagedBindOption; |
625 | } else if(QGLContext::currentContext()) { |
626 | glDeleteTextures(1, &m_texture.id); |
627 | m_texture.id = 0; |
628 | m_texture.boundPixmap = 0; |
629 | m_texture.boundKey = 0; |
630 | } |
631 | m_ctx = 0; |
632 | m_dirty = true; |
633 | } |
634 | } |
635 | |
636 | void QGLPixmapData::detachTextureFromPool() |
637 | { |
638 | QGLTexturePool::instance()->detachTexture(&m_texture); |
639 | } |
640 | |
641 | void QGLPixmapData::hibernate() |
642 | { |
643 | destroyTexture(); |
644 | } |
645 | |
646 | void QGLPixmapData::reclaimTexture() |
647 | { |
648 | if (!m_texture.inTexturePool) |
649 | return; |
650 | |
651 | forceToImage(); |
652 | |
653 | destroyTexture(); |
654 | } |
655 | |
656 | QGLPaintDevice *QGLPixmapData::glDevice() const |
657 | { |
658 | return 0; |
659 | } |
660 | |
661 | static inline bool knownGoodFormat(QImage::Format format) |
662 | { |
663 | switch (format) { |
664 | case QImage::Format_RGB16: // EColor64K |
665 | case QImage::Format_RGB32: // EColor16MU |
666 | case QImage::Format_ARGB32_Premultiplied: // EColor16MAP |
667 | return true; |
668 | default: |
669 | return false; |
670 | } |
671 | } |
672 | |
673 | #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE |
674 | static inline int symbianPixeFormatBitsPerPixel(TUidPixelFormat pixelFormat) |
675 | { |
676 | switch (pixelFormat) { |
677 | case EUidPixelFormatP_1: |
678 | case EUidPixelFormatL_1: |
679 | return 1; |
680 | case EUidPixelFormatP_2: |
681 | case EUidPixelFormatL_2: |
682 | return 2; |
683 | case EUidPixelFormatP_4: |
684 | case EUidPixelFormatL_4: |
685 | return 4; |
686 | case EUidPixelFormatRGB_332: |
687 | case EUidPixelFormatA_8: |
688 | case EUidPixelFormatBGR_332: |
689 | case EUidPixelFormatP_8: |
690 | case EUidPixelFormatL_8: |
691 | return 8; |
692 | case EUidPixelFormatRGB_565: |
693 | case EUidPixelFormatBGR_565: |
694 | case EUidPixelFormatARGB_1555: |
695 | case EUidPixelFormatXRGB_1555: |
696 | case EUidPixelFormatARGB_4444: |
697 | case EUidPixelFormatARGB_8332: |
698 | case EUidPixelFormatBGRX_5551: |
699 | case EUidPixelFormatBGRA_5551: |
700 | case EUidPixelFormatBGRA_4444: |
701 | case EUidPixelFormatBGRX_4444: |
702 | case EUidPixelFormatAP_88: |
703 | case EUidPixelFormatXRGB_4444: |
704 | case EUidPixelFormatXBGR_4444: |
705 | return 16; |
706 | case EUidPixelFormatBGR_888: |
707 | case EUidPixelFormatRGB_888: |
708 | return 24; |
709 | case EUidPixelFormatXRGB_8888: |
710 | case EUidPixelFormatBGRX_8888: |
711 | case EUidPixelFormatXBGR_8888: |
712 | case EUidPixelFormatBGRA_8888: |
713 | case EUidPixelFormatARGB_8888: |
714 | case EUidPixelFormatABGR_8888: |
715 | case EUidPixelFormatARGB_8888_PRE: |
716 | case EUidPixelFormatABGR_8888_PRE: |
717 | case EUidPixelFormatBGRA_8888_PRE: |
718 | case EUidPixelFormatARGB_2101010: |
719 | case EUidPixelFormatABGR_2101010: |
720 | return 32; |
721 | default: |
722 | return 32; |
723 | }; |
724 | } |
725 | #endif |
726 | |
727 | void QGLPixmapData::fromNativeType(void* pixmap, NativeType type) |
728 | { |
729 | if (type == QPixmapData::SgImage && pixmap) { |
730 | #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) |
731 | RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap); |
732 | |
733 | m_sgImage = new RSgImage; |
734 | m_sgImage->Open(sgImage->Id()); |
735 | |
736 | TSgImageInfo info; |
737 | sgImage->GetInfo(info); |
738 | |
739 | w = info.iSizeInPixels.iWidth; |
740 | h = info.iSizeInPixels.iHeight; |
741 | d = symbianPixeFormatBitsPerPixel((TUidPixelFormat)info.iPixelFormat); |
742 | |
743 | m_source = QVolatileImage(); |
744 | m_hasAlpha = true; |
745 | m_hasFillColor = false; |
746 | m_dirty = true; |
747 | is_null = (w <= 0 || h <= 0); |
748 | #endif |
749 | } else if (type == QPixmapData::FbsBitmap && pixmap) { |
750 | CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap); |
751 | QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight); |
752 | if (size.width() == w && size.height() == h) |
753 | setSerialNumber(++qt_gl_pixmap_serial); |
754 | resize(size.width(), size.height()); |
755 | m_source = QVolatileImage(bitmap); |
756 | if (pixelType() == BitmapType) { |
757 | m_source.ensureFormat(QImage::Format_MonoLSB); |
758 | } else if (!knownGoodFormat(m_source.format())) { |
759 | m_source.beginDataAccess(); |
760 | QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor); |
761 | m_source.endDataAccess(true); |
762 | m_source.ensureFormat(format); |
763 | } |
764 | m_hasAlpha = m_source.hasAlphaChannel(); |
765 | m_hasFillColor = false; |
766 | m_dirty = true; |
767 | d = m_source.depth(); |
768 | } else if (type == QPixmapData::VolatileImage && pixmap) { |
769 | // Support QS60Style in more efficient skin graphics retrieval. |
770 | QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); |
771 | if (img->width() == w && img->height() == h) |
772 | setSerialNumber(++qt_gl_pixmap_serial); |
773 | resize(img->width(), img->height()); |
774 | m_source = *img; |
775 | m_hasAlpha = m_source.hasAlphaChannel(); |
776 | m_hasFillColor = false; |
777 | m_dirty = true; |
778 | d = m_source.depth(); |
779 | } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) { |
780 | destroyTexture(); |
781 | nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap); |
782 | // Cannot defer the retrieval, we need at least the size right away. |
783 | createFromNativeImageHandleProvider(); |
784 | } |
785 | } |
786 | |
787 | void* QGLPixmapData::toNativeType(NativeType type) |
788 | { |
789 | if (type == QPixmapData::FbsBitmap) { |
790 | if (m_source.isNull()) |
791 | m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); |
792 | return m_source.duplicateNativeImage(); |
793 | } |
794 | |
795 | return 0; |
796 | } |
797 | |
798 | bool QGLPixmapData::initFromNativeImageHandle(void *handle, const QString &type) |
799 | { |
800 | if (type == QLatin1String("RSgImage")) { |
801 | fromNativeType(handle, QPixmapData::SgImage); |
802 | return true; |
803 | } else if (type == QLatin1String("CFbsBitmap")) { |
804 | fromNativeType(handle, QPixmapData::FbsBitmap); |
805 | return true; |
806 | } |
807 | return false; |
808 | } |
809 | |
810 | void QGLPixmapData::createFromNativeImageHandleProvider() |
811 | { |
812 | void *handle = 0; |
813 | QString type; |
814 | nativeImageHandleProvider->get(&handle, &type); |
815 | if (handle) { |
816 | if (initFromNativeImageHandle(handle, type)) { |
817 | nativeImageHandle = handle; |
818 | nativeImageType = type; |
819 | } else { |
820 | qWarning("QGLPixmapData: Unknown native image type '%s'", qPrintable(type)); |
821 | } |
822 | } else { |
823 | qWarning("QGLPixmapData: Native handle is null"); |
824 | } |
825 | } |
826 | |
827 | void QGLPixmapData::releaseNativeImageHandle() |
828 | { |
829 | if (nativeImageHandleProvider && nativeImageHandle) { |
830 | nativeImageHandleProvider->release(nativeImageHandle, nativeImageType); |
831 | nativeImageHandle = 0; |
832 | nativeImageType = QString(); |
833 | } |
834 | } |
835 | |
836 | QT_END_NAMESPACE |
837 |
Warning: That file was not part of the compilation database. It may have many parsing errors.