summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/powervr/QWSWSEGL
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/powervr/QWSWSEGL')
-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
5 files changed, 1574 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;
+}