Skip to content

Commit

Permalink
Change the pooled QGLPixmapData to be backed by QVolatileImage.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Laszlo Agocs committed Mar 21, 2011
1 parent 589fb78 commit 9204b29
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 141 deletions.
140 changes: 42 additions & 98 deletions src/opengl/qgl_symbian.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -72,6 +70,8 @@ QT_BEGIN_NAMESPACE
#endif
#endif

extern int qt_gl_pixmap_serial;

/*
QGLTemporaryContext implementation
*/
Expand Down Expand Up @@ -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

9 changes: 9 additions & 0 deletions src/opengl/qpixmapdata_gl_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -153,6 +157,7 @@ class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData
#endif

#ifdef Q_OS_SYMBIAN
QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags);
void* toNativeType(NativeType type);
void fromNativeType(void* pixmap, NativeType type);
#endif
Expand Down Expand Up @@ -184,7 +189,11 @@ class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData
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
Expand Down
Loading

0 comments on commit 9204b29

Please sign in to comment.