summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qgl_symbian.cpp114
-rw-r--r--src/opengl/qpixmapdata_gl.cpp159
-rw-r--r--src/opengl/qpixmapdata_gl_p.h9
-rw-r--r--src/opengl/qwindowsurface_gl.cpp54
4 files changed, 266 insertions, 70 deletions
diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp
index 82b66f5..a9e2248 100644
--- a/src/opengl/qgl_symbian.cpp
+++ b/src/opengl/qgl_symbian.cpp
@@ -44,12 +44,14 @@
#include <coemain.h>
#include <coecntrl.h>
#include <w32std.h>
+#include <private/qt_s60_p.h>
#include <private/qpixmap_s60_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
#include <private/qgl_p.h>
#include <private/qpaintengine_opengl_p.h>
#include <private/qwidget_p.h> // to access QWExtra
#include "qgl_egl_p.h"
+#include "qpixmapdata_gl_p.h"
#include "qcolormap.h"
#include <QDebug>
@@ -358,5 +360,117 @@ void QGLWidgetPrivate::recreateEglSurface()
eglSurfaceWindowId = currentId;
}
+/*
+ * Symbian specific QGLPixmapData functions
+ */
+
+static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap)
+{
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+}
+
+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);
+ }
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 43e80c1..70427d5 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -55,10 +55,11 @@
#include <qdesktopwidget.h>
#include <qfile.h>
#include <qimagereader.h>
+#include <qbuffer.h>
QT_BEGIN_NAMESPACE
-extern QGLWidget* qt_gl_share_widget();
+Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
/*!
\class QGLFramebufferObjectPool
@@ -369,40 +370,18 @@ void QGLPixmapData::ensureCreated() const
void QGLPixmapData::fromImage(const QImage &image,
Qt::ImageConversionFlags flags)
{
- if (image.size() == QSize(w, h))
- setSerialNumber(++qt_gl_pixmap_serial);
- resize(image.width(), image.height());
-
- if (pixelType() == BitmapType) {
- m_source = image.convertToFormat(QImage::Format_MonoLSB);
-
- } else {
- 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;;
-
- m_source = image.convertToFormat(format);
- }
-
- m_dirty = true;
- m_hasFillColor = false;
+ QImage img = image;
+ createPixmapForImage(img, flags, false);
+}
- m_hasAlpha = m_source.hasAlphaChannel();
- w = image.width();
- h = image.height();
- is_null = (w <= 0 || h <= 0);
- d = m_source.depth();
+void QGLPixmapData::fromImageReader(QImageReader *imageReader,
+ Qt::ImageConversionFlags flags)
+{
+ QImage image = imageReader->read();
+ if (image.isNull())
+ return;
- if (m_texture.id) {
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
- glDeleteTextures(1, &m_texture.id);
- m_texture.id = 0;
- }
+ createPixmapForImage(image, flags, true);
}
bool QGLPixmapData::fromFile(const QString &filename, const char *format,
@@ -411,31 +390,37 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format,
if (pixelType() == QPixmapData::BitmapType)
return QPixmapData::fromFile(filename, format, flags);
QFile file(filename);
- if (!file.open(QIODevice::ReadOnly))
- return false;
- QByteArray data = file.peek(64);
- bool alpha;
- if (m_texture.canBindCompressedTexture
- (data.constData(), data.size(), format, &alpha)) {
- resize(0, 0);
- data = file.readAll();
- file.close();
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
- QSize size = m_texture.bindCompressedTexture
- (data.constData(), data.size(), format);
- if (!size.isEmpty()) {
- w = size.width();
- h = size.height();
- is_null = false;
- d = 32;
- m_hasAlpha = alpha;
- m_source = QImage();
- m_dirty = isValid();
- return true;
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray data = file.peek(64);
+ bool alpha;
+ if (m_texture.canBindCompressedTexture
+ (data.constData(), data.size(), format, &alpha)) {
+ resize(0, 0);
+ data = file.readAll();
+ file.close();
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ QSize size = m_texture.bindCompressedTexture
+ (data.constData(), data.size(), format);
+ if (!size.isEmpty()) {
+ w = size.width();
+ h = size.height();
+ is_null = false;
+ d = 32;
+ m_hasAlpha = alpha;
+ m_source = QImage();
+ m_dirty = isValid();
+ return true;
+ }
+ return false;
}
- return false;
}
- fromImage(QImageReader(&file, format).read(), flags);
+
+ QImage image = QImageReader(filename, format).read();
+ if (image.isNull())
+ return false;
+
+ createPixmapForImage(image, flags, true);
+
return !isNull();
}
@@ -459,7 +444,67 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
return true;
}
}
- return QPixmapData::fromData(buffer, len, format, flags);
+
+ QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
+ QBuffer b(&a);
+ b.open(QIODevice::ReadOnly);
+ QImage image = QImageReader(&b, format).read();
+ if (image.isNull())
+ return false;
+
+ createPixmapForImage(image, flags, true);
+
+ return !isNull();
+}
+
+/*!
+ out-of-place conversion (inPlace == false) will always detach()
+ */
+void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
+{
+ if (image.size() == QSize(w, h))
+ setSerialNumber(++qt_gl_pixmap_serial);
+
+ resize(image.width(), image.height());
+
+ if (pixelType() == BitmapType) {
+ m_source = image.convertToFormat(QImage::Format_MonoLSB);
+
+ } else {
+ 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;;
+
+ if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
+ m_source = image;
+ } else {
+ m_source = image.convertToFormat(format);
+
+ // convertToFormat won't detach the image if format stays the same.
+ if (image.format() == format)
+ m_source.detach();
+ }
+ }
+
+ m_dirty = true;
+ m_hasFillColor = false;
+
+ m_hasAlpha = m_source.hasAlphaChannel();
+ w = image.width();
+ h = image.height();
+ is_null = (w <= 0 || h <= 0);
+ d = m_source.depth();
+
+ if (m_texture.id) {
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ glDeleteTextures(1, &m_texture.id);
+ m_texture.id = 0;
+ }
}
bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index 5545d3c..a4066fd 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -107,6 +107,8 @@ public:
// Re-implemented from QPixmapData:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ void fromImageReader(QImageReader *imageReader,
+ Qt::ImageConversionFlags flags);
bool fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags);
bool fromData(const uchar *buffer, uint len, const char *format,
@@ -127,6 +129,11 @@ public:
GLuint bind(bool copyBack = true) const;
QGLTexture *texture() const;
+#if defined(Q_OS_SYMBIAN)
+ void* toNativeType(NativeType type);
+ void fromNativeType(void* pixmap, NativeType type);
+#endif
+
private:
bool isValid() const;
@@ -149,6 +156,8 @@ private:
QImage fillImage(const QColor &color) const;
+ void createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace);
+
mutable QGLFramebufferObject *m_renderFbo;
mutable QPaintEngine *m_engine;
mutable QGLContext *m_ctx;
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index aad12d7..0bffbda 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -776,32 +776,60 @@ void QGLWindowSurface::updateGeometry() {
return;
d_ptr->geometry_updated = false;
- QRect rect = geometry();
- hijackWindow(window());
- QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
+ bool hijack(true);
+ QWidgetPrivate *wd = window()->d_func();
+ if (wd->extraData() && wd->extraData()->glContext)
+ hijack = false; // we already have gl context for widget
+
+ if (hijack)
+ hijackWindow(window());
+
+ QGLContext *ctx = reinterpret_cast<QGLContext *>(wd->extraData()->glContext);
#ifdef Q_WS_MAC
ctx->updatePaintDevice();
#endif
- const GLenum target = GL_TEXTURE_2D;
+ QSize surfSize = geometry().size();
- if (rect.width() <= 0 || rect.height() <= 0)
+ if (surfSize.width() <= 0 || surfSize.height() <= 0)
return;
- if (d_ptr->size == rect.size())
+ if (d_ptr->size == surfSize)
return;
- d_ptr->size = rect.size();
+ d_ptr->size = surfSize;
+
+#ifdef Q_OS_SYMBIAN
+ if (!hijack) { // Symbian needs to recreate EGL surface when native window size changes
+ if (ctx->d_func()->eglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(ctx->d_func()->eglContext->display(),
+ ctx->d_func()->eglSurface);
+ }
+
+ ctx->d_func()->eglSurface = QEgl::createSurface(ctx->device(),
+ ctx->d_func()->eglContext->config());
+
+#if !defined(QGL_NO_PRESERVED_SWAP)
+ eglGetError(); // Clear error state first.
+ eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurface,
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+ if (eglGetError() != EGL_SUCCESS) {
+ qWarning("QGLWindowSurface: could not restore preserved swap behaviour");
+ }
+#endif
+ }
+#endif
if (d_ptr->ctx) {
#ifndef QT_OPENGL_ES_2
if (d_ptr->destructive_swap_buffers)
- initializeOffscreenTexture(rect.size());
+ initializeOffscreenTexture(surfSize);
#endif
return;
}
+ const GLenum target = GL_TEXTURE_2D;
if (d_ptr->destructive_swap_buffers
&& (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject)
&& (d_ptr->fbo || !d_ptr->tried_fbo)
@@ -820,10 +848,10 @@ void QGLWindowSurface::updateGeometry() {
if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)
format.setSamples(8);
- d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);
+ d_ptr->fbo = new QGLFramebufferObject(surfSize, format);
if (d_ptr->fbo->isValid()) {
- qDebug() << "Created Window Surface FBO" << rect.size()
+ qDebug() << "Created Window Surface FBO" << surfSize
<< "with samples" << d_ptr->fbo->format().samples();
return;
} else {
@@ -844,7 +872,7 @@ void QGLWindowSurface::updateGeometry() {
delete d_ptr->pb;
- d_ptr->pb = new QGLPixelBuffer(rect.width(), rect.height(),
+ d_ptr->pb = new QGLPixelBuffer(surfSize.width(), surfSize.height(),
QGLFormat(QGL::SampleBuffers | QGL::StencilBuffer | QGL::DepthBuffer),
qt_gl_share_widget());
@@ -854,7 +882,7 @@ void QGLWindowSurface::updateGeometry() {
glGenTextures(1, &d_ptr->pb_tex_id);
glBindTexture(target, d_ptr->pb_tex_id);
- glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -878,7 +906,7 @@ void QGLWindowSurface::updateGeometry() {
#ifndef QT_OPENGL_ES_2
if (d_ptr->destructive_swap_buffers)
- initializeOffscreenTexture(rect.size());
+ initializeOffscreenTexture(surfSize);
#endif
qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;