summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
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;
}