summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/powervr/QWSWSEGL
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/plugins/gfxdrivers/powervr/QWSWSEGL
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/plugins/gfxdrivers/powervr/QWSWSEGL')
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro26
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c830
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h169
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h132
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c402
5 files changed, 1559 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 0000000000..595cf45301
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro
@@ -0,0 +1,26 @@
+TEMPLATE = lib
+TARGET = pvrQWSWSEGL
+CONFIG += dll warn_on
+CONFIG -= qt
+
+HEADERS+=\
+ pvrqwsdrawable.h \
+ pvrqwsdrawable_p.h
+
+SOURCES+=\
+ pvrqwsdrawable.c \
+ pvrqwswsegl.c
+
+INCLUDEPATH += $$QMAKE_INCDIR_EGL
+
+for(p, QMAKE_LIBDIR_EGL) {
+ exists($$p):LIBS += -L$$p
+}
+
+LIBS += -lpvr2d
+
+DESTDIR = $$QMAKE_LIBDIR_QT
+target.path = $$[QT_INSTALL_LIBS]
+INSTALLS += target
+
+include(../powervr.pri) \ No newline at end of file
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c
new file mode 100644
index 0000000000..8dc0120fe1
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c
@@ -0,0 +1,830 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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].initialized)
+ 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 = fix.line_length;
+ 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;
+
+ if (screen == 0) {
+ /* We use PVR2DGetFrameBuffer to map the first screen.
+ On some chipsets it is more reliable than using PVR2DMemWrap */
+ mapped = 0;
+ memInfo = 0;
+ } else {
+ /* Other screens: 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].screenDrawable = 0;
+ if (mapped) {
+ /* Don't set these fields if mapped is 0, because PVR2DGetFrameBuffer
+ may have already been called and set them */
+ pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
+ pvrQwsDisplay.screens[screen].mapped = mapped;
+ }
+ pvrQwsDisplay.screens[screen].mappedLength = length;
+ pvrQwsDisplay.screens[screen].screenStart = start;
+ pvrQwsDisplay.screens[screen].needsUnmap = (mapped != 0);
+ pvrQwsDisplay.screens[screen].initialized = 1;
+ 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 (screen != 0 && 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;
+ } else if (screen == 0) {
+ if (PVR2DGetFrameBuffer
+ (pvrQwsDisplay.context,
+ PVR2D_FB_PRIMARY_SURFACE, &memInfo) != PVR2D_OK) {
+ fprintf(stderr, "QWSWSEGL: could not get the primary framebuffer surface\n");
+ PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
+ pvrQwsDisplay.context = 0;
+ return 0;
+ }
+ pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
+ pvrQwsDisplay.screens[screen].mapped = memInfo->pBase;
+ }
+ }
+
+ /* 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 && info->needsUnmap)
+ 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;
+}
+
+void pvrQwsSetRotation(PvrQwsDrawable *drawable, int angle)
+{
+ if (drawable->rotationAngle != angle) {
+ drawable->rotationAngle = angle;
+
+ /* Force the buffers to be recreated if the rotation angle changes */
+ pvrQwsInvalidateBuffers(drawable);
+ }
+}
+
+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 + 31) & ~31;
+ 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;
+}
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h
new file mode 100644
index 0000000000..8c8cc27018
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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);
+
+/* Set the rotation angle in degrees */
+void pvrQwsSetRotation(PvrQwsDrawable *drawable, int angle);
+
+/* 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);
+
+#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 0000000000..3ad0693e02
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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;
+ int needsUnmap;
+ int initialized;
+
+} 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;
+ int rotationAngle;
+ 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 0000000000..f861838e90
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <GLES/eglplatform.h>
+#include <wsegl.h>
+#include <pvr2d.h>
+#include <string.h>
+#include <sys/mman.h>
+#include "pvrqwsdrawable_p.h"
+
+#define WSEGL_UNUSED(x) (void)x;
+
+// If the PVR2D version is not specified, then assume MBX-style headers.
+// If the version is defined, then we assume that we have SGX-style headers.
+#if !defined(PVR2D_REV_MAJOR)
+#define WSEGL_CAP_WINDOWS_USE_HW_SYNC WSEGL_CAP_WINDOWS_USE_MBX_SYNC
+#define WSEGL_CAP_PIXMAPS_USE_HW_SYNC WSEGL_CAP_PIXMAPS_USE_MBX_SYNC
+#endif
+
+/* Capability information for the display */
+static WSEGLCaps const wseglDisplayCaps[] = {
+ {WSEGL_CAP_WINDOWS_USE_HW_SYNC, 1},
+ {WSEGL_CAP_PIXMAPS_USE_HW_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;
+}
+
+static WSEGLRotationAngle wseglRotationValue(int degrees)
+{
+ switch (degrees) {
+ case 90: return WSEGL_ROTATE_90;
+ case 180: return WSEGL_ROTATE_180;
+ case 270: return WSEGL_ROTATE_270;
+ default: return WSEGL_ROTATE_0;
+ }
+}
+
+/* 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 = wseglRotationValue(screen->rotationAngle);
+ 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 = wseglRotationValue(draw->rotationAngle);
+ 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;
+ if (pvrQwsDisplay.numFlipBuffers == 0)
+ 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;
+}