summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-03-21 11:33:08 (GMT)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-03-21 11:35:08 (GMT)
commit9204b29b05cba62d64bf189d30b72b93f1693bbf (patch)
treee32220e12e751f5ab89aacfb822e0f402b493354 /src/opengl
parent589fb7812ac81192a7013c0b186354f121118398 (diff)
downloadQt-9204b29b05cba62d64bf189d30b72b93f1693bbf.zip
Qt-9204b29b05cba62d64bf189d30b72b93f1693bbf.tar.gz
Qt-9204b29b05cba62d64bf189d30b72b93f1693bbf.tar.bz2
Change the pooled QGLPixmapData to be backed by QVolatileImage.
This change currently affects QGLPixmapData on Symbian only. Similarly to the OpenVG engine, using QVolatileImage allows more efficient handling of to- and fromSymbianCFbsBitmap, reduces local heap usage, and improves s60 style performance. Task-number: QTBUG-15252 Reviewed-by: Jani Hautakangas
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qgl_symbian.cpp140
-rw-r--r--src/opengl/qpixmapdata_gl_p.h9
-rw-r--r--src/opengl/qpixmapdata_poolgl.cpp118
3 files changed, 126 insertions, 141 deletions
diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp
index 2978514..78624a2 100644
--- a/src/opengl/qgl_symbian.cpp
+++ b/src/opengl/qgl_symbian.cpp
@@ -41,9 +41,7 @@
#include "qgl.h"
-#include <coemain.h>
-#include <coecntrl.h>
-#include <w32std.h>
+#include <fbs.h>
#include <private/qt_s60_p.h>
#include <private/qpixmap_s60_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
@@ -72,6 +70,8 @@ QT_BEGIN_NAMESPACE
#endif
#endif
+extern int qt_gl_pixmap_serial;
+
/*
QGLTemporaryContext implementation
*/
@@ -361,117 +361,61 @@ void QGLWidgetPrivate::recreateEglSurface()
eglSurfaceWindowId = currentId;
}
-/*
- * Symbian specific QGLPixmapData functions
- */
-
-static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap)
+static inline bool knownGoodFormat(QImage::Format format)
{
- CFbsBitmap *copy = q_check_ptr(new CFbsBitmap);
- if (!copy)
- return 0;
-
- if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) {
- delete copy;
- copy = 0;
-
- return 0;
+ switch (format) {
+ case QImage::Format_RGB16: // EColor64K
+ case QImage::Format_RGB32: // EColor16MU
+ case QImage::Format_ARGB32_Premultiplied: // EColor16MAP
+ return true;
+ default:
+ return false;
}
-
- CFbsBitmapDevice* bitmapDevice = 0;
- CFbsBitGc *bitmapGc = 0;
- QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy));
- QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL());
- bitmapGc->Activate(bitmapDevice);
-
- bitmapGc->BitBlt(TPoint(), bitmap);
-
- delete bitmapGc;
- delete bitmapDevice;
-
- return copy;
}
void QGLPixmapData::fromNativeType(void* pixmap, NativeType type)
{
if (type == QPixmapData::FbsBitmap) {
- CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
-
- bool deleteSourceBitmap = false;
-#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
-
- // Rasterize extended bitmaps
-
- TUid extendedBitmapType = bitmap->ExtendedBitmapType();
- if (extendedBitmapType != KNullUid) {
- bitmap = createBlitCopy(bitmap);
- deleteSourceBitmap = true;
- }
-#endif
-
- if (bitmap->IsCompressedInRAM()) {
- bitmap = createBlitCopy(bitmap);
- deleteSourceBitmap = true;
+ 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);
}
-
- TDisplayMode displayMode = bitmap->DisplayMode();
- QImage::Format format = qt_TDisplayMode2Format(displayMode);
-
- TSize size = bitmap->SizeInPixels();
- int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode);
-
- bitmap->BeginDataAccess();
- uchar *bytes = (uchar*)bitmap->DataAddress();
- QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format);
- img = img.copy();
- bitmap->EndDataAccess();
-
- if (displayMode == EGray2) {
- //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
- //So invert mono bitmaps so that masks work correctly.
- img.invertPixels();
- } else if (displayMode == EColor16M) {
- img = img.rgbSwapped(); // EColor16M is BGR
- }
-
- fromImage(img, Qt::AutoColor);
-
- if (deleteSourceBitmap)
- delete bitmap;
+ 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;
}
}
void* QGLPixmapData::toNativeType(NativeType type)
{
if (type == QPixmapData::FbsBitmap) {
- CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);
-
- if (bitmap) {
- QImage image = toImage();
-
- TDisplayMode displayMode(EColor16MU);
- if (image.format()==QImage::Format_ARGB32_Premultiplied)
- displayMode = EColor16MAP;
-
- if (bitmap->Create(TSize(image.width(), image.height()),
- displayMode) == KErrNone) {
- const uchar *sptr = const_cast<const QImage&>(image).bits();
- bitmap->BeginDataAccess();
-
- uchar *dptr = (uchar*)bitmap->DataAddress();
- Mem::Copy(dptr, sptr, image.byteCount());
-
- bitmap->EndDataAccess();
- } else {
- delete bitmap;
- bitmap = 0;
- }
- }
-
- return reinterpret_cast<void*>(bitmap);
+ if (m_source.isNull())
+ m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ return m_source.duplicateNativeImage();
}
+
return 0;
}
QT_END_NAMESPACE
-
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index 55cc29d..41740dd 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -59,6 +59,10 @@
#include "private/qpixmapdata_p.h"
#include "private/qglpaintdevice_p.h"
+#ifdef Q_OS_SYMBIAN
+#include "private/qvolatileimage_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
class QPaintEngine;
@@ -153,6 +157,7 @@ public:
#endif
#ifdef Q_OS_SYMBIAN
+ QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags);
void* toNativeType(NativeType type);
void fromNativeType(void* pixmap, NativeType type);
#endif
@@ -184,7 +189,11 @@ private:
mutable QGLFramebufferObject *m_renderFbo;
mutable QPaintEngine *m_engine;
mutable QGLContext *m_ctx;
+#ifdef Q_OS_SYMBIAN
+ mutable QVolatileImage m_source;
+#else
mutable QImage m_source;
+#endif
mutable QGLTexture m_texture;
// the texture is not in sync with the source image
diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_poolgl.cpp
index f1220b1..64de29e 100644
--- a/src/opengl/qpixmapdata_poolgl.cpp
+++ b/src/opengl/qpixmapdata_poolgl.cpp
@@ -247,7 +247,7 @@ void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
data = d;
}
-static int qt_gl_pixmap_serial = 0;
+int qt_gl_pixmap_serial = 0;
QGLPixmapData::QGLPixmapData(PixelType type)
: QPixmapData(type, OpenGLClass)
@@ -330,7 +330,7 @@ void QGLPixmapData::resize(int width, int height)
destroyTexture();
- m_source = QImage();
+ m_source = QVolatileImage();
m_dirty = isValid();
setSerialNumber(++qt_gl_pixmap_serial);
}
@@ -353,6 +353,11 @@ void QGLPixmapData::ensureCreated() const
#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;
+
m_texture.options &= ~QGLContext::MemoryManagedBindOption;
if (!m_texture.id) {
@@ -361,7 +366,7 @@ void QGLPixmapData::ensureCreated() const
0, internal_format,
w, h,
external_format,
- GL_UNSIGNED_BYTE,
+ type,
const_cast<QGLPixmapData*>(this));
if (!m_texture.id) {
failedToAlloc = true;
@@ -378,21 +383,35 @@ void QGLPixmapData::ensureCreated() const
if (!m_source.isNull() && m_texture.id) {
if (external_format == GL_RGB) {
- const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true);
+ 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);
glBindTexture(target, m_texture.id);
- glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
- GL_UNSIGNED_BYTE, tx.bits());
+ 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
- const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
+ 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);
- glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
- GL_UNSIGNED_BYTE, tx.bits());
+ 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);
}
if (useFramebufferObjects())
- m_source = QImage();
+ m_source = QVolatileImage();
}
}
@@ -437,7 +456,7 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format,
is_null = false;
d = 32;
m_hasAlpha = alpha;
- m_source = QImage();
+ m_source = QVolatileImage();
m_dirty = isValid();
return true;
}
@@ -469,7 +488,7 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
is_null = false;
d = 32;
m_hasAlpha = alpha;
- m_source = QImage();
+ m_source = QVolatileImage();
m_dirty = isValid();
return true;
}
@@ -487,9 +506,20 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
return !isNull();
}
-/*!
- out-of-place conversion (inPlace == false) will always detach()
- */
+QImage::Format QGLPixmapData::idealFormat(QImage &image, Qt::ImageConversionFlags flags)
+{
+ QImage::Format format = QImage::Format_RGB32;
+ if (qApp->desktop()->depth() == 16)
+ format = QImage::Format_RGB16;
+
+ if (image.hasAlphaChannel()
+ && ((flags & Qt::NoOpaqueDetection)
+ || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
+ format = QImage::Format_ARGB32_Premultiplied;
+
+ return format;
+}
+
void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
{
if (image.size() == QSize(w, h))
@@ -498,26 +528,25 @@ void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags
resize(image.width(), image.height());
if (pixelType() == BitmapType) {
- m_source = image.convertToFormat(QImage::Format_MonoLSB);
+ QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB);
+ if (image.format() == QImage::Format_MonoLSB)
+ convertedImage.detach();
- } else {
- QImage::Format format = QImage::Format_RGB32;
- if (qApp->desktop()->depth() == 16)
- format = QImage::Format_RGB16;
+ m_source = QVolatileImage(convertedImage);
- if (image.hasAlphaChannel()
- && ((flags & Qt::NoOpaqueDetection)
- || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
- format = QImage::Format_ARGB32_Premultiplied;
+ } else {
+ QImage::Format format = idealFormat(image, flags);
if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
- m_source = image;
+ m_source = QVolatileImage(image);
} else {
- m_source = image.convertToFormat(format);
+ QImage convertedImage = image.convertToFormat(format);
// convertToFormat won't detach the image if format stays the same.
if (image.format() == format)
- m_source.detach();
+ convertedImage.detach();
+
+ m_source = QVolatileImage(convertedImage);
}
}
@@ -596,16 +625,13 @@ void QGLPixmapData::fill(const QColor &color)
}
if (useFramebufferObjects()) {
- m_source = QImage();
+ m_source = QVolatileImage();
m_hasFillColor = true;
m_fillColor = color;
} else {
+ forceToImage();
- if (m_source.isNull()) {
- m_fillColor = color;
- m_hasFillColor = true;
-
- } else if (m_source.depth() == 32) {
+ if (m_source.depth() == 32) {
m_source.fill(PREMUL(color.rgba()));
} else if (m_source.depth() == 1) {
@@ -656,13 +682,15 @@ QImage QGLPixmapData::toImage() const
if (m_renderFbo) {
copyBackFromRenderFbo(true);
} else if (!m_source.isNull()) {
- QImageData *data = const_cast<QImage &>(m_source).data_ptr();
- if (data->paintEngine && data->paintEngine->isActive()
- && data->paintEngine->paintDevice() == &m_source)
- {
- return m_source.copy();
+ // QVolatileImage::toImage() will make a copy always so no check
+ // for active painting is needed.
+ QImage img = m_source.toImage();
+ if (img.format() == QImage::Format_MonoLSB) {
+ img.setColorCount(2);
+ img.setColor(0, QColor(Qt::color0).rgba());
+ img.setColor(1, QColor(Qt::color1).rgba());
}
- return m_source;
+ return img;
} else if (m_dirty || m_hasFillColor) {
return fillImage(m_fillColor);
} else {
@@ -802,7 +830,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const
if (m_hasFillColor) {
if (!useFramebufferObjects()) {
- m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
m_source.fill(PREMUL(m_fillColor.rgba()));
}
@@ -811,7 +839,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const
GLenum format = qt_gl_preferredTextureFormat();
QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits());
}
return id;
@@ -888,8 +916,12 @@ void QGLPixmapData::forceToImage()
if (!isValid())
return;
- if (m_source.isNull())
- m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ if (m_source.isNull()) {
+ QImage::Format format = QImage::Format_ARGB32_Premultiplied;
+ if (pixelType() == BitmapType)
+ format = QImage::Format_MonoLSB;
+ m_source = QVolatileImage(w, h, format);
+ }
m_dirty = true;
}