summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/hybrid/hybridsurface.cpp')
-rw-r--r--src/plugins/gfxdrivers/hybrid/hybridsurface.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp b/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp
new file mode 100644
index 0000000..7281328
--- /dev/null
+++ b/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hybridsurface.h"
+
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qwslock_p.h>
+#include <qscreen_qws.h>
+#include <qvarlengtharray.h>
+
+static void error(const char *message)
+{
+ const EGLint error = eglGetError();
+ qWarning("HybridSurface error: %s: 0x%x", message, error);
+}
+
+static void imgToVanilla(const QImage *img, VanillaPixmap *pix)
+{
+ pix->width = img->width();
+ pix->height = img->height();
+ pix->stride = img->bytesPerLine();
+
+ if (img->depth() == 32) {
+ pix->rSize = pix->gSize = pix->bSize = pix->aSize = 8;
+ pix->lSize = 0;
+ pix->rOffset = 16;
+ pix->gOffset = 8;
+ pix->bOffset = 0;
+ pix->aOffset = 24;
+ } else if (img->format() == QImage::Format_RGB16) {
+ pix->rSize = 5;
+ pix->gSize = 6;
+ pix->bSize = 5;
+ pix->aSize = 0;
+ pix->lSize = 0;
+ pix->rOffset = 11;
+ pix->gOffset = 5;
+ pix->bOffset = 0;
+ pix->aOffset = 0;
+ }
+
+ pix->padding = pix->padding2 = 0;
+ pix->pixels = const_cast<uchar*>(img->bits());
+}
+
+HybridSurface::HybridSurface()
+ : QWSGLWindowSurface(), memlock(0)
+{
+ setSurfaceFlags(Buffered | Opaque);
+}
+
+HybridSurface::HybridSurface(QWidget *w, EGLDisplay disp)
+ : QWSGLWindowSurface(w), memlock(0), display(disp), config(0),
+ surface(EGL_NO_SURFACE), context(EGL_NO_CONTEXT),
+ pdevice(new QWSGLPaintDevice(w))
+{
+ setSurfaceFlags(Buffered | Opaque);
+
+ EGLint configAttribs[] = {
+ EGL_RED_SIZE, 0,
+ EGL_GREEN_SIZE, 0,
+ EGL_BLUE_SIZE, 0,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE, EGL_NONE
+ };
+
+
+ EGLBoolean status;
+ EGLint numConfigs;
+ status = eglChooseConfig(display, configAttribs, 0, 0, &numConfigs);
+ if (!status) {
+ error("chooseConfig");
+ return;
+ }
+
+ //If there isn't any configuration good enough
+ if (numConfigs < 1) {
+ error("chooseConfig, no matching configurations found");
+ return;
+ }
+
+ QVarLengthArray<EGLConfig> configs(numConfigs);
+
+ status = eglChooseConfig(display, configAttribs, configs.data(),
+ numConfigs, &numConfigs);
+ if (!status) {
+ error("chooseConfig");
+ return;
+ }
+
+ // hw: if used on an image buffer we need to check whether the resulting
+ // configuration matches our requirements exactly!
+ config = configs[0];
+
+ context = eglCreateContext(display, config, 0, 0);
+ //(shareContext ? shareContext->d_func()->cx : 0),
+ //configAttribs);
+ if (context == EGL_NO_CONTEXT)
+ error("eglCreateContext");
+
+}
+
+HybridSurface::~HybridSurface()
+{
+}
+
+bool HybridSurface::isValid() const
+{
+ return true;
+}
+
+void HybridSurface::setGeometry(const QRect &rect, const QRegion &mask)
+{
+ const QSize size = rect.size();
+ if (img.size() != size) {
+// QWidget *win = window();
+ QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied;
+ const int bytesPerPixel = 4;
+
+ const int bpl = (size.width() * bytesPerPixel + 3) & ~3;
+ const int imagesize = bpl * size.height();
+
+ if (imagesize == 0) {
+ eglDestroySurface(display, surface);
+ mem.detach();
+ img = QImage();
+ } else {
+ mem.detach();
+ if (!mem.create(imagesize)) {
+ perror("HybridSurface::setGeometry allocating shared memory");
+ qFatal("Error creating shared memory of size %d", imagesize);
+ }
+ uchar *base = static_cast<uchar*>(mem.address());
+ img = QImage(base, size.width(), size.height(), imageFormat);
+// setImageMetrics(img, win);
+
+ imgToVanilla(&img, &vanillaPix);
+ surface = eglCreatePixmapSurface(display, config, &vanillaPix, 0);
+ if (surface == EGL_NO_SURFACE)
+ error("setGeometry:eglCreatePixmapSurface");
+
+ }
+ }
+ QWSWindowSurface::setGeometry(rect, mask);
+}
+
+QByteArray HybridSurface::permanentState() const
+{
+ QByteArray array;
+ array.resize(4 * sizeof(int) + sizeof(QImage::Format) +
+ sizeof(SurfaceFlags));
+
+ char *ptr = array.data();
+
+ reinterpret_cast<int*>(ptr)[0] = mem.id();
+ reinterpret_cast<int*>(ptr)[1] = img.width();
+ reinterpret_cast<int*>(ptr)[2] = img.height();
+ reinterpret_cast<int*>(ptr)[3] = (memlock ? memlock->id() : -1);
+ ptr += 4 * sizeof(int);
+
+ *reinterpret_cast<QImage::Format*>(ptr) = img.format();
+ ptr += sizeof(QImage::Format);
+
+ *reinterpret_cast<SurfaceFlags*>(ptr) = surfaceFlags();
+
+ return array;
+}
+
+void HybridSurface::setPermanentState(const QByteArray &data)
+{
+ int memId;
+ int width;
+ int height;
+ int lockId;
+ QImage::Format format;
+ SurfaceFlags flags;
+
+ const char *ptr = data.constData();
+
+ memId = reinterpret_cast<const int*>(ptr)[0];
+ width = reinterpret_cast<const int*>(ptr)[1];
+ height = reinterpret_cast<const int*>(ptr)[2];
+ lockId = reinterpret_cast<const int*>(ptr)[3];
+ ptr += 4 * sizeof(int);
+
+ format = *reinterpret_cast<const QImage::Format*>(ptr);
+ ptr += sizeof(QImage::Format);
+ flags = *reinterpret_cast<const SurfaceFlags*>(ptr);
+
+ setSurfaceFlags(flags);
+
+// setMemory(memId);
+ if (mem.id() != memId) {
+ mem.detach();
+ if (!mem.attach(memId)) {
+ perror("QWSSharedMemSurface: attaching to shared memory");
+ qCritical("QWSSharedMemSurface: Error attaching to"
+ " shared memory 0x%x", memId);
+ }
+ }
+
+// setLock(lockId);
+ if (!memlock || memlock->id() == lockId) {
+ delete memlock;
+ memlock = (lockId == -1 ? 0 : new QWSLock(lockId));
+ }
+
+ uchar *base = static_cast<uchar*>(mem.address());
+ img = QImage(base, width, height, format);
+}
+
+QImage HybridSurface::image() const
+{
+ return img;
+}
+
+QPaintDevice* HybridSurface::paintDevice()
+{
+ return pdevice;
+}
+
+void HybridSurface::beginPaint(const QRegion &region)
+{
+ QWSGLWindowSurface::beginPaint(region);
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ EGLBoolean ok = eglMakeCurrent(display, surface, surface, context);
+ if (!ok)
+ error("qglMakeCurrent");
+}
+
+bool HybridSurface::lock(int timeout)
+{
+ Q_UNUSED(timeout);
+ if (!memlock)
+ return true;
+ return memlock->lock(QWSLock::BackingStore);
+}
+
+void HybridSurface::unlock()
+{
+ if (memlock)
+ memlock->unlock(QWSLock::BackingStore);
+}
+
+QPoint HybridSurface::painterOffset() const
+{
+ const QWidget *w = window();
+ if (!w)
+ return QPoint();
+
+ if (w->mask().isEmpty())
+ return QWSWindowSurface::painterOffset();
+
+ const QRegion region = w->mask()
+ & w->frameGeometry().translated(-w->geometry().topLeft());
+ return -region.boundingRect().topLeft();
+}
+