/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 226 lines · 145 code · 35 blank · 46 comment · 28 complexity · 347c5203b335bb998597ae0f773e8396 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 plugins 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 "qmeegopixmapdata.h"
  42. #include "qmeegoextensions.h"
  43. #include "qmeegorasterpixmapdata.h"
  44. #include <private/qimage_p.h>
  45. #include <private/qwindowsurface_gl_p.h>
  46. #include <private/qeglcontext_p.h>
  47. #include <private/qapplication_p.h>
  48. #include <private/qgraphicssystem_runtime_p.h>
  49. // from dithering.cpp
  50. extern unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride);
  51. extern unsigned short* convertARGB32_to_RGBA4444(const unsigned char *in, int width, int height, int stride);
  52. extern unsigned char* convertBGRA32_to_RGBA32(const unsigned char *in, int width, int height, int stride);
  53. static EGLint preserved_image_attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
  54. QHash <void*, QMeeGoImageInfo*> QMeeGoPixmapData::sharedImagesMap;
  55. /* Public */
  56. QMeeGoPixmapData::QMeeGoPixmapData() : QGLPixmapData(QPixmapData::PixmapType)
  57. {
  58. }
  59. void QMeeGoPixmapData::fromTexture(GLuint textureId, int w, int h, bool alpha)
  60. {
  61. resize(w, h);
  62. texture()->id = textureId;
  63. m_hasAlpha = alpha;
  64. softImage = QImage();
  65. }
  66. QImage QMeeGoPixmapData::toImage() const
  67. {
  68. return softImage;
  69. }
  70. void QMeeGoPixmapData::fromImage(const QImage &image,
  71. Qt::ImageConversionFlags flags)
  72. {
  73. void *rawResource = static_cast <void *> (((QImage &) image).data_ptr()->data);
  74. if (sharedImagesMap.contains(rawResource)) {
  75. QMeeGoImageInfo *info = sharedImagesMap.value(rawResource);
  76. fromEGLSharedImage(info->handle, image);
  77. } else {
  78. // This should *never* happen since the graphics system should never
  79. // create a QMeeGoPixmapData for an origin that doesn't contain a raster
  80. // image we know about. But...
  81. qWarning("QMeeGoPixmapData::fromImage called on non-know resource. Falling back...");
  82. QGLPixmapData::fromImage(image, flags);
  83. }
  84. }
  85. void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si)
  86. {
  87. if (si.isNull())
  88. qFatal("Trying to build pixmap with an empty/null softimage!");
  89. QGLShareContextScope ctx(qt_gl_share_widget()->context());
  90. QMeeGoExtensions::ensureInitialized();
  91. bool textureIsBound = false;
  92. GLuint newTextureId;
  93. GLint newWidth, newHeight;
  94. glGenTextures(1, &newTextureId);
  95. glBindTexture(GL_TEXTURE_2D, newTextureId);
  96. EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_SHARED_IMAGE_NOK,
  97. (EGLClientBuffer)handle, preserved_image_attribs);
  98. if (image != EGL_NO_IMAGE_KHR) {
  99. glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  100. GLint err = glGetError();
  101. if (err == GL_NO_ERROR)
  102. textureIsBound = true;
  103. QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_WIDTH, &newWidth);
  104. QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_HEIGHT, &newHeight);
  105. QEgl::eglDestroyImageKHR(QEgl::display(), image);
  106. }
  107. if (textureIsBound) {
  108. fromTexture(newTextureId, newWidth, newHeight,
  109. (si.hasAlphaChannel() && const_cast<QImage &>(si).data_ptr()->checkForAlphaPixels()));
  110. texture()->options &= ~QGLContext::InvertedYBindOption;
  111. softImage = si;
  112. QMeeGoPixmapData::registerSharedImage(handle, softImage);
  113. } else {
  114. qWarning("Failed to create a texture from a shared image!");
  115. glDeleteTextures(1, &newTextureId);
  116. }
  117. }
  118. Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image)
  119. {
  120. QGLShareContextScope ctx(qt_gl_share_widget()->context());
  121. QMeeGoExtensions::ensureInitialized();
  122. GLuint textureId;
  123. glGenTextures(1, &textureId);
  124. glBindTexture(GL_TEXTURE_2D, textureId);
  125. if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) {
  126. void *converted = convertBGRA32_to_RGBA32(image.bits(), image.width(), image.height(), image.bytesPerLine());
  127. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, converted);
  128. free(converted);
  129. } else {
  130. void *converted = convertRGB32_to_RGB565(image.bits(), image.width(), image.height(), image.bytesPerLine());
  131. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, converted);
  132. free(converted);
  133. }
  134. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  135. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  136. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  137. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  138. EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(),
  139. EGL_GL_TEXTURE_2D_KHR,
  140. (EGLClientBuffer) textureId,
  141. preserved_image_attribs);
  142. glDeleteTextures(1, &textureId);
  143. if (eglimage) {
  144. EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL);
  145. QEgl::eglDestroyImageKHR(QEgl::display(), eglimage);
  146. return (Qt::HANDLE) handle;
  147. } else {
  148. qWarning("Failed to create shared image from pixmap/texture!");
  149. return 0;
  150. }
  151. }
  152. void QMeeGoPixmapData::updateFromSoftImage()
  153. {
  154. // FIXME That's broken with recent 16bit textures changes.
  155. m_dirty = true;
  156. m_source = softImage;
  157. ensureCreated();
  158. if (softImage.width() != w || softImage.height() != h)
  159. qWarning("Ooops, looks like softImage changed dimensions since last updated! Corruption ahead?!");
  160. }
  161. bool QMeeGoPixmapData::destroyEGLSharedImage(Qt::HANDLE h)
  162. {
  163. QGLShareContextScope ctx(qt_gl_share_widget()->context());
  164. QMeeGoExtensions::ensureInitialized();
  165. QMutableHashIterator <void*, QMeeGoImageInfo*> i(sharedImagesMap);
  166. while (i.hasNext()) {
  167. i.next();
  168. if (i.value()->handle == h)
  169. i.remove();
  170. }
  171. return QMeeGoExtensions::eglDestroySharedImageNOK(QEgl::display(), (EGLNativeSharedImageTypeNOK) h);
  172. }
  173. void QMeeGoPixmapData::registerSharedImage(Qt::HANDLE handle, const QImage &si)
  174. {
  175. void *raw = static_cast <void *> (((QImage) si).data_ptr()->data);
  176. QMeeGoImageInfo *info;
  177. if (! sharedImagesMap.contains(raw)) {
  178. info = new QMeeGoImageInfo;
  179. info->handle = handle;
  180. info->rawFormat = si.format();
  181. sharedImagesMap.insert(raw, info);
  182. } else {
  183. info = sharedImagesMap.value(raw);
  184. if (info->handle != handle || info->rawFormat != si.format())
  185. qWarning("Inconsistency detected: overwriting entry in sharedImagesMap but handle/format different");
  186. }
  187. }
  188. QPixmapData *QMeeGoPixmapData::createCompatiblePixmapData() const
  189. {
  190. return new QMeeGoRasterPixmapData(pixelType());
  191. }