/src/opengl/qpixmapdata_symbiangl.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 836 lines · 654 code · 124 blank · 58 comment · 143 complexity · 0e563717aecc24b3a70f70ea5c6c5d1c MD5 · raw file

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