summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJani Hautakangas <jani.hautakangas@nokia.com>2011-06-30 11:28:39 (GMT)
committerJani Hautakangas <jani.hautakangas@nokia.com>2011-06-30 11:59:11 (GMT)
commit2b6cf174153c6a680bac94eb666a131a3aad3891 (patch)
tree2b9b8184cbea924a9868b94d87747ce4e052398c
parentc1759aa657f5f729c96696b819465c70266c21c8 (diff)
downloadQt-2b6cf174153c6a680bac94eb666a131a3aad3891.zip
Qt-2b6cf174153c6a680bac94eb666a131a3aad3891.tar.gz
Qt-2b6cf174153c6a680bac94eb666a131a3aad3891.tar.bz2
Introduce QPixmap::fromSymbianRSgImage(RSgImage*) to GL engine
Initial implementation of QPixmap::fromSymbianRSgImage(RSgImage*) on OpenGL graphics system. Task-number: QTBUG-15254 Reviewed-by: Laszlo Agocs
-rw-r--r--mkspecs/common/symbian/symbian.conf3
-rw-r--r--src/opengl/qgl.cpp1
-rw-r--r--src/opengl/qgl_symbian.cpp109
-rw-r--r--src/opengl/qpixmapdata_gl_p.h15
-rw-r--r--src/opengl/qpixmapdata_symbiangl.cpp627
-rw-r--r--src/opengl/qwindowsurface_gl.cpp55
6 files changed, 339 insertions, 471 deletions
diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf
index 0288ada..e30347b 100644
--- a/mkspecs/common/symbian/symbian.conf
+++ b/mkspecs/common/symbian/symbian.conf
@@ -88,6 +88,9 @@ QMAKE_LIBS_S60 = -lavkon -leikcoctl -lgfxtrans
exists($${EPOCROOT}epoc32/include/platform/sgresource/sgimage.h) {
QMAKE_LIBS_OPENVG += -lsgresource
+ QMAKE_LIBS_OPENGL_QT += -lsgresource
+ QMAKE_LIBS_OPENGL_ES1_QT += -lsgresource
+ QMAKE_LIBS_OPENGL_ES2_QT += -lsgresource
}
contains(QMAKE_HOST.os,Windows) {
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 4fee886..161e099 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -5920,6 +5920,7 @@ void QGLTexture::freeTexture()
}
id = 0;
+ boundPixmap = 0;
boundKey = 0;
}
#endif
diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp
index 21671a6..b8e5c22 100644
--- a/src/opengl/qgl_symbian.cpp
+++ b/src/opengl/qgl_symbian.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qgl.h"
-#include <fbs.h>
#include <private/qt_s60_p.h>
#include <private/qpixmap_raster_symbian_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
@@ -55,7 +54,7 @@
#include "qpixmapdata_gl_p.h"
#include "qgltexturepool_p.h"
#include "qcolormap.h"
-#include <QDebug>
+
QT_BEGIN_NAMESPACE
@@ -73,7 +72,7 @@ QT_BEGIN_NAMESPACE
#endif
#endif
-extern int qt_gl_pixmap_serial;
+Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
/*
QGLTemporaryContext implementation
@@ -266,6 +265,11 @@ void QGLWidget::resizeEvent(QResizeEvent *)
if (!isValid())
return;
+ // Shared widget can ignore resize events which
+ // may happen due to orientation change
+ if (this == qt_gl_share_widget())
+ return;
+
if (QGLContext::currentContext())
doneCurrent();
@@ -378,103 +382,4 @@ void QGLWidgetPrivate::recreateEglSurface()
eglSurfaceWindowId = currentId;
}
-static inline bool knownGoodFormat(QImage::Format format)
-{
- switch (format) {
- case QImage::Format_RGB16: // EColor64K
- case QImage::Format_RGB32: // EColor16MU
- case QImage::Format_ARGB32_Premultiplied: // EColor16MAP
- return true;
- default:
- return false;
- }
-}
-
-void QGLPixmapData::fromNativeType(void* pixmap, NativeType type)
-{
- if (type == QPixmapData::FbsBitmap) {
- CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap);
- QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight);
- if (size.width() == w && size.height() == h)
- setSerialNumber(++qt_gl_pixmap_serial);
- resize(size.width(), size.height());
- m_source = QVolatileImage(bitmap);
- if (pixelType() == BitmapType) {
- m_source.ensureFormat(QImage::Format_MonoLSB);
- } else if (!knownGoodFormat(m_source.format())) {
- m_source.beginDataAccess();
- QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor);
- m_source.endDataAccess(true);
- m_source.ensureFormat(format);
- }
- m_hasAlpha = m_source.hasAlphaChannel();
- m_hasFillColor = false;
- m_dirty = true;
-
- } else if (type == QPixmapData::VolatileImage && pixmap) {
- // Support QS60Style in more efficient skin graphics retrieval.
- QVolatileImage *img = static_cast<QVolatileImage *>(pixmap);
- if (img->width() == w && img->height() == h)
- setSerialNumber(++qt_gl_pixmap_serial);
- resize(img->width(), img->height());
- m_source = *img;
- m_hasAlpha = m_source.hasAlphaChannel();
- m_hasFillColor = false;
- m_dirty = true;
- } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) {
- destroyTexture();
- nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap);
- // Cannot defer the retrieval, we need at least the size right away.
- createFromNativeImageHandleProvider();
- }
-}
-
-void* QGLPixmapData::toNativeType(NativeType type)
-{
- if (type == QPixmapData::FbsBitmap) {
- if (m_source.isNull())
- m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
- return m_source.duplicateNativeImage();
- }
- return 0;
-}
-
-bool QGLPixmapData::initFromNativeImageHandle(void *handle, const QString &type)
-{
- if (type == QLatin1String("RSgImage")) {
- fromNativeType(handle, QPixmapData::SgImage);
- return true;
- } else if (type == QLatin1String("CFbsBitmap")) {
- fromNativeType(handle, QPixmapData::FbsBitmap);
- return true;
- }
- return false;
-}
-
-void QGLPixmapData::createFromNativeImageHandleProvider()
-{
- void *handle = 0;
- QString type;
- nativeImageHandleProvider->get(&handle, &type);
- if (handle) {
- if (initFromNativeImageHandle(handle, type)) {
- nativeImageHandle = handle;
- nativeImageType = type;
- } else {
- qWarning("QGLPixmapData: Unknown native image type '%s'", qPrintable(type));
- }
- } else {
- qWarning("QGLPixmapData: Native handle is null");
- }
-}
-
-void QGLPixmapData::releaseNativeImageHandle()
-{
- if (nativeImageHandleProvider && nativeImageHandle) {
- nativeImageHandleProvider->release(nativeImageHandle, nativeImageType);
- nativeImageHandle = 0;
- nativeImageType = QString();
- }
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index bf1a303..3d22ad1 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -61,6 +61,9 @@
#ifdef Q_OS_SYMBIAN
#include "private/qvolatileimage_p.h"
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+# include <sgresource/sgimage.h>
+#endif
#endif
QT_BEGIN_NAMESPACE
@@ -72,8 +75,7 @@ class QGLPixmapData;
#ifdef Q_OS_SYMBIAN
class QNativeImageHandleProvider;
-#endif
-
+#else
class QGLFramebufferObjectPool
{
public:
@@ -102,7 +104,7 @@ public:
private:
QGLPixmapData *data;
};
-
+#endif
class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData
{
@@ -194,6 +196,9 @@ private:
mutable QNativeImageHandleProvider *nativeImageHandleProvider;
void *nativeImageHandle;
QString nativeImageType;
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+ RSgImage *m_sgImage;
+#endif
#else
mutable QImage m_source;
#endif
@@ -208,9 +213,9 @@ private:
mutable bool m_hasFillColor;
mutable bool m_hasAlpha;
-
+#ifndef Q_OS_SYMBIAN
mutable QGLPixmapGLPaintDevice m_glDevice;
-
+#endif
friend class QGLPixmapGLPaintDevice;
friend class QMeeGoPixmapData;
friend class QMeeGoLivePixmapData;
diff --git a/src/opengl/qpixmapdata_symbiangl.cpp b/src/opengl/qpixmapdata_symbiangl.cpp
index 8c3d61a..372b5ca 100644
--- a/src/opengl/qpixmapdata_symbiangl.cpp
+++ b/src/opengl/qpixmapdata_symbiangl.cpp
@@ -58,181 +58,61 @@
#include <qimagereader.h>
#include <qbuffer.h>
+#include <fbs.h>
+
#include "qgltexturepool_p.h"
QT_BEGIN_NAMESPACE
Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
-static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
-{
- return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
-}
-
-extern int qt_next_power_of_two(int v);
-
-static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
-{
-#ifdef QT_OPENGL_ES_2
- QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
- if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
- return rounded;
-#endif
- return sz;
-}
-
-
-QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
+class QGLSgImageTextureCleanup
{
- QGLFramebufferObject *chosen = 0;
- QGLFramebufferObject *candidate = 0;
- for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
- QGLFramebufferObject *fbo = m_fbos.at(i);
+public:
+ QGLSgImageTextureCleanup() {}
- if (strictSize) {
- if (fbo->size() == requestSize && fbo->format() == requestFormat) {
- chosen = fbo;
- break;
- } else {
- continue;
- }
- }
-
- if (fbo->format() == requestFormat) {
- // choose the fbo with a matching format and the closest size
- if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
- candidate = fbo;
- }
-
- if (candidate) {
- m_fbos.removeOne(candidate);
-
- const QSize fboSize = candidate->size();
- QSize sz = fboSize;
-
- if (sz.width() < requestSize.width())
- sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
- if (sz.height() < requestSize.height())
- sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
-
- // wasting too much space?
- if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
- sz = requestSize;
-
- if (sz != fboSize) {
- delete candidate;
- candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
- }
-
- chosen = candidate;
+ ~QGLSgImageTextureCleanup()
+ {
+ QList<qint64> keys = m_cache.keys();
+ while(keys.size() > 0) {
+ QGLPixmapData *data = m_cache.take(keys.takeAt(0));
+ if (data)
+ data->destroyTexture();
}
}
- if (!chosen) {
- if (strictSize)
- chosen = new QGLFramebufferObject(requestSize, requestFormat);
- else
- chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
- }
+ static QGLSgImageTextureCleanup *cleanupForContext(const QGLContext *context);
- if (!chosen->isValid()) {
- delete chosen;
- chosen = 0;
+ void insert(quint64 key, QGLPixmapData *data)
+ {
+ m_cache.insert(key, data);
}
- return chosen;
-}
-
-void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
-{
- if (fbo)
- m_fbos << fbo;
-}
-
-
-QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
-{
- return data->paintEngine();
-}
-
-void QGLPixmapGLPaintDevice::beginPaint()
-{
- if (!data->isValid())
- return;
-
- // QGLPaintDevice::beginPaint will store the current binding and replace
- // it with m_thisFBO:
- m_thisFBO = data->m_renderFbo->handle();
- QGLPaintDevice::beginPaint();
-
- Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
-
- // QPixmap::fill() is deferred until now, where we actually need to do the fill:
- if (data->needsFill()) {
- const QColor &c = data->fillColor();
- float alpha = c.alphaF();
- glDisable(GL_SCISSOR_TEST);
- glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
- glClear(GL_COLOR_BUFFER_BIT);
+ void remove(quint64 key)
+ {
+ m_cache.take(key);
}
- else if (!data->isUninitialized()) {
- // If the pixmap (GL Texture) has valid content (it has been
- // uploaded from an image or rendered into before), we need to
- // copy it from the texture to the render FBO.
-
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
-
-#if !defined(QT_OPENGL_ES_2)
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, data->width(), data->height(), 0, -999999, 999999);
-#endif
-
- glViewport(0, 0, data->width(), data->height());
-
- // Pass false to bind so it doesn't copy the FBO into the texture!
- context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false));
- }
-}
-
-void QGLPixmapGLPaintDevice::endPaint()
-{
- if (!data->isValid())
- return;
- data->copyBackFromRenderFbo(false);
+private:
- // Base's endPaint will restore the previous FBO binding
- QGLPaintDevice::endPaint();
-
- qgl_fbo_pool()->release(data->m_renderFbo);
- data->m_renderFbo = 0;
-}
+ QCache<qint64, QGLPixmapData> m_cache;
+};
-QGLContext* QGLPixmapGLPaintDevice::context() const
+static void qt_sgimage_texture_cleanup_free(void *data)
{
- data->ensureCreated();
- return data->m_ctx;
+ delete reinterpret_cast<QGLSgImageTextureCleanup *>(data);
}
-QSize QGLPixmapGLPaintDevice::size() const
-{
- return data->size();
-}
+Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_sgimage_texture_cleanup, (qt_sgimage_texture_cleanup_free))
-bool QGLPixmapGLPaintDevice::alphaRequested() const
+QGLSgImageTextureCleanup *QGLSgImageTextureCleanup::cleanupForContext(const QGLContext *context)
{
- return data->m_hasAlpha;
-}
-
-void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
-{
- data = d;
+ QGLSgImageTextureCleanup *p = reinterpret_cast<QGLSgImageTextureCleanup *>(qt_sgimage_texture_cleanup()->value(context));
+ if (!p) {
+ QGLShareContextScope scope(context);
+ qt_sgimage_texture_cleanup()->insert(context, p = new QGLSgImageTextureCleanup);
+ }
+ return p;
}
int qt_gl_pixmap_serial = 0;
@@ -244,16 +124,28 @@ QGLPixmapData::QGLPixmapData(PixelType type)
, m_ctx(0)
, nativeImageHandleProvider(0)
, nativeImageHandle(0)
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+ , m_sgImage(0)
+#endif
, m_dirty(false)
, m_hasFillColor(false)
, m_hasAlpha(false)
{
setSerialNumber(++qt_gl_pixmap_serial);
- m_glDevice.setPixmapData(this);
}
QGLPixmapData::~QGLPixmapData()
{
+ if (m_sgImage) {
+ if (m_texture.id) {
+ QGLSgImageTextureCleanup::cleanupForContext(m_ctx)->remove(m_texture.id);
+ destroyTexture();
+ }
+
+ m_sgImage->Close();
+ delete m_sgImage;
+ m_sgImage = 0;
+ }
delete m_engine;
}
@@ -275,6 +167,16 @@ bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
// That's why if source pixels are valid we return false
// to simulate raster pixmaps. Only QPixmaps created from
// SgImage will enable usage of QGLPixmapData.
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+ if (m_sgImage) {
+ // SgImage texture
+ if (ctx == m_ctx)
+ return true;
+
+ const QGLContext *share_ctx = qt_gl_share_widget()->context();
+ return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx);
+ }
+#endif
return false;
}
@@ -313,72 +215,45 @@ void QGLPixmapData::ensureCreated() const
QGLShareContextScope ctx(qt_gl_share_widget()->context());
m_ctx = ctx;
- const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
-#ifdef QT_OPENGL_ES_2
- const GLenum external_format = internal_format;
-#else
- const GLenum external_format = qt_gl_preferredTextureFormat();
-#endif
- const GLenum target = GL_TEXTURE_2D;
-
- GLenum type = GL_UNSIGNED_BYTE;
- // Avoid conversion when pixmap is created from CFbsBitmap of EColor64K.
- if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16)
- type = GL_UNSIGNED_SHORT_5_6_5;
-
- if (!m_texture.id) {
- m_texture.id = QGLTexturePool::instance()->createTexture(
- target,
- 0, internal_format,
- w, h,
- external_format,
- type,
- &m_texture);
- if (!m_texture.id) {
- m_texture.failedToAlloc = true;
- return;
- }
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+ if (m_sgImage) {
+ qt_resolve_eglimage_gl_extensions(ctx); // ensure initialized
- m_texture.inTexturePool = true;
- } else if (m_texture.inTexturePool) {
- glBindTexture(target, m_texture.id);
- QGLTexturePool::instance()->useTexture(&m_texture);
- }
+ bool textureIsBound = false;
+ GLuint newTextureId;
- if (!m_source.isNull() && m_texture.id) {
- if (external_format == GL_RGB) {
- m_source.beginDataAccess();
- QImage tx;
- if (type == GL_UNSIGNED_BYTE)
- tx = m_source.imageRef().convertToFormat(QImage::Format_RGB888).mirrored(false, true);
- else if (type == GL_UNSIGNED_SHORT_5_6_5)
- tx = m_source.imageRef().mirrored(false, true);
- m_source.endDataAccess(true);
+ EGLint imgAttr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+ EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display()
+ , EGL_NO_CONTEXT
+ , EGL_NATIVE_PIXMAP_KHR
+ , (EGLClientBuffer)m_sgImage
+ , imgAttr);
- glBindTexture(target, m_texture.id);
- if (!tx.isNull())
- glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
- type, tx.constBits());
- else
- qWarning("QGLPixmapData: Failed to create GL_RGB image of size %dx%d", w, h);
- } else {
- // do byte swizzling ARGB -> RGBA
- m_source.beginDataAccess();
- const QImage tx = ctx->d_func()->convertToGLFormat(m_source.imageRef(), true, external_format);
- m_source.endDataAccess(true);
- glBindTexture(target, m_texture.id);
- if (!tx.isNull())
- glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
- type, tx.constBits());
- else
- qWarning("QGLPixmapData: Failed to create GL_RGBA image of size %dx%d", w, h);
+ glGenTextures(1, &newTextureId);
+ glBindTexture( GL_TEXTURE_2D, newTextureId);
+
+ if (image != EGL_NO_IMAGE_KHR) {
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+ GLint err = glGetError();
+ if (err == GL_NO_ERROR)
+ textureIsBound = true;
+
+ QEgl::eglDestroyImageKHR(QEgl::display(), image);
}
- if (useFramebufferObjects())
- m_source = QVolatileImage();
+ if (textureIsBound) {
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ m_texture.id = newTextureId;
+ m_texture.boundPixmap = const_cast<QGLPixmapData*>(this);
+ QGLSgImageTextureCleanup::cleanupForContext(m_ctx)->insert(m_texture.id, const_cast<QGLPixmapData*>(this));
+ } else {
+ qWarning("QGLPixmapData: Failed to create texture from a SgImage image of size %dx%d", w, h);
+ glDeleteTextures(1, &newTextureId);
+ }
}
+#endif
}
@@ -538,42 +413,7 @@ bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
{
- if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) {
- QPixmapData::copy(data, rect);
- return;
- }
-
- const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data);
- if (other->m_renderFbo) {
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
-
- resize(rect.width(), rect.height());
- m_hasAlpha = other->m_hasAlpha;
- ensureCreated();
-
- if (!ctx->d_ptr->fbo)
- glGenFramebuffers(1, &ctx->d_ptr->fbo);
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, m_texture.id, 0);
-
- if (!other->m_renderFbo->isBound())
- glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle());
-
- glDisable(GL_SCISSOR_TEST);
- if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState();
-
- glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(),
- 0, 0, w, h,
- GL_COLOR_BUFFER_BIT,
- GL_NEAREST);
-
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
- } else {
- QPixmapData::copy(data, rect);
- }
+ QPixmapData::copy(data, rect);
}
void QGLPixmapData::fill(const QColor &color)
@@ -590,11 +430,6 @@ void QGLPixmapData::fill(const QColor &color)
m_hasAlpha = color.alpha() != 255;
}
- if (useFramebufferObjects()) {
- m_source = QVolatileImage();
- m_hasFillColor = true;
- m_fillColor = color;
- } else {
forceToImage();
if (m_source.depth() == 32) {
@@ -605,7 +440,6 @@ void QGLPixmapData::fill(const QColor &color)
m_source.fill(1);
else
m_source.fill(0);
- }
}
}
@@ -645,9 +479,7 @@ QImage QGLPixmapData::toImage() const
if (!isValid())
return QImage();
- if (m_renderFbo) {
- copyBackFromRenderFbo(true);
- } else if (!m_source.isNull()) {
+ if (!m_source.isNull()) {
// QVolatileImage::toImage() will make a copy always so no check
// for active painting is needed.
QImage img = m_source.toImage();
@@ -668,58 +500,9 @@ QImage QGLPixmapData::toImage() const
return qt_gl_read_texture(QSize(w, h), true, true);
}
-struct TextureBuffer
-{
- QGLFramebufferObject *fbo;
- QGL2PaintEngineEx *engine;
-};
-
-Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
-QGLFramebufferObjectPool* qgl_fbo_pool()
-{
- return _qgl_fbo_pool();
-}
-
void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
{
- if (!isValid())
- return;
-
- m_hasFillColor = false;
-
- const QGLContext *share_ctx = qt_gl_share_widget()->context();
- QGLShareContextScope ctx(share_ctx);
-
- ensureCreated();
-
- if (!ctx->d_ptr->fbo)
- glGenFramebuffers(1, &ctx->d_ptr->fbo);
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, m_texture.id, 0);
-
- const int x0 = 0;
- const int x1 = w;
- const int y0 = 0;
- const int y1 = h;
-
- if (!m_renderFbo->isBound())
- glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
-
- glDisable(GL_SCISSOR_TEST);
-
- glBlitFramebufferEXT(x0, y0, x1, y1,
- x0, y0, x1, y1,
- GL_COLOR_BUFFER_BIT,
- GL_NEAREST);
-
- if (keepCurrentFboBound) {
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
- } else {
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle());
- ctx->d_ptr->current_fbo = m_renderFbo->handle();
- }
+ // We don't use FBOs on Symbian
}
bool QGLPixmapData::useFramebufferObjects() const
@@ -733,32 +516,6 @@ QPaintEngine* QGLPixmapData::paintEngine() const
if (!isValid())
return 0;
- if (m_renderFbo)
- return m_engine;
-
- if (useFramebufferObjects()) {
- extern QGLWidget* qt_gl_share_widget();
-
- if (!QGLContext::currentContext())
- qt_gl_share_widget()->makeCurrent();
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
-
- QGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
- format.setSamples(4);
- format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));
-
- m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
-
- if (m_renderFbo) {
- if (!m_engine)
- m_engine = new QGL2PaintEngineEx;
- return m_engine;
- }
-
- qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
- }
-
// If the application wants to paint into the QPixmap, we first
// force it to QImage format and then paint into that.
// This is simpler than juggling multiple GL contexts.
@@ -773,25 +530,16 @@ QPaintEngine* QGLPixmapData::paintEngine() const
extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format);
-// If copyBack is true, bind will copy the contents of the render
-// FBO to the texture (which is not bound to the texture, as it's
-// a multisample FBO).
GLuint QGLPixmapData::bind(bool copyBack) const
{
- if (m_renderFbo && copyBack) {
- copyBackFromRenderFbo(true);
- } else {
- ensureCreated();
- }
+ ensureCreated();
GLuint id = m_texture.id;
glBindTexture(GL_TEXTURE_2D, id);
if (m_hasFillColor) {
- if (!useFramebufferObjects()) {
m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
m_source.fill(PREMUL(m_fillColor.rgba()));
- }
m_hasFillColor = false;
@@ -860,7 +608,21 @@ void QGLPixmapData::forceToImage()
void QGLPixmapData::destroyTexture()
{
- // Destroy SgImage texture
+ if (m_texture.id) {
+ QGLWidget *shareWidget = qt_gl_share_widget();
+ if (shareWidget) {
+ m_texture.options |= QGLContext::MemoryManagedBindOption;
+ m_texture.freeTexture();
+ m_texture.options &= ~QGLContext::MemoryManagedBindOption;
+ } else if(QGLContext::currentContext()) {
+ glDeleteTextures(1, &m_texture.id);
+ m_texture.id = 0;
+ m_texture.boundPixmap = 0;
+ m_texture.boundKey = 0;
+ }
+ m_ctx = 0;
+ m_dirty = true;
+ }
}
void QGLPixmapData::detachTextureFromPool()
@@ -885,7 +647,180 @@ void QGLPixmapData::reclaimTexture()
QGLPaintDevice *QGLPixmapData::glDevice() const
{
- return &m_glDevice;
+ return 0;
+}
+
+static inline bool knownGoodFormat(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGB16: // EColor64K
+ case QImage::Format_RGB32: // EColor16MU
+ case QImage::Format_ARGB32_Premultiplied: // EColor16MAP
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline int symbianPixeFormatBitsPerPixel(TUidPixelFormat pixelFormat)
+{
+ switch (pixelFormat) {
+ case EUidPixelFormatP_1:
+ case EUidPixelFormatL_1:
+ return 1;
+ case EUidPixelFormatP_2:
+ case EUidPixelFormatL_2:
+ return 2;
+ case EUidPixelFormatP_4:
+ case EUidPixelFormatL_4:
+ return 4;
+ case EUidPixelFormatRGB_332:
+ case EUidPixelFormatA_8:
+ case EUidPixelFormatBGR_332:
+ case EUidPixelFormatP_8:
+ case EUidPixelFormatL_8:
+ return 8;
+ case EUidPixelFormatRGB_565:
+ case EUidPixelFormatBGR_565:
+ case EUidPixelFormatARGB_1555:
+ case EUidPixelFormatXRGB_1555:
+ case EUidPixelFormatARGB_4444:
+ case EUidPixelFormatARGB_8332:
+ case EUidPixelFormatBGRX_5551:
+ case EUidPixelFormatBGRA_5551:
+ case EUidPixelFormatBGRA_4444:
+ case EUidPixelFormatBGRX_4444:
+ case EUidPixelFormatAP_88:
+ case EUidPixelFormatXRGB_4444:
+ case EUidPixelFormatXBGR_4444:
+ return 16;
+ case EUidPixelFormatBGR_888:
+ case EUidPixelFormatRGB_888:
+ return 24;
+ case EUidPixelFormatXRGB_8888:
+ case EUidPixelFormatBGRX_8888:
+ case EUidPixelFormatXBGR_8888:
+ case EUidPixelFormatBGRA_8888:
+ case EUidPixelFormatARGB_8888:
+ case EUidPixelFormatABGR_8888:
+ case EUidPixelFormatARGB_8888_PRE:
+ case EUidPixelFormatABGR_8888_PRE:
+ case EUidPixelFormatBGRA_8888_PRE:
+ case EUidPixelFormatARGB_2101010:
+ case EUidPixelFormatABGR_2101010:
+ return 32;
+ default:
+ return 32;
+ };
+}
+
+void QGLPixmapData::fromNativeType(void* pixmap, NativeType type)
+{
+ if (type == QPixmapData::SgImage && pixmap) {
+#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
+ RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);
+
+ m_sgImage = new RSgImage;
+ m_sgImage->Open(sgImage->Id());
+
+ TSgImageInfo info;
+ sgImage->GetInfo(info);
+
+ w = info.iSizeInPixels.iWidth;
+ h = info.iSizeInPixels.iHeight;
+ d = symbianPixeFormatBitsPerPixel((TUidPixelFormat)info.iPixelFormat);
+
+ m_source = QVolatileImage();
+ m_hasAlpha = true;
+ m_hasFillColor = false;
+ m_dirty = true;
+ is_null = (w <= 0 || h <= 0);
+#endif
+ } else if (type == QPixmapData::FbsBitmap && pixmap) {
+ CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap);
+ QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight);
+ if (size.width() == w && size.height() == h)
+ setSerialNumber(++qt_gl_pixmap_serial);
+ resize(size.width(), size.height());
+ m_source = QVolatileImage(bitmap);
+ if (pixelType() == BitmapType) {
+ m_source.ensureFormat(QImage::Format_MonoLSB);
+ } else if (!knownGoodFormat(m_source.format())) {
+ m_source.beginDataAccess();
+ QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor);
+ m_source.endDataAccess(true);
+ m_source.ensureFormat(format);
+ }
+ m_hasAlpha = m_source.hasAlphaChannel();
+ m_hasFillColor = false;
+ m_dirty = true;
+ d = m_source.depth();
+ } else if (type == QPixmapData::VolatileImage && pixmap) {
+ // Support QS60Style in more efficient skin graphics retrieval.
+ QVolatileImage *img = static_cast<QVolatileImage *>(pixmap);
+ if (img->width() == w && img->height() == h)
+ setSerialNumber(++qt_gl_pixmap_serial);
+ resize(img->width(), img->height());
+ m_source = *img;
+ m_hasAlpha = m_source.hasAlphaChannel();
+ m_hasFillColor = false;
+ m_dirty = true;
+ d = m_source.depth();
+ } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) {
+ destroyTexture();
+ nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap);
+ // Cannot defer the retrieval, we need at least the size right away.
+ createFromNativeImageHandleProvider();
+ }
+}
+
+void* QGLPixmapData::toNativeType(NativeType type)
+{
+ if (type == QPixmapData::FbsBitmap) {
+ if (m_source.isNull())
+ m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ return m_source.duplicateNativeImage();
+ }
+
+ return 0;
+}
+
+bool QGLPixmapData::initFromNativeImageHandle(void *handle, const QString &type)
+{
+ if (type == QLatin1String("RSgImage")) {
+ fromNativeType(handle, QPixmapData::SgImage);
+ return true;
+ } else if (type == QLatin1String("CFbsBitmap")) {
+ fromNativeType(handle, QPixmapData::FbsBitmap);
+ return true;
+ }
+ return false;
+}
+
+void QGLPixmapData::createFromNativeImageHandleProvider()
+{
+ void *handle = 0;
+ QString type;
+ nativeImageHandleProvider->get(&handle, &type);
+ if (handle) {
+ if (initFromNativeImageHandle(handle, type)) {
+ nativeImageHandle = handle;
+ nativeImageType = type;
+ } else {
+ qWarning("QGLPixmapData: Unknown native image type '%s'", qPrintable(type));
+ }
+ } else {
+ qWarning("QGLPixmapData: Native handle is null");
+ }
+}
+
+void QGLPixmapData::releaseNativeImageHandle()
+{
+ if (nativeImageHandleProvider && nativeImageHandle) {
+ nativeImageHandleProvider->release(nativeImageHandle, nativeImageType);
+ nativeImageHandle = 0;
+ nativeImageType = QString();
+ }
}
QT_END_NAMESPACE
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 17b2044..b48fe2c 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -184,7 +184,7 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL)
class QGLGlobalShareWidget
{
public:
- QGLGlobalShareWidget() : refCount(0), widget(0), initializing(false) {}
+ QGLGlobalShareWidget() : widget(0), initializing(false) {}
QGLWidget *shareWidget() {
if (!initializing && !widget && !cleanedUp) {
@@ -223,7 +223,6 @@ public:
}
static bool cleanedUp;
- int refCount;
private:
QGLWidget *widget;
@@ -354,14 +353,10 @@ QGLWindowSurface::~QGLWindowSurface()
if (QGLGlobalShareWidget::cleanedUp)
return;
- --(_qt_gl_share_widget()->refCount);
-
#ifdef Q_OS_SYMBIAN
- if (_qt_gl_share_widget()->refCount <= 0) {
// Destroy the context if necessary.
if (!qt_gl_share_widget()->context()->isSharing())
qt_destroy_gl_share_widget();
- }
#endif
}
@@ -410,9 +405,6 @@ void QGLWindowSurface::hijackWindow(QWidget *widget)
ctx->create(qt_gl_share_widget()->context());
- if (widget != qt_gl_share_widget())
- ++(_qt_gl_share_widget()->refCount);
-
#ifndef QT_NO_EGL
static bool checkedForNOKSwapRegion = false;
static bool haveNOKSwapRegion = false;
@@ -719,6 +711,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
} else {
+#ifndef Q_OS_SYMBIAN // We don't have FBO pool on Symbian
// can't do sub-region blits with multisample FBOs
QGLFramebufferObject *temp = qgl_fbo_pool()->acquire(d_ptr->fbo->size(), QGLFramebufferObjectFormat());
@@ -741,6 +734,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
qgl_fbo_pool()->release(temp);
+#endif // Q_OS_SYMBIAN
}
ctx->d_ptr->current_fbo = 0;
@@ -823,18 +817,43 @@ void QGLWindowSurface::updateGeometry() {
if (wd->extraData() && wd->extraData()->glContext) {
#ifdef Q_OS_SYMBIAN // Symbian needs to recreate the context when native window size changes
if (d_ptr->size != geometry().size()) {
- if (window() != qt_gl_share_widget())
- --(_qt_gl_share_widget()->refCount);
+ QGLContext *ctx = reinterpret_cast<QGLContext *>(wd->extraData()->glContext);
+
+ if (ctx == QGLContext::currentContext())
+ ctx->doneCurrent();
- delete wd->extraData()->glContext;
- wd->extraData()->glContext = 0;
- d_ptr->ctx = 0;
+ ctx->d_func()->destroyEglSurfaceForDevice();
+
+ // Delete other contexts (shouldn't happen too often, if at all)
+ while (d_ptr->contexts.size()) {
+ QGLContext **ctxPtrPtr = d_ptr->contexts.takeFirst();
+ if ((*ctxPtrPtr) != ctx)
+ delete *ctxPtrPtr;
+ }
+ union { QGLContext **ctxPtrPtr; void **voidPtrPtr; };
+ voidPtrPtr = &wd->extraData()->glContext;
+ d_ptr->contexts << ctxPtrPtr;
+
+ ctx->d_func()->eglSurface = ctx->d_func()->eglContext->createSurface(window());
+
+ // Partial update supported has been decided already in previous hijackWindow call.
+ // Reset swap behaviour based on that flag.
+ if (hasPartialUpdateSupport()) {
+ eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurfaceForDevice(),
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+
+ if (eglGetError() != EGL_SUCCESS)
+ qWarning("QGLWindowSurface::updateGeometry() - could not re-enable preserved swap behaviour");
+ } else {
+ eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurfaceForDevice(),
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+
+ if (eglGetError() != EGL_SUCCESS)
+ qWarning("QGLWindowSurface::updateGeometry() - could not re-enable destroyed swap behaviour");
+ }
}
- else
#endif
- {
- hijack = false; // we already have gl context for widget
- }
+ hijack = false; // we already have gl context for widget
}
if (hijack)