summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/powervr
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:18:55 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:18:55 (GMT)
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/plugins/gfxdrivers/powervr
downloadQt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2
Long live Qt 4.5!
Diffstat (limited to 'src/plugins/gfxdrivers/powervr')
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro24
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c856
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h181
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h129
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c384
-rw-r--r--src/plugins/gfxdrivers/powervr/README56
-rw-r--r--src/plugins/gfxdrivers/powervr/powervr.pro3
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp390
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h113
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro24
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp74
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp219
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h83
13 files changed, 2536 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro
new file mode 100644
index 0000000..b62894d
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro
@@ -0,0 +1,24 @@
+TEMPLATE = lib
+TARGET = pvrQWSWSEGL
+CONFIG += dll warn_on
+CONFIG -= qt
+
+HEADERS+=\
+ pvrqwsdrawable.h \
+ pvrqwsdrawable_p.h
+
+SOURCES+=\
+ pvrqwsdrawable.c \
+ pvrqwswsegl.c
+
+INCLUDEPATH += $$QMAKE_INCDIR_OPENGL
+
+for(p, QMAKE_LIBDIR_OPENGL) {
+ exists($$p):LIBS += -L$$p
+}
+
+LIBS += -lpvr2d
+
+DESTDIR = $$QMAKE_LIBDIR_QT
+target.path = $$[QT_INSTALL_LIBS]
+INSTALLS += target
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c
new file mode 100644
index 0000000..5c37253
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c
@@ -0,0 +1,856 @@
+/****************************************************************************
+**
+** 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 "pvrqwsdrawable_p.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+PvrQwsDisplay pvrQwsDisplay;
+
+static void pvrQwsDestroyDrawableForced(PvrQwsDrawable *drawable);
+
+/* Initialize the /dev/fbN device for a specific screen */
+static int pvrQwsInitFbScreen(int screen)
+{
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ unsigned long start;
+ unsigned long length;
+ int width, height, stride;
+ PVR2DFORMAT format;
+ void *mapped;
+ int fd, bytesPerPixel;
+ char name[64];
+ PVR2DMEMINFO *memInfo;
+ unsigned long pageAddresses[2];
+
+ /* Bail out if already initialized, or the number is incorrect */
+ if (screen < 0 || screen >= PVRQWS_MAX_SCREENS)
+ return 0;
+ if (pvrQwsDisplay.screens[screen].mapped)
+ return 1;
+
+ /* Open the framebuffer and fetch its properties */
+ sprintf(name, "/dev/fb%d", screen);
+ fd = open(name, O_RDWR, 0);
+ if (fd < 0) {
+ perror(name);
+ return 0;
+ }
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0) {
+ perror("FBIOGET_VSCREENINFO");
+ close(fd);
+ return 0;
+ }
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &fix) < 0) {
+ perror("FBIOGET_FSCREENINFO");
+ close(fd);
+ return 0;
+ }
+ width = var.xres;
+ height = var.yres;
+ bytesPerPixel = var.bits_per_pixel / 8;
+ stride = var.xres * bytesPerPixel;
+ format = PVR2D_1BPP;
+ if (var.bits_per_pixel == 16) {
+ if (var.red.length == 5 && var.green.length == 6 &&
+ var.blue.length == 5 && var.red.offset == 11 &&
+ var.green.offset == 5 && var.blue.offset == 0) {
+ format = PVR2D_RGB565;
+ }
+ if (var.red.length == 4 && var.green.length == 4 &&
+ var.blue.length == 4 && var.transp.length == 4 &&
+ var.red.offset == 8 && var.green.offset == 4 &&
+ var.blue.offset == 0 && var.transp.offset == 12) {
+ format = PVR2D_ARGB4444;
+ }
+ } else if (var.bits_per_pixel == 32) {
+ if (var.red.length == 8 && var.green.length == 8 &&
+ var.blue.length == 8 && var.transp.length == 8 &&
+ var.red.offset == 16 && var.green.offset == 8 &&
+ var.blue.offset == 0 && var.transp.offset == 24) {
+ format = PVR2D_ARGB8888;
+ }
+ }
+ if (format == PVR2D_1BPP) {
+ fprintf(stderr, "%s: could not find a suitable PVR2D pixel format\n", name);
+ close(fd);
+ return 0;
+ }
+ start = fix.smem_start;
+ length = var.xres_virtual * var.yres_virtual * bytesPerPixel;
+
+ /* Map the framebuffer region into memory */
+ mapped = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (!mapped || mapped == (void *)(-1)) {
+ perror("mmap");
+ close(fd);
+ return 0;
+ }
+
+ /* Allocate a PVR2D memory region for the framebuffer */
+ memInfo = 0;
+ if (pvrQwsDisplay.context) {
+ pageAddresses[0] = start & 0xFFFFF000;
+ pageAddresses[1] = 0;
+ if (PVR2DMemWrap
+ (pvrQwsDisplay.context, mapped, PVR2D_WRAPFLAG_CONTIGUOUS,
+ length, pageAddresses, &memInfo) != PVR2D_OK) {
+ munmap(mapped, length);
+ close(fd);
+ return 0;
+ }
+ }
+
+ /* We don't need the file descriptor any more */
+ close(fd);
+
+ /* The framebuffer is ready, so initialize the PvrQwsScreenInfo */
+ pvrQwsDisplay.screens[screen].screenRect.x = 0;
+ pvrQwsDisplay.screens[screen].screenRect.y = 0;
+ pvrQwsDisplay.screens[screen].screenRect.width = width;
+ pvrQwsDisplay.screens[screen].screenRect.height = height;
+ pvrQwsDisplay.screens[screen].screenStride = stride;
+ pvrQwsDisplay.screens[screen].pixelFormat = format;
+ pvrQwsDisplay.screens[screen].bytesPerPixel = bytesPerPixel;
+ pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
+ pvrQwsDisplay.screens[screen].screenDrawable = 0;
+ pvrQwsDisplay.screens[screen].mapped = mapped;
+ pvrQwsDisplay.screens[screen].mappedLength = length;
+ pvrQwsDisplay.screens[screen].screenStart = start;
+ return 1;
+}
+
+/* Called when a new drawable is added to ensure that we have a
+ PVR2D context and framebuffer PVR2DMEMINFO blocks */
+static int pvrQwsAddDrawable(void)
+{
+ int numDevs, screen;
+ PVR2DDEVICEINFO *devs;
+ unsigned long devId;
+ unsigned long pageAddresses[2];
+ PVR2DMEMINFO *memInfo;
+ PVR2DDISPLAYINFO displayInfo;
+
+ /* Bail out early if this is not the first drawable */
+ if (pvrQwsDisplay.numDrawables > 0) {
+ ++(pvrQwsDisplay.numDrawables);
+ return 1;
+ }
+
+ /* Find the first PVR2D device in the system and open it */
+ numDevs = PVR2DEnumerateDevices(0);
+ if (numDevs <= 0)
+ return 0;
+ devs = (PVR2DDEVICEINFO *)malloc(sizeof(PVR2DDEVICEINFO) * numDevs);
+ if (!devs)
+ return 0;
+ if (PVR2DEnumerateDevices(devs) != PVR2D_OK) {
+ free(devs);
+ return 0;
+ }
+ devId = devs[0].ulDevID;
+ free(devs);
+ if (PVR2DCreateDeviceContext(devId, &pvrQwsDisplay.context, 0) != PVR2D_OK)
+ return 0;
+ pvrQwsDisplay.numFlipBuffers = 0;
+ pvrQwsDisplay.flipChain = 0;
+ if (PVR2DGetDeviceInfo(pvrQwsDisplay.context, &displayInfo) == PVR2D_OK) {
+ if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0)
+ pvrQwsDisplay.numFlipBuffers = displayInfo.ulMaxBuffersInChain;
+ if (pvrQwsDisplay.numFlipBuffers > PVRQWS_MAX_FLIP_BUFFERS)
+ pvrQwsDisplay.numFlipBuffers = PVRQWS_MAX_FLIP_BUFFERS;
+ }
+
+ /* Create the PVR2DMEMINFO blocks for the active framebuffers */
+ for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
+ if (pvrQwsDisplay.screens[screen].mapped) {
+ pageAddresses[0]
+ = pvrQwsDisplay.screens[screen].screenStart & 0xFFFFF000;
+ pageAddresses[1] = 0;
+ if (PVR2DMemWrap
+ (pvrQwsDisplay.context,
+ pvrQwsDisplay.screens[screen].mapped,
+ PVR2D_WRAPFLAG_CONTIGUOUS,
+ pvrQwsDisplay.screens[screen].mappedLength,
+ pageAddresses, &memInfo) != PVR2D_OK) {
+ PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
+ pvrQwsDisplay.context = 0;
+ return 0;
+ }
+ pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
+ }
+ }
+
+ /* Create a flip chain for the screen if supported by the hardware */
+ pvrQwsDisplay.usePresentBlit = 0;
+ if (pvrQwsDisplay.numFlipBuffers > 0) {
+ long stride = 0;
+ unsigned long flipId = 0;
+ unsigned long numBuffers;
+ if (PVR2DCreateFlipChain(pvrQwsDisplay.context, 0,
+ //PVR2D_CREATE_FLIPCHAIN_SHARED |
+ //PVR2D_CREATE_FLIPCHAIN_QUERY,
+ pvrQwsDisplay.numFlipBuffers,
+ pvrQwsDisplay.screens[0].screenRect.width,
+ pvrQwsDisplay.screens[0].screenRect.height,
+ pvrQwsDisplay.screens[0].pixelFormat,
+ &stride, &flipId, &(pvrQwsDisplay.flipChain))
+ == PVR2D_OK) {
+ pvrQwsDisplay.screens[0].screenStride = stride;
+ PVR2DGetFlipChainBuffers(pvrQwsDisplay.context,
+ pvrQwsDisplay.flipChain,
+ &numBuffers,
+ pvrQwsDisplay.flipBuffers);
+ } else {
+ pvrQwsDisplay.flipChain = 0;
+ pvrQwsDisplay.numFlipBuffers = 0;
+ }
+
+ /* PVR2DPresentBlt is a little more reliable than PVR2DBlt
+ when flip chains are present, even if we cannot create a
+ flip chain at the moment */
+ pvrQwsDisplay.usePresentBlit = 1;
+ }
+
+ /* The context is ready to go */
+ ++(pvrQwsDisplay.numDrawables);
+ return 1;
+}
+
+/* Called when the last drawable is destroyed. The PVR2D context
+ will be destroyed but the raw framebuffer memory will stay mapped */
+static void pvrQwsDestroyContext(void)
+{
+ int screen;
+ for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
+ if (pvrQwsDisplay.screens[screen].frameBuffer) {
+ PVR2DMemFree
+ (pvrQwsDisplay.context,
+ pvrQwsDisplay.screens[screen].frameBuffer);
+ pvrQwsDisplay.screens[screen].frameBuffer = 0;
+ }
+ }
+
+ if (pvrQwsDisplay.numFlipBuffers > 0)
+ PVR2DDestroyFlipChain(pvrQwsDisplay.context, pvrQwsDisplay.flipChain);
+ PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
+ pvrQwsDisplay.context = 0;
+ pvrQwsDisplay.flipChain = 0;
+ pvrQwsDisplay.numFlipBuffers = 0;
+ pvrQwsDisplay.usePresentBlit = 0;
+}
+
+int pvrQwsDisplayOpen(void)
+{
+ int screen;
+
+ /* If the display is already open, increase reference count and return */
+ if (pvrQwsDisplay.refCount > 0) {
+ ++(pvrQwsDisplay.refCount);
+ return 1;
+ }
+
+ /* Open the framebuffer and map it directly */
+ if (!pvrQwsInitFbScreen(0)) {
+ --(pvrQwsDisplay.refCount);
+ return 0;
+ }
+
+ /* Clear the other screens. We will create them if they are referenced */
+ for (screen = 1; screen < PVRQWS_MAX_SCREENS; ++screen)
+ memset(&(pvrQwsDisplay.screens[screen]), 0, sizeof(PvrQwsScreenInfo));
+
+ /* The display is open and ready */
+ ++(pvrQwsDisplay.refCount);
+ return 1;
+}
+
+void pvrQwsDisplayClose(void)
+{
+ int screen;
+
+ if (pvrQwsDisplay.refCount == 0)
+ return;
+ if (--(pvrQwsDisplay.refCount) > 0)
+ return;
+
+ /* Prevent pvrQwsDestroyContext from being called for the time being */
+ ++pvrQwsDisplay.numDrawables;
+
+ /* Free the screens */
+ for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
+ PvrQwsScreenInfo *info = &(pvrQwsDisplay.screens[screen]);
+ if (info->screenDrawable)
+ pvrQwsDestroyDrawableForced(info->screenDrawable);
+ if (info->frameBuffer)
+ PVR2DMemFree(pvrQwsDisplay.context, info->frameBuffer);
+ if (info->mapped)
+ munmap(info->mapped, info->mappedLength);
+ }
+
+ /* Now it is safe to destroy the PVR2D context */
+ --pvrQwsDisplay.numDrawables;
+ if (pvrQwsDisplay.context)
+ PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
+
+ memset(&pvrQwsDisplay, 0, sizeof(pvrQwsDisplay));
+}
+
+int pvrQwsDisplayIsOpen(void)
+{
+ return (pvrQwsDisplay.refCount > 0);
+}
+
+/* Ensure that a specific screen has been initialized */
+static int pvrQwsEnsureScreen(int screen)
+{
+ if (screen < 0 || screen >= PVRQWS_MAX_SCREENS)
+ return 0;
+ if (!screen)
+ return 1;
+ return pvrQwsInitFbScreen(screen);
+}
+
+PvrQwsDrawable *pvrQwsScreenWindow(int screen)
+{
+ PvrQwsDrawable *drawable;
+
+ if (!pvrQwsEnsureScreen(screen))
+ return 0;
+
+ drawable = pvrQwsDisplay.screens[screen].screenDrawable;
+ if (drawable)
+ return drawable;
+
+ drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
+ if (!drawable)
+ return 0;
+
+ drawable->type = PvrQwsScreen;
+ drawable->screen = screen;
+ drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
+ drawable->rect = pvrQwsDisplay.screens[screen].screenRect;
+ drawable->visibleRects[0] = drawable->rect;
+ drawable->numVisibleRects = 1;
+ drawable->isFullScreen = 1;
+
+ if (!pvrQwsAddDrawable()) {
+ free(drawable);
+ return 0;
+ }
+
+ pvrQwsDisplay.screens[screen].screenDrawable = drawable;
+
+ return drawable;
+}
+
+PvrQwsDrawable *pvrQwsCreateWindow(int screen, long winId, const PvrQwsRect *rect)
+{
+ PvrQwsDrawable *drawable;
+
+ if (!pvrQwsEnsureScreen(screen))
+ return 0;
+
+ drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
+ if (!drawable)
+ return 0;
+
+ drawable->type = PvrQwsWindow;
+ drawable->winId = winId;
+ drawable->refCount = 1;
+ drawable->screen = screen;
+ drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
+ drawable->rect = *rect;
+
+ if (!pvrQwsAddDrawable()) {
+ free(drawable);
+ return 0;
+ }
+
+ drawable->nextWinId = pvrQwsDisplay.firstWinId;
+ pvrQwsDisplay.firstWinId = drawable;
+
+ return drawable;
+}
+
+PvrQwsDrawable *pvrQwsFetchWindow(long winId)
+{
+ PvrQwsDrawable *drawable = pvrQwsDisplay.firstWinId;
+ while (drawable != 0 && drawable->winId != winId)
+ drawable = drawable->nextWinId;
+
+ if (drawable)
+ ++(drawable->refCount);
+ return drawable;
+}
+
+int pvrQwsReleaseWindow(PvrQwsDrawable *drawable)
+{
+ if (drawable->type == PvrQwsWindow)
+ return (--(drawable->refCount) <= 0);
+ else
+ return 0;
+}
+
+PvrQwsDrawable *pvrQwsCreatePixmap(int width, int height, int screen)
+{
+ PvrQwsDrawable *drawable;
+
+ if (!pvrQwsEnsureScreen(screen))
+ return 0;
+
+ drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
+ if (!drawable)
+ return 0;
+
+ drawable->type = PvrQwsPixmap;
+ drawable->screen = screen;
+ drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
+ drawable->rect.x = 0;
+ drawable->rect.y = 0;
+ drawable->rect.width = width;
+ drawable->rect.height = height;
+
+ if (!pvrQwsAddDrawable()) {
+ free(drawable);
+ return 0;
+ }
+
+ return drawable;
+}
+
+static void pvrQwsDestroyDrawableForced(PvrQwsDrawable *drawable)
+{
+ /* Remove the drawable from the display's winId list */
+ PvrQwsDrawable *current = pvrQwsDisplay.firstWinId;
+ PvrQwsDrawable *prev = 0;
+ while (current != 0 && current != drawable) {
+ prev = current;
+ current = current->nextWinId;
+ }
+ if (current != 0) {
+ if (prev)
+ prev->nextWinId = current->nextWinId;
+ else
+ pvrQwsDisplay.firstWinId = current->nextWinId;
+ }
+
+ pvrQwsFreeBuffers(drawable);
+ free(drawable);
+
+ --pvrQwsDisplay.numDrawables;
+ if (pvrQwsDisplay.numDrawables == 0)
+ pvrQwsDestroyContext();
+}
+
+void pvrQwsDestroyDrawable(PvrQwsDrawable *drawable)
+{
+ if (drawable && drawable->type != PvrQwsScreen)
+ pvrQwsDestroyDrawableForced(drawable);
+}
+
+PvrQwsDrawableType pvrQwsGetDrawableType(PvrQwsDrawable *drawable)
+{
+ return drawable->type;
+}
+
+void pvrQwsSetVisibleRegion
+ (PvrQwsDrawable *drawable, const PvrQwsRect *rects, int numRects)
+{
+ int index, indexOut;
+ PvrQwsRect *rect;
+ PvrQwsRect *screenRect;
+
+ /* Visible regions don't make sense for pixmaps */
+ if (drawable->type == PvrQwsPixmap)
+ return;
+
+ /* Restrict the number of rectangles to prevent buffer overflow */
+ if (numRects > PVRQWS_MAX_VISIBLE_RECTS)
+ numRects = PVRQWS_MAX_VISIBLE_RECTS;
+ if (numRects > 0)
+ memcpy(drawable->visibleRects, rects, numRects * sizeof(PvrQwsRect));
+
+ /* Convert the rectangles into screen-relative co-ordinates and
+ then clamp them to the screen boundaries. If any of the
+ clamped rectangles are empty, remove them from the list */
+ screenRect = &(pvrQwsDisplay.screens[drawable->screen].screenRect);
+ indexOut = 0;
+ for (index = 0, rect = drawable->visibleRects; index < numRects; ++index, ++rect) {
+ if (rect->x < 0) {
+ rect->width += rect->x;
+ rect->x = 0;
+ if (rect->width < 0)
+ rect->width = 0;
+ } else if (rect->x >= screenRect->width) {
+ rect->x = screenRect->width;
+ rect->width = 0;
+ }
+ if ((rect->x + rect->width) > screenRect->width) {
+ rect->width = screenRect->width - rect->x;
+ }
+ if (rect->y < 0) {
+ rect->height += rect->y;
+ rect->y = 0;
+ if (rect->height < 0)
+ rect->height = 0;
+ } else if (rect->y >= screenRect->height) {
+ rect->y = screenRect->height;
+ rect->height = 0;
+ }
+ if ((rect->y + rect->height) > screenRect->height) {
+ rect->height = screenRect->height - rect->y;
+ }
+ if (rect->width > 0 && rect->height > 0) {
+ if (index != indexOut)
+ drawable->visibleRects[indexOut] = *rect;
+ ++indexOut;
+ }
+ }
+ drawable->numVisibleRects = indexOut;
+}
+
+void pvrQwsClearVisibleRegion(PvrQwsDrawable *drawable)
+{
+ if (drawable->type != PvrQwsPixmap)
+ drawable->numVisibleRects = 0;
+}
+
+void pvrQwsSetGeometry(PvrQwsDrawable *drawable, const PvrQwsRect *rect)
+{
+ /* We can only change the geometry of window drawables */
+ if (drawable->type != PvrQwsWindow)
+ return;
+
+ /* If the position has changed, then clear the visible region */
+ if (drawable->rect.x != rect->x || drawable->rect.y != rect->y) {
+ drawable->rect.x = rect->x;
+ drawable->rect.y = rect->y;
+ drawable->numVisibleRects = 0;
+ }
+
+ /* If the size has changed, then clear the visible region and
+ invalidate the drawable's buffers. Invalidating the buffers
+ will force EGL to recreate the drawable, which will then
+ allocate new buffers for the new size */
+ if (drawable->rect.width != rect->width ||
+ drawable->rect.height != rect->height) {
+ drawable->rect.width = rect->width;
+ drawable->rect.height = rect->height;
+ drawable->numVisibleRects = 0;
+ pvrQwsInvalidateBuffers(drawable);
+ }
+}
+
+void pvrQwsGetGeometry(PvrQwsDrawable *drawable, PvrQwsRect *rect)
+{
+ *rect = drawable->rect;
+}
+
+int pvrQwsGetStride(PvrQwsDrawable *drawable)
+{
+ if (drawable->backBuffersValid)
+ return drawable->strideBytes;
+ else
+ return 0;
+}
+
+PvrQwsPixelFormat pvrQwsGetPixelFormat(PvrQwsDrawable *drawable)
+{
+ return (PvrQwsPixelFormat)(drawable->pixelFormat);
+}
+
+void *pvrQwsGetRenderBuffer(PvrQwsDrawable *drawable)
+{
+ if (drawable->backBuffersValid)
+ return drawable->backBuffers[drawable->currentBackBuffer]->pBase;
+ else
+ return 0;
+}
+
+int pvrQwsAllocBuffers(PvrQwsDrawable *drawable)
+{
+ int index;
+ int numBuffers = PVRQWS_MAX_BACK_BUFFERS;
+ if (drawable->type == PvrQwsPixmap)
+ numBuffers = 1;
+ if (drawable->backBuffers[0]) {
+ if (drawable->backBuffersValid)
+ return 1;
+ if (!drawable->usingFlipBuffers) {
+ for (index = 0; index < numBuffers; ++index)
+ PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
+ }
+ }
+ drawable->stridePixels = (drawable->rect.width + 7) & ~7;
+ drawable->strideBytes =
+ drawable->stridePixels *
+ pvrQwsDisplay.screens[drawable->screen].bytesPerPixel;
+ drawable->usingFlipBuffers =
+ (pvrQwsDisplay.numFlipBuffers > 0 && drawable->isFullScreen);
+ if (drawable->usingFlipBuffers) {
+ if (numBuffers > (int)(pvrQwsDisplay.numFlipBuffers))
+ numBuffers = pvrQwsDisplay.numFlipBuffers;
+ for (index = 0; index < numBuffers; ++index)
+ drawable->backBuffers[index] = pvrQwsDisplay.flipBuffers[index];
+ } else {
+ for (index = 0; index < numBuffers; ++index) {
+ if (PVR2DMemAlloc(pvrQwsDisplay.context,
+ drawable->strideBytes * drawable->rect.height,
+ 128, 0,
+ &(drawable->backBuffers[index])) != PVR2D_OK) {
+ while (--index >= 0)
+ PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
+ memset(drawable->backBuffers, 0, sizeof(drawable->backBuffers));
+ drawable->backBuffersValid = 0;
+ return 0;
+ }
+ }
+ }
+ for (index = numBuffers; index < PVRQWS_MAX_BACK_BUFFERS; ++index) {
+ drawable->backBuffers[index] = drawable->backBuffers[0];
+ }
+ drawable->backBuffersValid = 1;
+ drawable->currentBackBuffer = 0;
+ return 1;
+}
+
+void pvrQwsFreeBuffers(PvrQwsDrawable *drawable)
+{
+ int index;
+ int numBuffers = PVRQWS_MAX_BACK_BUFFERS;
+ if (drawable->type == PvrQwsPixmap)
+ numBuffers = 1;
+ if (!drawable->usingFlipBuffers) {
+ for (index = 0; index < numBuffers; ++index) {
+ if (drawable->backBuffers[index])
+ PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
+ }
+ }
+ memset(drawable->backBuffers, 0, sizeof(drawable->backBuffers));
+ drawable->backBuffersValid = 0;
+ drawable->usingFlipBuffers = 0;
+}
+
+void pvrQwsInvalidateBuffers(PvrQwsDrawable *drawable)
+{
+ drawable->backBuffersValid = 0;
+}
+
+int pvrQwsGetBuffers
+ (PvrQwsDrawable *drawable, PVR2DMEMINFO **source, PVR2DMEMINFO **render)
+{
+ if (!drawable->backBuffersValid)
+ return 0;
+ *render = drawable->backBuffers[drawable->currentBackBuffer];
+ *source = drawable->backBuffers
+ [(drawable->currentBackBuffer + PVRQWS_MAX_BACK_BUFFERS - 1) %
+ PVRQWS_MAX_BACK_BUFFERS];
+ return 1;
+}
+
+int pvrQwsSwapBuffers(PvrQwsDrawable *drawable, int repaintOnly)
+{
+ PVR2DMEMINFO *buffer;
+ PvrQwsRect *rect;
+ int index;
+
+ /* Bail out if the back buffers have been invalidated */
+ if (!drawable->backBuffersValid)
+ return 0;
+
+ /* If there is a swap function, then use that instead */
+ if (drawable->swapFunction) {
+ (*(drawable->swapFunction))(drawable, drawable->userData, repaintOnly);
+ if (!repaintOnly) {
+ drawable->currentBackBuffer
+ = (drawable->currentBackBuffer + 1) % PVRQWS_MAX_BACK_BUFFERS;
+ }
+ return 1;
+ }
+
+ /* Iterate through the visible rectangles and blit them to the screen */
+ if (!repaintOnly) {
+ index = drawable->currentBackBuffer;
+ } else {
+ index = (drawable->currentBackBuffer + PVRQWS_MAX_BACK_BUFFERS - 1)
+ % PVRQWS_MAX_BACK_BUFFERS;
+ }
+ buffer = drawable->backBuffers[index];
+ rect = drawable->visibleRects;
+ if (drawable->usingFlipBuffers) {
+ PVR2DPresentFlip(pvrQwsDisplay.context, pvrQwsDisplay.flipChain, buffer, 0);
+ } else if (pvrQwsDisplay.usePresentBlit && drawable->numVisibleRects > 0) {
+ PVR2DRECT pvrRects[PVRQWS_MAX_VISIBLE_RECTS];
+ for (index = 0; index < drawable->numVisibleRects; ++index, ++rect) {
+ pvrRects[index].left = rect->x;
+ pvrRects[index].top = rect->y;
+ pvrRects[index].right = rect->x + rect->width;
+ pvrRects[index].bottom = rect->y + rect->height;
+ }
+ for (index = 0; index < drawable->numVisibleRects; index += 4) {
+ int numClip = drawable->numVisibleRects - index;
+ if (numClip > 4) /* No more than 4 clip rects at a time */
+ numClip = 4;
+ PVR2DSetPresentBltProperties
+ (pvrQwsDisplay.context,
+ PVR2D_PRESENT_PROPERTY_SRCSTRIDE |
+ PVR2D_PRESENT_PROPERTY_DSTSIZE |
+ PVR2D_PRESENT_PROPERTY_DSTPOS |
+ PVR2D_PRESENT_PROPERTY_CLIPRECTS,
+ drawable->strideBytes,
+ drawable->rect.width, drawable->rect.height,
+ drawable->rect.x, drawable->rect.y,
+ numClip, pvrRects + index, 0);
+ PVR2DPresentBlt(pvrQwsDisplay.context, buffer, 0);
+ }
+ PVR2DQueryBlitsComplete(pvrQwsDisplay.context, buffer, 1);
+ } else {
+ /* TODO: use PVR2DBltClipped for faster transfers of clipped windows */
+ PVR2DBLTINFO blit;
+ for (index = 0; index < drawable->numVisibleRects; ++index, ++rect) {
+ memset(&blit, 0, sizeof(blit));
+
+ blit.CopyCode = PVR2DROPcopy;
+ blit.BlitFlags = PVR2D_BLIT_DISABLE_ALL;
+
+ blit.pSrcMemInfo = buffer;
+ blit.SrcStride = drawable->strideBytes;
+ blit.SrcX = rect->x - drawable->rect.x;
+ blit.SrcY = rect->y - drawable->rect.y;
+ blit.SizeX = rect->width;
+ blit.SizeY = rect->height;
+ blit.SrcFormat = drawable->pixelFormat;
+
+ blit.pDstMemInfo = pvrQwsDisplay.screens[drawable->screen].frameBuffer;
+ blit.DstStride = pvrQwsDisplay.screens[drawable->screen].screenStride;
+ blit.DstX = rect->x;
+ blit.DstY = rect->y;
+ blit.DSizeX = rect->width;
+ blit.DSizeY = rect->height;
+ blit.DstFormat = pvrQwsDisplay.screens[drawable->screen].pixelFormat;
+
+ PVR2DBlt(pvrQwsDisplay.context, &blit);
+ }
+ }
+
+ /* Swap the buffers */
+ if (!repaintOnly) {
+ drawable->currentBackBuffer
+ = (drawable->currentBackBuffer + 1) % PVRQWS_MAX_BACK_BUFFERS;
+ }
+ return 1;
+}
+
+void pvrQwsSetSwapFunction
+ (PvrQwsDrawable *drawable, PvrQwsSwapFunction func, void *userData)
+{
+ drawable->swapFunction = func;
+ drawable->userData = userData;
+}
+
+unsigned long pvrQwsGetMemoryId(PvrQwsDrawable *drawable)
+{
+ unsigned long addr;
+ unsigned long start;
+ unsigned long end;
+ unsigned long off;
+ unsigned long offset;
+ FILE *file;
+ char buffer[BUFSIZ];
+ char flags[16];
+
+ if (!drawable->backBuffersValid)
+ return 0;
+ addr = (unsigned long)
+ (drawable->backBuffers[drawable->currentBackBuffer]->pBase);
+
+ /* Search /proc/self/maps for the memory region that contains "addr".
+ The file offset for that memory region is the identifier we need */
+ file = fopen("/proc/self/maps", "r");
+ if (!file) {
+ perror("/proc/self/maps");
+ return 0;
+ }
+ offset = 0;
+ while (fgets(buffer, sizeof(buffer), file)) {
+ if (sscanf(buffer, "%lx-%lx %s %lx",
+ &start, &end, flags, &off) < 4)
+ continue;
+ if (start <= addr && addr < end) {
+ offset = off;
+ break;
+ }
+ }
+ fclose(file);
+ return offset;
+}
+
+void *pvrQwsMapMemory(unsigned long id, int size)
+{
+ void *addr;
+ int fd = open("/dev/pvrsrv", O_RDWR, 0);
+ if (fd < 0) {
+ perror("/dev/pvrsrv");
+ return 0;
+ }
+ addr = mmap(0, (size_t)size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, (off_t)id);
+ if (addr == (void *)(-1)) {
+ perror("mmap pvr memory region");
+ addr = 0;
+ }
+ close(fd);
+ return addr;
+}
+
+void pvrQwsUnmapMemory(void *addr, int size)
+{
+ munmap(addr, size);
+}
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h
new file mode 100644
index 0000000..16872a9
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PVRQWSDRAWABLE_H
+#define PVRQWSDRAWABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int x, y, width, height;
+} PvrQwsRect;
+
+typedef enum
+{
+ PvrQwsScreen,
+ PvrQwsWindow,
+ PvrQwsPixmap
+
+} PvrQwsDrawableType;
+
+typedef enum
+{
+ PvrQws_1BPP = 0,
+ PvrQws_RGB565,
+ PvrQws_ARGB4444,
+ PvrQws_RGB888,
+ PvrQws_ARGB8888,
+ PvrQws_VGAEMU
+
+} PvrQwsPixelFormat;
+
+typedef struct _PvrQwsDrawable PvrQwsDrawable;
+
+typedef void (*PvrQwsSwapFunction)
+ (PvrQwsDrawable *drawable, void *userData, int repaintOnly);
+
+/* Open the display and prepare for window operations. The display
+ can be opened multiple times and each time is reference counted.
+ The display will be finally closed when the same number of
+ calls to pvrQwsDisplayClose() have been encountered */
+int pvrQwsDisplayOpen(void);
+
+/* Close the display */
+void pvrQwsDisplayClose(void);
+
+/* Determine if the display is already open */
+int pvrQwsDisplayIsOpen(void);
+
+/* Create a window that represents a particular framebuffer screen.
+ Initially the visible region will be the whole screen. If the screen
+ window has already been created, then will return the same value */
+PvrQwsDrawable *pvrQwsScreenWindow(int screen);
+
+/* Create a top-level window on a particular framebuffer screen.
+ Initially the window will not have a visible region */
+PvrQwsDrawable *pvrQwsCreateWindow(int screen, long winId, const PvrQwsRect *rect);
+
+/* Fetch an existing window for a window id and increase its refcount */
+PvrQwsDrawable *pvrQwsFetchWindow(long winId);
+
+/* Release the refcount on a window. Returns 1 if refcount is zero */
+int pvrQwsReleaseWindow(PvrQwsDrawable *drawable);
+
+/* Create an off-screen pixmap */
+PvrQwsDrawable *pvrQwsCreatePixmap(int width, int height, int screen);
+
+/* Destroy a previously-created drawable. Will not destroy screens. */
+void pvrQwsDestroyDrawable(PvrQwsDrawable *drawable);
+
+/* Get a drawable's type */
+PvrQwsDrawableType pvrQwsGetDrawableType(PvrQwsDrawable *drawable);
+
+/* Sets the visible region for a window or screen drawable. Pixels within
+ the specified rectangles will be copied to the framebuffer when the window
+ or screen is swapped. The rectangles should be in global co-ordinates */
+void pvrQwsSetVisibleRegion
+ (PvrQwsDrawable *drawable, const PvrQwsRect *rects, int numRects);
+
+/* Clear the visible region for a window or screen drawable,
+ effectively removing it from the screen */
+void pvrQwsClearVisibleRegion(PvrQwsDrawable *drawable);
+
+/* Set the geometry for a drawable. This can only be used on windows */
+void pvrQwsSetGeometry(PvrQwsDrawable *drawable, const PvrQwsRect *rect);
+
+/* Get the current geometry for a drawable */
+void pvrQwsGetGeometry(PvrQwsDrawable *drawable, PvrQwsRect *rect);
+
+/* Get the line stride for a drawable. Returns zero if the buffers
+ are not allocated or have been invalidated */
+int pvrQwsGetStride(PvrQwsDrawable *drawable);
+
+/* Get the pixel format for a drawable */
+PvrQwsPixelFormat pvrQwsGetPixelFormat(PvrQwsDrawable *drawable);
+
+/* Get a pointer to the beginning of a drawable's current render buffer.
+ Returns null if the buffers are not allocated or have been invalidated */
+void *pvrQwsGetRenderBuffer(PvrQwsDrawable *drawable);
+
+/* Allocate the buffers associated with a drawable. We allocate one buffer
+ for pixmaps, and several for windows and screens */
+int pvrQwsAllocBuffers(PvrQwsDrawable *drawable);
+
+/* Free the buffers associated with a drawable */
+void pvrQwsFreeBuffers(PvrQwsDrawable *drawable);
+
+/* Invalidate the buffers associated with a drawable. The buffers will
+ still be allocated but the next attempt to swap the buffers will fail */
+void pvrQwsInvalidateBuffers(PvrQwsDrawable *drawable);
+
+/* Swap the back buffers for a window or screen and copy to the framebuffer */
+int pvrQwsSwapBuffers(PvrQwsDrawable *drawable, int repaintOnly);
+
+/* Set the swap function for a drawable. When pvrQwsSwapBuffers()
+ is called on the drawable, the supplied function will be called
+ instead of copying the drawable contents to the screen. This allows
+ higher-level compositors to know when a drawable has changed.
+ The swap function can be set to null to return to normal processing */
+void pvrQwsSetSwapFunction
+ (PvrQwsDrawable *drawable, PvrQwsSwapFunction func, void *userData);
+
+/* Get a memory identifier for the indicated drawable's buffer.
+ The identifier can be passed to another process and then
+ passed to pvrQwsMapMemory() to map the drawable's buffer into
+ the other process's address space. Returns zero if the
+ memory identifier could not be determined. This should only
+ be used for pixmap drawables */
+unsigned long pvrQwsGetMemoryId(PvrQwsDrawable *drawable);
+
+/* Map the memory buffer of a foreign application's drawable, as
+ indicated by "id" and "size". Returns null if the map failed */
+void *pvrQwsMapMemory(unsigned long id, int size);
+
+/* Unmap the memory obtained from pvrQwsMapMemory() */
+void pvrQwsUnmapMemory(void *addr, int size);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h
new file mode 100644
index 0000000..d6c42a6
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PVRQWSDRAWABLE_P_H
+#define PVRQWSDRAWABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// reasons. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <pvr2d.h>
+#include "pvrqwsdrawable.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PVRQWS_MAX_VISIBLE_RECTS 32
+#define PVRQWS_MAX_SCREENS 1
+#define PVRQWS_MAX_BACK_BUFFERS 2
+#define PVRQWS_MAX_FLIP_BUFFERS 2
+
+typedef struct {
+
+ PvrQwsRect screenRect;
+ int screenStride;
+ PVR2DFORMAT pixelFormat;
+ int bytesPerPixel;
+ PVR2DMEMINFO *frameBuffer;
+ PvrQwsDrawable *screenDrawable;
+ void *mapped;
+ int mappedLength;
+ unsigned long screenStart;
+
+} PvrQwsScreenInfo;
+
+typedef struct {
+
+ int refCount;
+ PvrQwsScreenInfo screens[PVRQWS_MAX_SCREENS];
+ PVR2DCONTEXTHANDLE context;
+ int numDrawables;
+ unsigned long numFlipBuffers;
+ PVR2DFLIPCHAINHANDLE flipChain;
+ PVR2DMEMINFO *flipBuffers[PVRQWS_MAX_FLIP_BUFFERS];
+ int usePresentBlit;
+ PvrQwsDrawable *firstWinId;
+
+} PvrQwsDisplay;
+
+extern PvrQwsDisplay pvrQwsDisplay;
+
+struct _PvrQwsDrawable
+{
+ PvrQwsDrawableType type;
+ long winId;
+ int refCount;
+ PvrQwsRect rect;
+ int screen;
+ PVR2DFORMAT pixelFormat;
+ PvrQwsRect visibleRects[PVRQWS_MAX_VISIBLE_RECTS];
+ int numVisibleRects;
+ PVR2DMEMINFO *backBuffers[PVRQWS_MAX_BACK_BUFFERS];
+ int currentBackBuffer;
+ int backBuffersValid;
+ int usingFlipBuffers;
+ int isFullScreen;
+ int strideBytes;
+ int stridePixels;
+ PvrQwsSwapFunction swapFunction;
+ void *userData;
+ PvrQwsDrawable *nextWinId;
+
+};
+
+/* Get the current source and render buffers for a drawable */
+int pvrQwsGetBuffers
+ (PvrQwsDrawable *drawable, PVR2DMEMINFO **source, PVR2DMEMINFO **render);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c
new file mode 100644
index 0000000..f46448e
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** 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 <GLES/egltypes.h>
+#include <wsegl.h>
+#include <pvr2d.h>
+#include <string.h>
+#include <sys/mman.h>
+#include "pvrqwsdrawable_p.h"
+
+#define WSEGL_UNUSED(x) (void)x;
+
+/* Capability information for the display */
+static WSEGLCaps const wseglDisplayCaps[] = {
+ {WSEGL_CAP_WINDOWS_USE_MBX_SYNC, 1},
+ {WSEGL_CAP_PIXMAPS_USE_MBX_SYNC, 1},
+ {WSEGL_NO_CAPS, 0}
+};
+
+/* Configuration information for the display */
+static WSEGLConfig wseglDisplayConfigs[] = {
+ {WSEGL_DRAWABLE_WINDOW, WSEGL_PIXELFORMAT_565, WSEGL_FALSE,
+ 0, 0, 0, WSEGL_OPAQUE, 0},
+ {WSEGL_DRAWABLE_PIXMAP, WSEGL_PIXELFORMAT_565, WSEGL_FALSE,
+ 0, 0, 0, WSEGL_OPAQUE, 0},
+ {WSEGL_NO_DRAWABLE, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/* Determine if nativeDisplay is a valid display handle */
+static WSEGLError wseglIsDisplayValid(NativeDisplayType nativeDisplay)
+{
+ /* We only have the default display in this system */
+ if (nativeDisplay == WSEGL_DEFAULT_DISPLAY)
+ return WSEGL_SUCCESS;
+ else
+ return WSEGL_BAD_NATIVE_DISPLAY;
+}
+
+/* Initialize a native display for use with WSEGL */
+static WSEGLError wseglInitializeDisplay
+ (NativeDisplayType nativeDisplay, WSEGLDisplayHandle *display,
+ const WSEGLCaps **caps, WSEGLConfig **configs)
+{
+ WSEGLPixelFormat pixelFormat;
+
+ /* Bail out if the native display is incorrect */
+ if (nativeDisplay != WSEGL_DEFAULT_DISPLAY)
+ return WSEGL_CANNOT_INITIALISE;
+
+ /* Open the PVR/QWS display, which will initialize the framebuffer */
+ if (!pvrQwsDisplayOpen())
+ return WSEGL_CANNOT_INITIALISE;
+
+ /* Convert the PVR2D pixel format into a WSEGL pixel format */
+ switch (pvrQwsDisplay.screens[0].pixelFormat) {
+ case PVR2D_RGB565:
+ pixelFormat = WSEGL_PIXELFORMAT_565;
+ break;
+
+ case PVR2D_ARGB4444:
+ pixelFormat = WSEGL_PIXELFORMAT_4444;
+ break;
+
+ case PVR2D_ARGB8888:
+ pixelFormat = WSEGL_PIXELFORMAT_8888;
+ break;
+
+ default:
+ pvrQwsDisplayClose();
+ return WSEGL_CANNOT_INITIALISE;
+ }
+ wseglDisplayConfigs[0].ePixelFormat = pixelFormat;
+ wseglDisplayConfigs[1].ePixelFormat = pixelFormat;
+
+ /* The display has been initialized */
+ *display = (WSEGLDisplayHandle)&pvrQwsDisplay;
+ *caps = wseglDisplayCaps;
+ *configs = wseglDisplayConfigs;
+ return WSEGL_SUCCESS;
+}
+
+/* Close the WSEGL display */
+static WSEGLError wseglCloseDisplay(WSEGLDisplayHandle display)
+{
+ if (display == (WSEGLDisplayHandle)&pvrQwsDisplay)
+ pvrQwsDisplayClose();
+ return WSEGL_SUCCESS;
+}
+
+/* Create the WSEGL drawable version of a native window */
+static WSEGLError wseglCreateWindowDrawable
+ (WSEGLDisplayHandle display, WSEGLConfig *config,
+ WSEGLDrawableHandle *drawable, NativeWindowType nativeWindow,
+ WSEGLRotationAngle *rotationAngle)
+{
+ PvrQwsDrawable *draw;
+
+ WSEGL_UNUSED(display);
+ WSEGL_UNUSED(config);
+
+ /* Check for special handles that indicate framebuffer screens */
+ if (nativeWindow >= (NativeWindowType)0 &&
+ nativeWindow < (NativeWindowType)PVRQWS_MAX_SCREENS) {
+ PvrQwsDrawable *screen = pvrQwsScreenWindow((int)nativeWindow);
+ if (!screen)
+ return WSEGL_OUT_OF_MEMORY;
+ *drawable = (WSEGLDrawableHandle)screen;
+ if (!pvrQwsAllocBuffers(screen))
+ return WSEGL_OUT_OF_MEMORY;
+ *rotationAngle = WSEGL_ROTATE_0;
+ return WSEGL_SUCCESS;
+ }
+
+ /* The native window is the winId - fetch the underlying drawable */
+ draw = pvrQwsFetchWindow((long)nativeWindow);
+ if (!draw)
+ return WSEGL_BAD_DRAWABLE;
+
+ /* The drawable is ready to go */
+ *drawable = (WSEGLDrawableHandle)draw;
+ *rotationAngle = WSEGL_ROTATE_0;
+ if (!pvrQwsAllocBuffers(draw))
+ return WSEGL_OUT_OF_MEMORY;
+ return WSEGL_SUCCESS;
+}
+
+/* Create the WSEGL drawable version of a native pixmap */
+static WSEGLError wseglCreatePixmapDrawable
+ (WSEGLDisplayHandle display, WSEGLConfig *config,
+ WSEGLDrawableHandle *drawable, NativePixmapType nativePixmap,
+ WSEGLRotationAngle *rotationAngle)
+{
+ WSEGL_UNUSED(display);
+ WSEGL_UNUSED(config);
+ if (!nativePixmap)
+ return WSEGL_BAD_NATIVE_PIXMAP;
+ if (!pvrQwsAllocBuffers((PvrQwsDrawable *)nativePixmap))
+ return WSEGL_OUT_OF_MEMORY;
+ *drawable = (WSEGLDrawableHandle)nativePixmap;
+ *rotationAngle = WSEGL_ROTATE_0;
+ return WSEGL_SUCCESS;
+}
+
+/* Delete a specific drawable */
+static WSEGLError wseglDeleteDrawable(WSEGLDrawableHandle _drawable)
+{
+ PvrQwsDrawable *drawable = (PvrQwsDrawable *)_drawable;
+ if (!drawable || drawable->type == PvrQwsScreen)
+ return WSEGL_SUCCESS;
+ pvrQwsFreeBuffers(drawable);
+ if (pvrQwsReleaseWindow(drawable))
+ pvrQwsDestroyDrawable(drawable);
+ return WSEGL_SUCCESS;
+}
+
+/* Swap the contents of a drawable to the screen */
+static WSEGLError wseglSwapDrawable
+ (WSEGLDrawableHandle _drawable, unsigned long data)
+{
+ WSEGL_UNUSED(data);
+ PvrQwsDrawable *drawable = (PvrQwsDrawable *)_drawable;
+ if (drawable->type != PvrQwsPixmap && !pvrQwsSwapBuffers(drawable, 0))
+ return WSEGL_BAD_DRAWABLE;
+ else
+ return WSEGL_SUCCESS;
+}
+
+/* Set the swap interval of a window drawable */
+static WSEGLError wseglSwapControlInterval
+ (WSEGLDrawableHandle drawable, unsigned long interval)
+{
+ WSEGL_UNUSED(drawable);
+ if (pvrQwsDisplay.flipChain) {
+ PVR2DSetPresentFlipProperties
+ (pvrQwsDisplay.context, pvrQwsDisplay.flipChain,
+ PVR2D_PRESENT_PROPERTY_INTERVAL, 0, 0, 0, NULL, interval);
+ }
+ return WSEGL_SUCCESS;
+}
+
+/* Flush native rendering requests on a drawable */
+static WSEGLError wseglWaitNative
+ (WSEGLDrawableHandle drawable, unsigned long engine)
+{
+ WSEGL_UNUSED(drawable);
+ if (engine == WSEGL_DEFAULT_NATIVE_ENGINE)
+ return WSEGL_SUCCESS;
+ else
+ return WSEGL_BAD_NATIVE_ENGINE;
+}
+
+/* Copy color data from a drawable to a native pixmap */
+static WSEGLError wseglCopyFromDrawable
+ (WSEGLDrawableHandle _drawable, NativePixmapType nativePixmap)
+{
+ PvrQwsDrawable *drawable = (PvrQwsDrawable *)_drawable;
+ PvrQwsDrawable *pixmap = (PvrQwsDrawable *)nativePixmap;
+ PVR2DBLTINFO blit;
+
+ if (!drawable || !drawable->backBuffersValid)
+ return WSEGL_BAD_NATIVE_WINDOW;
+ if (!pixmap || !pixmap->backBuffersValid)
+ return WSEGL_BAD_NATIVE_PIXMAP;
+
+ memset(&blit, 0, sizeof(blit));
+
+ blit.CopyCode = PVR2DROPcopy;
+ blit.BlitFlags = PVR2D_BLIT_DISABLE_ALL;
+
+ blit.pSrcMemInfo = drawable->backBuffers[drawable->currentBackBuffer];
+ blit.SrcStride = drawable->strideBytes;
+ blit.SrcX = 0;
+ blit.SrcY = 0;
+ blit.SizeX = drawable->rect.width;
+ blit.SizeY = drawable->rect.height;
+ blit.SrcFormat = drawable->pixelFormat;
+
+ blit.pDstMemInfo = pixmap->backBuffers[pixmap->currentBackBuffer];
+ blit.DstStride = pixmap->strideBytes;
+ blit.DstX = 0;
+ blit.DstY = 0;
+ blit.DSizeX = pixmap->rect.width;
+ blit.DSizeY = pixmap->rect.height;
+ blit.DstFormat = pixmap->pixelFormat;
+
+ PVR2DBlt(pvrQwsDisplay.context, &blit);
+ PVR2DQueryBlitsComplete
+ (pvrQwsDisplay.context, pixmap->backBuffers[pixmap->currentBackBuffer], 1);
+
+ return WSEGL_SUCCESS;
+}
+
+/* Copy color data from a PBuffer to a native pixmap */
+static WSEGLError wseglCopyFromPBuffer
+ (void *address, unsigned long width, unsigned long height,
+ unsigned long stride, WSEGLPixelFormat format,
+ NativePixmapType nativePixmap)
+{
+ PvrQwsDrawable *pixmap = (PvrQwsDrawable *)nativePixmap;
+ PVR2DFORMAT pixelFormat;
+
+ if (!pixmap)
+ return WSEGL_BAD_NATIVE_PIXMAP;
+
+ /* We can only copy under certain conditions */
+ switch (format) {
+ case WSEGL_PIXELFORMAT_565:
+ pixelFormat = PVR2D_RGB565; break;
+ case WSEGL_PIXELFORMAT_4444:
+ pixelFormat = PVR2D_ARGB4444; break;
+ case WSEGL_PIXELFORMAT_8888:
+ pixelFormat = PVR2D_ARGB8888; break;
+ default:
+ return WSEGL_BAD_CONFIG;
+ }
+ if (width > (unsigned long)(pixmap->rect.width) ||
+ height > (unsigned long)(pixmap->rect.height) ||
+ pixelFormat != pixmap->pixelFormat) {
+ return WSEGL_BAD_CONFIG;
+ }
+
+ /* We'd like to use PVR2DBlt to do this, but there is no easy way
+ to map the virtual "address" into physical space to be able
+ to use the hardware assist. Use memcpy to do the work instead.
+ Note: PBuffer's are upside down, so we copy from the bottom up */
+ char *srcaddr = (char *)address;
+ char *dstaddr = (char *)(pixmap->backBuffers[pixmap->currentBackBuffer]->pBase);
+ int dststride = pixmap->strideBytes;
+ int srcwidth = ((int)width) * pvrQwsDisplay.screens[0].bytesPerPixel;
+ srcaddr += height * stride;
+ while (height > 0) {
+ srcaddr -= (int)stride;
+ memcpy(dstaddr, srcaddr, srcwidth);
+ dstaddr += dststride;
+ --height;
+ }
+ return WSEGL_SUCCESS;
+}
+
+/* Return the parameters of a drawable that are needed by the EGL layer */
+static WSEGLError wseglGetDrawableParameters
+ (WSEGLDrawableHandle _drawable, WSEGLDrawableParams *sourceParams,
+ WSEGLDrawableParams *renderParams)
+{
+ PvrQwsDrawable *drawable = (PvrQwsDrawable *)_drawable;
+ PVR2DMEMINFO *source, *render;
+ WSEGLPixelFormat pixelFormat;
+
+ if (!pvrQwsGetBuffers(drawable, &source, &render))
+ return WSEGL_BAD_DRAWABLE;
+
+ switch (drawable->pixelFormat) {
+ case PVR2D_RGB565:
+ default:
+ pixelFormat = WSEGL_PIXELFORMAT_565;
+ break;
+
+ case PVR2D_ARGB4444:
+ pixelFormat = WSEGL_PIXELFORMAT_4444;
+ break;
+
+ case PVR2D_ARGB8888:
+ pixelFormat = WSEGL_PIXELFORMAT_8888;
+ break;
+ }
+
+ sourceParams->ui32Width = drawable->rect.width;
+ sourceParams->ui32Height = drawable->rect.height;
+ sourceParams->ui32Stride = drawable->stridePixels;
+ sourceParams->ePixelFormat = pixelFormat;
+ sourceParams->pvLinearAddress = source->pBase;
+ sourceParams->ui32HWAddress = source->ui32DevAddr;
+ sourceParams->hPrivateData = source->hPrivateData;
+
+ renderParams->ui32Width = drawable->rect.width;
+ renderParams->ui32Height = drawable->rect.height;
+ renderParams->ui32Stride = drawable->stridePixels;
+ renderParams->ePixelFormat = pixelFormat;
+ renderParams->pvLinearAddress = render->pBase;
+ renderParams->ui32HWAddress = render->ui32DevAddr;
+ renderParams->hPrivateData = render->hPrivateData;
+
+ return WSEGL_SUCCESS;
+}
+
+static WSEGL_FunctionTable const wseglFunctions = {
+ WSEGL_VERSION,
+ wseglIsDisplayValid,
+ wseglInitializeDisplay,
+ wseglCloseDisplay,
+ wseglCreateWindowDrawable,
+ wseglCreatePixmapDrawable,
+ wseglDeleteDrawable,
+ wseglSwapDrawable,
+ wseglSwapControlInterval,
+ wseglWaitNative,
+ wseglCopyFromDrawable,
+ wseglCopyFromPBuffer,
+ wseglGetDrawableParameters
+};
+
+/* Return the table of WSEGL functions to the EGL implementation */
+const WSEGL_FunctionTable *WSEGL_GetFunctionTablePointer(void)
+{
+ return &wseglFunctions;
+}
diff --git a/src/plugins/gfxdrivers/powervr/README b/src/plugins/gfxdrivers/powervr/README
new file mode 100644
index 0000000..b830066
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/README
@@ -0,0 +1,56 @@
+PowerVR QScreen Driver
+======================
+
+This QScreen plugin driver allows the QtOpenGl module to integrate with PowerVR
+hardware from Imagination Technologies. Using this plugin, applications may use
+QGLWidget & QGLPixelBuffer with OpenGL ES. The integration with PowerVR drivers
+is built as two libraries: The actual QScreen plugin used by Qt (in the
+pvreglscreen directory) and a WSEGL plugin for the PowerVR drivers (in the
+QWSWSEGL directory).
+
+The PowerVR drivers provide the WSEGL plugin API to allow window systems such as
+QWS to integrate correctly. In order to use the integration, the WSEGL plugin
+(libpvrQWSWSEGL.so, usually installed into the Qt library directory) must be in
+the LD library path. The PowerVR driver also needs to be told which WSEGL library
+to use. This is done by creating/modifying /etc/powervr.ini:
+
+[default]
+WindowSystem=libpvrQWSWSEGL.so
+
+Note: It is important that the /etc/powervr.ini file not contain ^M (Ctrl-M) DOS
+end of line markers at the end of its lines. If ^M markers are present, then the
+libpvrQWSWSEGL.so driver will not be loaded and the default null Linux driver
+will be loaded silently instead. Make sure that the end of line markers are
+strictly Unix-style markers.
+
+
+***************************************************************************
+* IMPORTANT: To build the QScreen plugin and the WSEGL library it depends *
+* on, the pvr2d.h, wsegl.h headers for your platform are required. These *
+* can be obtained either through your platform provider or directly from *
+* Imagination Technologies. *
+***************************************************************************
+
+
+When you start a Qt/Embedded application, you should modify the QWS_DISPLAY
+environment variable to use the "powervr" driver instead of "LinuxFb". For
+example, if your original QWS_DISPLAY variable was:
+
+ LinuxFb:mmWidth40:mmHeight54:0
+
+then it should be changed to:
+
+ powervr:mmWidth40:mmHeight54:0
+
+To test the OpenGL ES integration, you can use the hellogl_es example and run it
+on the device with:
+
+ hellogl_es -qws
+
+
+Know Issues:
+ * A QGLWidget may not have window decorations if it is a top-level window.
+ * On some platforms, starting a QWS application after the system has been up
+ for a long time may cause the driver to fail. This is due to fragmentation
+ of main memory prevening older PowerVR drivers from allocating a contiguous
+ region of phyical RAM for the GL surface.
diff --git a/src/plugins/gfxdrivers/powervr/powervr.pro b/src/plugins/gfxdrivers/powervr/powervr.pro
new file mode 100644
index 0000000..f31ad04
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/powervr.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = QWSWSEGL pvreglscreen
+CONFIG += ordered
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
new file mode 100644
index 0000000..3a94851
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** 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 "pvreglscreen.h"
+#include "pvreglwindowsurface.h"
+#include "pvrqwsdrawable_p.h"
+#include <QRegExp>
+#include <qwindowsystem_qws.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/kd.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+PvrEglScreen::PvrEglScreen(int displayId)
+ : QGLScreen(displayId)
+{
+ setOptions(NativeWindows);
+ setSupportsBlitInClients(true);
+ setSurfaceFunctions(new PvrEglScreenSurfaceFunctions(this, displayId));
+ fd = -1;
+ ttyfd = -1;
+ doGraphicsMode = true;
+ oldKdMode = KD_TEXT;
+ if (QWSServer::instance())
+ holder = new PvrEglSurfaceHolder();
+ else
+ holder = 0;
+}
+
+PvrEglScreen::~PvrEglScreen()
+{
+ if (fd >= 0)
+ ::close(fd);
+ delete holder;
+}
+
+bool PvrEglScreen::initDevice()
+{
+ openTty();
+ return true;
+}
+
+bool PvrEglScreen::connect(const QString &displaySpec)
+{
+ if (!pvrQwsDisplayOpen())
+ return false;
+
+ // Initialize the QScreen properties.
+ data = (uchar *)(pvrQwsDisplay.screens[0].mapped);
+ w = pvrQwsDisplay.screens[0].screenRect.width;
+ h = pvrQwsDisplay.screens[0].screenRect.height;
+ lstep = pvrQwsDisplay.screens[0].screenStride;
+ dw = w;
+ dh = h;
+ size = h * lstep;
+ mapsize = size;
+ switch (pvrQwsDisplay.screens[0].pixelFormat) {
+ case PVR2D_RGB565:
+ d = 16;
+ setPixelFormat(QImage::Format_RGB16);
+ break;
+ case PVR2D_ARGB4444:
+ d = 16;
+ setPixelFormat(QImage::Format_ARGB4444_Premultiplied);
+ break;
+ case PVR2D_ARGB8888:
+ d = 32;
+ setPixelFormat(QImage::Format_ARGB32);
+ break;
+ default:
+ pvrQwsDisplayClose();
+ qWarning("PvrEglScreen::connect: unsupported pixel format %d", (int)(pvrQwsDisplay.screens[0].pixelFormat));
+ return false;
+ }
+
+ // Handle display physical size spec.
+ QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
+ QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
+ int dimIdxW = displayArgs.indexOf(mmWidthRx);
+ QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
+ int dimIdxH = displayArgs.indexOf(mmHeightRx);
+ if (dimIdxW >= 0) {
+ mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
+ physWidth = mmWidthRx.cap(1).toInt();
+ if (dimIdxH < 0)
+ physHeight = dh*physWidth/dw;
+ }
+ if (dimIdxH >= 0) {
+ mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
+ physHeight = mmHeightRx.cap(1).toInt();
+ if (dimIdxW < 0)
+ physWidth = dw*physHeight/dh;
+ }
+ if (dimIdxW < 0 && dimIdxH < 0) {
+ const int dpi = 72;
+ physWidth = qRound(dw * 25.4 / dpi);
+ physHeight = qRound(dh * 25.4 / dpi);
+ }
+
+ // Find the name of the tty device to use.
+ QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
+ if (displayArgs.indexOf(ttyRegExp) != -1)
+ ttyDevice = ttyRegExp.cap(1);
+ if (displayArgs.contains(QLatin1String("nographicsmodeswitch")))
+ doGraphicsMode = false;
+
+ // The screen is ready.
+ return true;
+}
+
+void PvrEglScreen::disconnect()
+{
+ pvrQwsDisplayClose();
+}
+
+void PvrEglScreen::shutdownDevice()
+{
+ closeTty();
+}
+
+void PvrEglScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &region)
+{
+ QGLScreen::blit(img, topLeft, region);
+ sync();
+}
+
+void PvrEglScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ QGLScreen::solidFill(color, region);
+ sync();
+}
+
+bool PvrEglScreen::chooseContext
+ (QGLContext *context, const QGLContext *shareContext)
+{
+ // We use PvrEglScreenSurfaceFunctions instead.
+ Q_UNUSED(context);
+ Q_UNUSED(shareContext);
+ return false;
+}
+
+bool PvrEglScreen::hasOpenGL()
+{
+ return true;
+}
+
+QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const
+{
+ if (qobject_cast<QGLWidget*>(widget))
+ return new PvrEglWindowSurface(widget, (QScreen *)this, displayId);
+
+ return QScreen::createSurface(widget);
+}
+
+QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const
+{
+ if (key == QLatin1String("PvrEgl"))
+ return new PvrEglWindowSurface(holder);
+
+ return QScreen::createSurface(key);
+}
+
+void PvrEglScreen::sync()
+{
+ // Put code here to synchronize 2D and 3D operations if necessary.
+}
+
+void PvrEglScreen::openTty()
+{
+ const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
+
+ if (ttyDevice.isEmpty()) {
+ for (const char * const *dev = devs; *dev; ++dev) {
+ ttyfd = ::open(*dev, O_RDWR);
+ if (ttyfd != -1)
+ break;
+ }
+ } else {
+ ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR);
+ }
+
+ if (ttyfd == -1)
+ return;
+
+ ::fcntl(ttyfd, F_SETFD, FD_CLOEXEC);
+
+ if (doGraphicsMode) {
+ ioctl(ttyfd, KDGETMODE, &oldKdMode);
+ if (oldKdMode != KD_GRAPHICS) {
+ int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
+ if (ret == -1)
+ doGraphicsMode = false;
+ }
+ }
+
+ // No blankin' screen, no blinkin' cursor!, no cursor!
+ const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
+ ::write(ttyfd, termctl, sizeof(termctl));
+}
+
+void PvrEglScreen::closeTty()
+{
+ if (ttyfd == -1)
+ return;
+
+ if (doGraphicsMode)
+ ioctl(ttyfd, KDSETMODE, oldKdMode);
+
+ // Blankin' screen, blinkin' cursor!
+ const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
+ ::write(ttyfd, termctl, sizeof(termctl));
+
+ ::close(ttyfd);
+ ttyfd = -1;
+}
+
+bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native)
+{
+ QWSWindowSurface *surface =
+ static_cast<QWSWindowSurface *>(widget->windowSurface());
+ if (!surface) {
+ // The widget does not have a surface yet, so give it one.
+ surface = new PvrEglWindowSurface(widget, screen, displayId);
+ widget->setWindowSurface(surface);
+ } else if (surface->key() != QLatin1String("PvrEgl")) {
+ // The application has attached a QGLContext to an ordinary QWidget.
+ // Replace the widget's window surface with a new one that can do GL.
+ QRect geometry = widget->frameGeometry();
+ geometry.moveTo(widget->mapToGlobal(QPoint(0, 0)));
+ surface = new PvrEglWindowSurface(widget, screen, displayId);
+ surface->setGeometry(geometry);
+ widget->setWindowSurface(surface);
+ widget->setAttribute(Qt::WA_NoSystemBackground, true);
+ }
+ PvrEglWindowSurface *nsurface = static_cast<PvrEglWindowSurface*>(surface);
+ *native = (EGLNativeWindowType)(nsurface->nativeDrawable());
+ return true;
+}
+
+// The PowerVR engine on the device needs to allocate about 2Mb of
+// contiguous physical memory to manage drawing into a surface.
+//
+// The problem is that once Qtopia begins its startup sequence,
+// it allocates enough memory to severely fragment the physical
+// address space on the device. This leaves the PowerVR engine
+// unable to allocate the necessary contiguous physical memory
+// when an EGL surface is created.
+//
+// A solution to this is to pre-allocate a dummy surface early
+// in the startup sequence before memory becomes fragmented,
+// reserving it for any future EGL applications to use.
+//
+// However, the PowerVR engine has problems managing multiple
+// surfaces concurrently, and so real EGL applications end up
+// with unacceptably slow frame rates unless the dummy surface
+// is destroyed while the real EGL applications are running.
+//
+// In summary, we need to try to ensure that there is always at
+// least one EGL surface active at any given time to reserve the
+// memory but destroy the temporary surface when a real surface
+// is using the device. That is the purpose of PvrEglSurfaceHolder.
+
+PvrEglSurfaceHolder::PvrEglSurfaceHolder(QObject *parent)
+ : QObject(parent)
+{
+ numRealSurfaces = 0;
+
+ PvrQwsRect rect;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = 16;
+ rect.height = 16;
+ tempSurface = pvrQwsCreateWindow(0, -1, &rect);
+
+ dpy = EGL_NO_DISPLAY;
+ config = 0;
+ surface = EGL_NO_SURFACE;
+
+ dpy = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
+ if (!eglInitialize(dpy, 0, 0)) {
+ qWarning("Could not initialize EGL display - are the drivers loaded?");
+ dpy = EGL_NO_DISPLAY;
+ return;
+ }
+
+ EGLint attribList[16];
+ int temp = 0;
+ attribList[temp++] = EGL_LEVEL; // Framebuffer level 0
+ attribList[temp++] = 0;
+ attribList[temp++] = EGL_SURFACE_TYPE;
+ attribList[temp++] = EGL_WINDOW_BIT;
+ attribList[temp++] = EGL_NONE;
+
+ EGLint numConfigs = 0;
+ if (!eglChooseConfig(dpy, attribList, &config, 1, &numConfigs) || numConfigs != 1) {
+ qWarning("Could not find a matching a EGL configuration");
+ eglTerminate(dpy);
+ dpy = EGL_NO_DISPLAY;
+ return;
+ }
+
+ surface = eglCreateWindowSurface
+ (dpy, config, (EGLNativeWindowType)(-1), NULL);
+ if (surface == EGL_NO_SURFACE)
+ qWarning("Could not create the temporary EGL surface");
+}
+
+PvrEglSurfaceHolder::~PvrEglSurfaceHolder()
+{
+ if (surface != EGL_NO_SURFACE)
+ eglDestroySurface(dpy, surface);
+ if (dpy != EGL_NO_DISPLAY)
+ eglTerminate(dpy);
+ if (tempSurface)
+ pvrQwsDestroyDrawable(tempSurface);
+}
+
+// Add a real EGL surface to the system.
+void PvrEglSurfaceHolder::addSurface()
+{
+ ++numRealSurfaces;
+ if (numRealSurfaces == 1) {
+ // Destroy the temporary surface while some other application
+ // is making use of the EGL sub-system for 3D rendering.
+ if (surface != EGL_NO_SURFACE) {
+ eglDestroySurface(dpy, surface);
+ surface = EGL_NO_SURFACE;
+ }
+ }
+}
+
+// Remove an actual EGL surface from the system.
+void PvrEglSurfaceHolder::removeSurface()
+{
+ if (numRealSurfaces > 0) {
+ --numRealSurfaces;
+ if (numRealSurfaces == 0) {
+ // The last real EGL surface has been destroyed, so re-create
+ // the temporary surface. There is a race condition here in
+ // that Qtopia could allocate a lot of memory just after
+ // the real EGL surface is destroyed but before we could
+ // create the temporary surface again.
+ if (surface == EGL_NO_SURFACE && dpy != EGL_NO_DISPLAY) {
+ surface = eglCreateWindowSurface
+ (dpy, config, (EGLNativeWindowType)tempSurface, NULL);
+ if (surface == EGL_NO_SURFACE)
+ qWarning("Could not re-create the temporary EGL surface");
+ }
+ }
+ }
+}
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
new file mode 100644
index 0000000..ee27e36
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PVREGLSCREEN_H
+#define PVREGLSCREEN_H
+
+#include <QScreen>
+#include <QGLScreen>
+#include "pvrqwsdrawable.h"
+
+class PvrEglScreenSurfaceFunctions : public QGLScreenSurfaceFunctions
+{
+public:
+ PvrEglScreenSurfaceFunctions(QScreen *s, int screenNum)
+ : screen(s), displayId(screenNum) {}
+
+ bool createNativeWindow(QWidget *widget, EGLNativeWindowType *native);
+
+private:
+ QScreen *screen;
+ int displayId;
+};
+
+class PvrEglSurfaceHolder : public QObject
+{
+ Q_OBJECT
+public:
+ PvrEglSurfaceHolder(QObject *parent=0);
+ ~PvrEglSurfaceHolder();
+
+ void addSurface();
+ void removeSurface();
+
+private:
+ int numRealSurfaces;
+ PvrQwsDrawable *tempSurface;
+ EGLDisplay dpy;
+ EGLConfig config;
+ EGLSurface surface;
+};
+
+class PvrEglScreen : public QGLScreen
+{
+public:
+ PvrEglScreen(int displayId);
+ ~PvrEglScreen();
+
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+ void setMode(int, int, int) {}
+
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void solidFill(const QColor &color, const QRegion &region);
+
+ bool chooseContext(QGLContext *context, const QGLContext *shareContext);
+ bool hasOpenGL();
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+private:
+ void sync();
+ void openTty();
+ void closeTty();
+
+ int fd;
+ int ttyfd, oldKdMode;
+ PvrEglSurfaceHolder *holder;
+ QString ttyDevice;
+ bool doGraphicsMode;
+};
+
+#endif
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro
new file mode 100644
index 0000000..691cd2d
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro
@@ -0,0 +1,24 @@
+TEMPLATE = lib
+TARGET = qgfxpvregl
+CONFIG += qt plugin warn_on
+QT += opengl
+
+LIBS += -lpvrQWSWSEGL
+
+DEFINES += QT_QWS_CLIENTBLIT
+
+INCLUDEPATH += ../QWSWSEGL
+
+HEADERS = \
+ pvreglscreen.h \
+ pvreglwindowsurface.h
+
+SOURCES = \
+ pvreglscreenplugin.cpp \
+ pvreglscreen.cpp \
+ pvreglwindowsurface.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers
+
+target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers
+INSTALLS += target
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp
new file mode 100644
index 0000000..e9748d6
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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 "pvreglscreen.h"
+
+#include <QScreenDriverPlugin>
+#include <QStringList>
+
+class PvrEglScreenPlugin : public QScreenDriverPlugin
+{
+public:
+ PvrEglScreenPlugin();
+
+ QStringList keys() const;
+ QScreen *create(const QString&, int displayId);
+};
+
+PvrEglScreenPlugin::PvrEglScreenPlugin()
+ : QScreenDriverPlugin()
+{
+}
+
+QStringList PvrEglScreenPlugin::keys() const
+{
+ return (QStringList() << "powervr");
+}
+
+QScreen* PvrEglScreenPlugin::create(const QString& driver, int displayId)
+{
+ if (driver.toLower() != "powervr")
+ return 0;
+
+ return new PvrEglScreen(displayId);
+}
+
+Q_EXPORT_PLUGIN2(qgfxpvregl, PvrEglScreenPlugin)
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
new file mode 100644
index 0000000..e7f4987
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** 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 "pvreglwindowsurface.h"
+#include "pvreglscreen.h"
+#include <QScreen>
+#include <QDebug>
+#include <QWSDisplay>
+
+PvrEglWindowSurface::PvrEglWindowSurface
+ (QWidget *widget, QScreen *screen, int screenNum)
+ : QWSGLWindowSurface(widget)
+{
+ setSurfaceFlags(QWSWindowSurface::Opaque);
+
+ this->widget = widget;
+ this->screen = screen;
+ this->holder = 0;
+ this->pdevice = 0;
+
+ QPoint pos = offset(widget);
+ QSize size = widget->size();
+
+ PvrQwsRect pvrRect;
+ pvrRect.x = pos.x();
+ pvrRect.y = pos.y();
+ pvrRect.width = size.width();
+ pvrRect.height = size.height();
+
+ // Try to recover a previous PvrQwsDrawable object for the widget
+ // if there is one. This can happen when a PvrEglWindowSurface
+ // is created for a widget, bound to a EGLSurface, and then destroyed.
+ // When a new PvrEglWindowSurface is created for the widget, it will
+ // pick up the previous PvrQwsDrawable if the EGLSurface has not been
+ // destroyed in the meantime.
+ drawable = pvrQwsFetchWindow((long)widget);
+ if (drawable)
+ pvrQwsSetGeometry(drawable, &pvrRect);
+ else
+ drawable = pvrQwsCreateWindow(screenNum, (long)widget, &pvrRect);
+}
+
+PvrEglWindowSurface::PvrEglWindowSurface(PvrEglSurfaceHolder *holder)
+ : QWSGLWindowSurface()
+{
+ setSurfaceFlags(QWSWindowSurface::Opaque);
+ drawable = 0;
+ widget = 0;
+ screen = 0;
+ pdevice = 0;
+
+ this->holder = holder;
+ holder->addSurface();
+}
+
+PvrEglWindowSurface::~PvrEglWindowSurface()
+{
+ // Release the PvrQwsDrawable. If it is bound to an EGLSurface,
+ // then it will stay around until a new PvrEglWindowSurface is
+ // created for the widget. If it is not bound to an EGLSurface,
+ // it will be destroyed immediately.
+ if (drawable && pvrQwsReleaseWindow(drawable))
+ pvrQwsDestroyDrawable(drawable);
+
+ if (holder)
+ holder->removeSurface();
+ delete pdevice;
+}
+
+bool PvrEglWindowSurface::isValid() const
+{
+ return (widget != 0);
+}
+
+void PvrEglWindowSurface::setGeometry(const QRect &rect)
+{
+ if (drawable) {
+ // XXX: adjust for the screen offset.
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ pvrRect.y = rect.y();
+ pvrRect.width = rect.width();
+ pvrRect.height = rect.height();
+ pvrQwsSetGeometry(drawable, &pvrRect);
+ }
+ QWSGLWindowSurface::setGeometry(rect);
+}
+
+bool PvrEglWindowSurface::move(const QPoint &offset)
+{
+ QRect rect = geometry().translated(offset);
+ if (drawable) {
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ pvrRect.y = rect.y();
+ pvrRect.width = rect.width();
+ pvrRect.height = rect.height();
+ pvrQwsSetGeometry(drawable, &pvrRect);
+ }
+ return QWSGLWindowSurface::move(offset);
+}
+
+QByteArray PvrEglWindowSurface::permanentState() const
+{
+ // Nothing interesting to pass to the server just yet.
+ return QByteArray();
+}
+
+void PvrEglWindowSurface::setPermanentState(const QByteArray &state)
+{
+ Q_UNUSED(state);
+}
+
+QImage PvrEglWindowSurface::image() const
+{
+ if (drawable) {
+ PvrQwsRect pvrRect;
+ pvrQwsGetGeometry(drawable, &pvrRect);
+ void *data = pvrQwsGetRenderBuffer(drawable);
+ if (data) {
+ return QImage((uchar *)data, pvrRect.width, pvrRect.height,
+ pvrQwsGetStride(drawable), QImage::Format_RGB16);
+ }
+ }
+ return QImage();
+}
+
+QPaintDevice *PvrEglWindowSurface::paintDevice()
+{
+ // Return a dummy paint device because the widget itself
+ // cannot be painted to this way.
+ if (!pdevice)
+ pdevice = new QImage(50, 50, QImage::Format_RGB16);
+ return pdevice;
+}
+
+void PvrEglWindowSurface::setDirectRegion(const QRegion &r, int id)
+{
+ QWSGLWindowSurface::setDirectRegion(r, id);
+
+ if (!drawable)
+ return;
+
+ // Clip the region to the window boundaries in case the child
+ // is partially outside the geometry of the parent.
+ QWidget *window = widget->window();
+ QRegion region = r;
+ if (widget != window) {
+ QRect rect = window->geometry();
+ rect.moveTo(window->mapToGlobal(QPoint(0, 0)));
+ region = region.intersect(rect);
+ }
+
+ if (region.isEmpty()) {
+ pvrQwsClearVisibleRegion(drawable);
+ } else if (region.numRects() == 1) {
+ QRect rect = region.boundingRect();
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ pvrRect.y = rect.y();
+ pvrRect.width = rect.width();
+ pvrRect.height = rect.height();
+ pvrQwsSetVisibleRegion(drawable, &pvrRect, 1);
+ if (!pvrQwsSwapBuffers(drawable, 1))
+ screen->solidFill(QColor(0, 0, 0), region);
+ } else {
+ QVector<QRect> rects = region.rects();
+ PvrQwsRect *pvrRects = new PvrQwsRect [rects.size()];
+ for (int index = 0; index < rects.size(); ++index) {
+ QRect rect = rects[index];
+ pvrRects[index].x = rect.x();
+ pvrRects[index].y = rect.y();
+ pvrRects[index].width = rect.width();
+ pvrRects[index].height = rect.height();
+ }
+ pvrQwsSetVisibleRegion(drawable, pvrRects, rects.size());
+ if (!pvrQwsSwapBuffers(drawable, 1))
+ screen->solidFill(QColor(0, 0, 0), region);
+ delete [] pvrRects;
+ }
+}
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h
new file mode 100644
index 0000000..8bec796
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PVREGLWINDOWSURFACE_H
+#define PVREGLWINDOWSURFACE_H
+
+#include <private/qglwindowsurface_qws_p.h>
+#include "pvrqwsdrawable.h"
+
+class QScreen;
+class PvrEglSurfaceHolder;
+
+class PvrEglWindowSurface : public QWSGLWindowSurface
+{
+public:
+ PvrEglWindowSurface(QWidget *widget, QScreen *screen, int screenNum);
+ PvrEglWindowSurface(PvrEglSurfaceHolder *holder);
+ ~PvrEglWindowSurface();
+
+ QString key() const { return QLatin1String("PvrEgl"); }
+
+ bool isValid() const;
+
+ void setGeometry(const QRect &rect);
+ bool move(const QPoint &offset);
+
+ QByteArray permanentState() const;
+ void setPermanentState(const QByteArray &state);
+
+ QImage image() const;
+ QPaintDevice *paintDevice();
+
+ void setDirectRegion(const QRegion &region, int id);
+
+ long nativeDrawable() const { return (long)widget; }
+
+private:
+ QWidget *widget;
+ PvrQwsDrawable *drawable;
+ QScreen *screen;
+ PvrEglSurfaceHolder *holder;
+ QPaintDevice *pdevice;
+};
+
+#endif