summaryrefslogtreecommitdiffstats
path: root/src/openvg/qwindowsurface_vgegl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvg/qwindowsurface_vgegl.cpp')
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp751
1 files changed, 751 insertions, 0 deletions
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
new file mode 100644
index 0000000..11c7021
--- /dev/null
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -0,0 +1,751 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenVG module 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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsurface_vgegl_p.h"
+#include "qpaintengine_vg_p.h"
+#include "qpixmapdata_vg_p.h"
+#include "qvg_p.h"
+
+#if !defined(QT_NO_EGL)
+
+QT_BEGIN_NAMESPACE
+
+// Turn off "direct to window" rendering if EGL cannot support it.
+#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER)
+#if defined(QVG_DIRECT_TO_WINDOW)
+#undef QVG_DIRECT_TO_WINDOW
+#endif
+#endif
+
+// Determine if preserved window contents should be used.
+#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED)
+#if !defined(QVG_NO_PRESERVED_SWAP)
+#define QVG_NO_PRESERVED_SWAP 1
+#endif
+#endif
+
+VGImageFormat qt_vg_config_to_vg_format(QEglContext *context)
+{
+ return qt_vg_image_to_vg_format
+ (qt_vg_config_to_image_format(context));
+}
+
+QImage::Format qt_vg_config_to_image_format(QEglContext *context)
+{
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+ context->configAttrib(EGL_RED_SIZE, &red);
+ context->configAttrib(EGL_GREEN_SIZE, &green);
+ context->configAttrib(EGL_BLUE_SIZE, &blue);
+ context->configAttrib(EGL_ALPHA_SIZE, &alpha);
+ QImage::Format argbFormat;
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ EGLint type = 0;
+ context->configAttrib(EGL_SURFACE_TYPE, &type);
+ if ((type & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0)
+ argbFormat = QImage::Format_ARGB32_Premultiplied;
+ else
+ argbFormat = QImage::Format_ARGB32;
+#else
+ argbFormat = QImage::Format_ARGB32;
+#endif
+ if (red == 8 && green == 8 && blue == 8 && alpha == 8)
+ return argbFormat;
+ else if (red == 8 && green == 8 && blue == 8 && alpha == 0)
+ return QImage::Format_RGB32;
+ else if (red == 5 && green == 6 && blue == 5 && alpha == 0)
+ return QImage::Format_RGB16;
+ else if (red == 4 && green == 4 && blue == 4 && alpha == 4)
+ return QImage::Format_ARGB4444_Premultiplied;
+ else
+ return argbFormat; // XXX
+}
+
+static void copySubImage(QImage *image, VGImage vgImage, const QRect& rect)
+{
+ vgGetImageSubData
+ (vgImage,
+ image->bits() + rect.bottom() * image->bytesPerLine() +
+ rect.x() * (image->depth() / 8),
+ -(image->bytesPerLine()),
+ qt_vg_image_to_vg_format(image->format()),
+ rect.x(), (image->height() - 1) - rect.bottom(),
+ rect.width(), rect.height());
+}
+
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+
+class QVGSharedContext
+{
+public:
+ QVGSharedContext();
+ ~QVGSharedContext();
+
+ QEglContext *context;
+ int refCount;
+ QVGPaintEngine *engine;
+ EGLSurface surface;
+ EGLSurface lastSurface;
+};
+
+QVGSharedContext::QVGSharedContext()
+ : context(0)
+ , refCount(0)
+ , engine(0)
+ , surface(EGL_NO_SURFACE)
+ , lastSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGSharedContext::~QVGSharedContext()
+{
+ if (context)
+ qt_vg_make_current(context, qt_vg_shared_surface());
+ delete engine;
+ if (context)
+ qt_vg_done_current(context, true);
+ if (surface != EGL_NO_SURFACE)
+ qt_vg_destroy_surface(context, surface);
+ delete context;
+}
+
+Q_GLOBAL_STATIC(QVGSharedContext, sharedContext);
+
+QVGPaintEngine *qt_vg_create_paint_engine(void)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (!shared->engine)
+ shared->engine = new QVGPaintEngine();
+ return shared->engine;
+}
+
+void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
+{
+ Q_UNUSED(engine);
+}
+
+#else
+
+QVGPaintEngine *qt_vg_create_paint_engine(void)
+{
+ return new QVGPaintEngine();
+}
+
+void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
+{
+ delete engine;
+}
+
+#endif
+
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+
+static bool isPremultipliedContext(const QEglContext *context)
+{
+ EGLint value = 0;
+ if (context->configAttrib(EGL_SURFACE_TYPE, &value))
+ return (value & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0;
+ else
+ return false;
+}
+
+#endif
+
+static QEglContext *createContext(QPaintDevice *device)
+{
+ QEglContext *context;
+
+ // Create the context object and open the display.
+ context = new QEglContext();
+ context->setApi(QEgl::OpenVG);
+ if (!context->openDisplay(device)) {
+ delete context;
+ return 0;
+ }
+
+ // Choose an appropriate configuration for rendering into the device.
+ QEglProperties configProps;
+ configProps.setPaintDeviceFormat(device);
+ int redSize = configProps.value(EGL_RED_SIZE);
+ if (redSize == EGL_DONT_CARE || redSize == 0)
+ configProps.setPixelFormat(QImage::Format_ARGB32); // XXX
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT |
+ EGL_VG_ALPHA_FORMAT_PRE_BIT);
+ configProps.setRenderableType(QEgl::OpenVG);
+ if (!context->chooseConfig(configProps)) {
+ // Try again without the "pre" bit.
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ if (!context->chooseConfig(configProps)) {
+ delete context;
+ return 0;
+ }
+ }
+#else
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ configProps.setRenderableType(QEgl::OpenVG);
+ if (!context->chooseConfig(configProps)) {
+ delete context;
+ return 0;
+ }
+#endif
+
+ // Construct a new EGL context for the selected configuration.
+ if (!context->createContext()) {
+ delete context;
+ return 0;
+ }
+
+ return context;
+}
+
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+
+QEglContext *qt_vg_create_context(QPaintDevice *device)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->context) {
+ ++(shared->refCount);
+ return shared->context;
+ } else {
+ shared->context = createContext(device);
+ shared->refCount = 1;
+ return shared->context;
+ }
+}
+
+void qt_vg_destroy_context(QEglContext *context)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->context != context) {
+ // This is not the shared context. Shouldn't happen!
+ delete context;
+ } else if (--(shared->refCount) <= 0) {
+ qt_vg_make_current(shared->context, qt_vg_shared_surface());
+ delete shared->engine;
+ shared->engine = 0;
+ qt_vg_done_current(shared->context, true);
+ if (shared->surface != EGL_NO_SURFACE) {
+ qt_vg_destroy_surface(shared->context, shared->surface);
+ shared->surface = EGL_NO_SURFACE;
+ }
+ delete shared->context;
+ shared->context = 0;
+ }
+}
+
+EGLSurface qt_vg_shared_surface(void)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->surface == EGL_NO_SURFACE) {
+ EGLint attribs[7];
+ attribs[0] = EGL_WIDTH;
+ attribs[1] = 16;
+ attribs[2] = EGL_HEIGHT;
+ attribs[3] = 16;
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ if (isPremultipliedContext(shared->context)) {
+ attribs[4] = EGL_VG_ALPHA_FORMAT;
+ attribs[5] = EGL_VG_ALPHA_FORMAT_PRE;
+ attribs[6] = EGL_NONE;
+ } else
+#endif
+ {
+ attribs[4] = EGL_NONE;
+ }
+ shared->surface = eglCreatePbufferSurface
+ (shared->context->display(), shared->context->config(), attribs);
+ }
+ return shared->surface;
+}
+
+void qt_vg_make_current(QEglContext *context, EGLSurface surface)
+{
+ // Bail out if the context and surface are already current.
+ if (context->isCurrent() && context->surface() == surface)
+ return;
+
+ // Are we setting the surface to the same as the last elided doneCurrent()?
+ QVGSharedContext *shared = sharedContext();
+ if (context->isCurrent() && shared->lastSurface == surface) {
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->setSurface(surface);
+ return;
+ }
+
+ // Switch to the new context and surface.
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->setSurface(surface);
+ context->makeCurrent();
+}
+
+void qt_vg_done_current(QEglContext *context, bool force)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (force) {
+ context->doneCurrent();
+ shared->lastSurface = EGL_NO_SURFACE;
+ } else {
+ // Keep the context current for now just in case we immediately
+ // reuse the same surface for the next frame.
+ shared->lastSurface = context->surface();
+ }
+}
+
+void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->lastSurface == surface) {
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->doneCurrent();
+ }
+ context->setSurface(surface);
+ context->destroySurface();
+}
+
+#else
+
+QEglContext *qt_vg_create_context(QPaintDevice *device)
+{
+ return createContext(device);
+}
+
+void qt_vg_destroy_context(QEglContext *context)
+{
+ delete context;
+}
+
+EGLSurface qt_vg_shared_surface(void)
+{
+ return EGL_NO_SURFACE;
+}
+
+void qt_vg_make_current(QEglContext *context, EGLSurface surface)
+{
+ context->setSurface(surface);
+ context->makeCurrent();
+}
+
+void qt_vg_done_current(QEglContext *context, bool force)
+{
+ Q_UNUSED(force);
+ context->doneCurrent();
+}
+
+void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface)
+{
+ context->setSurface(surface);
+ context->destroySurface();
+}
+
+#endif
+
+QVGEGLWindowSurfacePrivate::QVGEGLWindowSurfacePrivate(QWindowSurface *win)
+{
+ winSurface = win;
+ engine = 0;
+}
+
+QVGEGLWindowSurfacePrivate::~QVGEGLWindowSurfacePrivate()
+{
+ // Destroy the paint engine if it hasn't been destroyed already.
+ destroyPaintEngine();
+}
+
+QVGEGLWindowSurfacePrivate *QVGEGLWindowSurfacePrivate::create
+ (SurfaceType type, QWindowSurface *win)
+{
+#if defined(QVG_VGIMAGE_BACKBUFFERS)
+ if (type == VGImageSurface)
+ return new QVGEGLWindowSurfaceVGImage(win);
+ else if (type == QImageSurface)
+ return new QVGEGLWindowSurfaceQImage(win);
+#endif
+ if (type == WindowSurface)
+ return new QVGEGLWindowSurfaceDirect(win);
+ return 0;
+}
+
+QVGPaintEngine *QVGEGLWindowSurfacePrivate::paintEngine()
+{
+ if (!engine)
+ engine = qt_vg_create_paint_engine();
+ return engine;
+}
+
+VGImage QVGEGLWindowSurfacePrivate::surfaceImage() const
+{
+ return VG_INVALID_HANDLE;
+}
+
+void QVGEGLWindowSurfacePrivate::destroyPaintEngine()
+{
+ if (engine) {
+ qt_vg_destroy_paint_engine(engine);
+ engine = 0;
+ }
+}
+
+QSize QVGEGLWindowSurfacePrivate::windowSurfaceSize(QWidget *widget) const
+{
+ Q_UNUSED(widget);
+
+ QRect rect = winSurface->geometry();
+ QSize newSize = rect.size();
+
+#if defined(Q_WS_QWS)
+ // Account for the widget mask, if any.
+ if (widget && !widget->mask().isEmpty()) {
+ const QRegion region = widget->mask()
+ & rect.translated(-widget->geometry().topLeft());
+ newSize = region.boundingRect().size();
+ }
+#endif
+
+ return newSize;
+}
+
+#if defined(QVG_VGIMAGE_BACKBUFFERS)
+
+QVGEGLWindowSurfaceVGImage::QVGEGLWindowSurfaceVGImage(QWindowSurface *win)
+ : QVGEGLWindowSurfacePrivate(win)
+ , context(0)
+ , backBuffer(VG_INVALID_HANDLE)
+ , backBufferSurface(EGL_NO_SURFACE)
+ , recreateBackBuffer(false)
+ , isPaintingActive(false)
+ , windowSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGEGLWindowSurfaceVGImage::~QVGEGLWindowSurfaceVGImage()
+{
+ destroyPaintEngine();
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ // We need a current context to be able to destroy the image.
+ // We use the shared surface because the native window handle
+ // associated with "windowSurface" may have been destroyed already.
+ qt_vg_make_current(context, qt_vg_shared_surface());
+ qt_vg_destroy_surface(context, backBufferSurface);
+ vgDestroyImage(backBuffer);
+ qt_vg_done_current(context, true);
+ }
+ if (windowSurface != EGL_NO_SURFACE)
+ qt_vg_destroy_surface(context, windowSurface);
+ qt_vg_destroy_context(context);
+ }
+}
+
+QEglContext *QVGEGLWindowSurfaceVGImage::ensureContext(QWidget *widget)
+{
+ QSize newSize = windowSurfaceSize(widget);
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate
+ // the back buffer. Keep the same context and paint engine.
+ size = newSize;
+ if (isPaintingActive)
+ qt_vg_done_current(context, true);
+ isPaintingActive = false;
+ recreateBackBuffer = true;
+ }
+ if (!context) {
+ // Create a new EGL context. We create the surface in beginPaint().
+ size = newSize;
+ context = qt_vg_create_context(widget);
+ if (!context)
+ return 0;
+ isPaintingActive = false;
+ }
+ return context;
+}
+
+void QVGEGLWindowSurfaceVGImage::beginPaint(QWidget *widget)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (recreateBackBuffer || backBufferSurface == EGL_NO_SURFACE) {
+ // Create a VGImage object to act as the back buffer
+ // for this window. We have to create the VGImage with a
+ // current context, so activate the main surface for the window.
+ qt_vg_make_current(context, mainSurface());
+ recreateBackBuffer = false;
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(context->display(), backBufferSurface);
+ backBufferSurface = EGL_NO_SURFACE;
+ }
+ if (backBuffer != VG_INVALID_HANDLE) {
+ vgDestroyImage(backBuffer);
+ }
+ VGImageFormat format = qt_vg_config_to_vg_format(context);
+ backBuffer = vgCreateImage
+ (format, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (backBuffer != VG_INVALID_HANDLE) {
+ // Create an EGL surface for rendering into the VGImage.
+ backBufferSurface = eglCreatePbufferFromClientBuffer
+ (context->display(), EGL_OPENVG_IMAGE,
+ (EGLClientBuffer)(backBuffer),
+ context->config(), NULL);
+ if (backBufferSurface == EGL_NO_SURFACE) {
+ vgDestroyImage(backBuffer);
+ backBuffer = VG_INVALID_HANDLE;
+ }
+ }
+ }
+ if (backBufferSurface != EGL_NO_SURFACE)
+ qt_vg_make_current(context, backBufferSurface);
+ else
+ qt_vg_make_current(context, mainSurface());
+ isPaintingActive = true;
+ }
+}
+
+void QVGEGLWindowSurfaceVGImage::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(image);
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ if (isPaintingActive)
+ vgFlush();
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+VGImage QVGEGLWindowSurfaceVGImage::surfaceImage() const
+{
+ return backBuffer;
+}
+
+EGLSurface QVGEGLWindowSurfaceVGImage::mainSurface() const
+{
+ if (windowSurface != EGL_NO_SURFACE)
+ return windowSurface;
+ else
+ return qt_vg_shared_surface();
+}
+
+QVGEGLWindowSurfaceQImage::QVGEGLWindowSurfaceQImage(QWindowSurface *win)
+ : QVGEGLWindowSurfaceVGImage(win)
+{
+}
+
+QVGEGLWindowSurfaceQImage::~QVGEGLWindowSurfaceQImage()
+{
+}
+
+void QVGEGLWindowSurfaceQImage::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ if (isPaintingActive)
+ vgFlush();
+ qt_vg_make_current(context, mainSurface());
+ QRegion rgn = region.intersected
+ (QRect(0, 0, image->width(), image->height()));
+ if (rgn.numRects() == 1) {
+ copySubImage(image, backBuffer, rgn.boundingRect());
+ } else {
+ QVector<QRect> rects = rgn.rects();
+ for (int index = 0; index < rects.size(); ++index)
+ copySubImage(image, backBuffer, rects[index]);
+ }
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+#endif // QVG_VGIMAGE_BACKBUFFERS
+
+QVGEGLWindowSurfaceDirect::QVGEGLWindowSurfaceDirect(QWindowSurface *win)
+ : QVGEGLWindowSurfacePrivate(win)
+ , context(0)
+ , isPaintingActive(false)
+ , needToSwap(false)
+ , windowSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGEGLWindowSurfaceDirect::~QVGEGLWindowSurfaceDirect()
+{
+}
+
+QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
+{
+ QSize newSize = windowSurfaceSize(widget);
+ QEglProperties surfaceProps;
+
+#if defined(QVG_RECREATE_ON_SIZE_CHANGE)
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate it.
+ // We can keep the same context and paint engine.
+ size = newSize;
+ if (isPaintingActive)
+ qt_vg_done_current(context, true);
+ context->setSurface(windowSurface);
+ context->destroySurface();
+#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
+ if (isPremultipliedContext(context)) {
+ surfaceProps.setValue
+ (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
+ } else {
+ surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
+ }
+#endif
+ context->createSurface(widget, &surfaceProps);
+ windowSurface = context->surface();
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+#else
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate
+ // the EGL context for the widget. We also need to recreate
+ // the surface's paint engine if context sharing is not
+ // enabled because we cannot reuse the existing paint objects
+ // in the new context.
+ qt_vg_destroy_paint_engine(engine);
+ engine = 0;
+ context->setSurface(windowSurface);
+ context->destroySurface();
+ qt_vg_destroy_context(context);
+ context = 0;
+ windowSurface = EGL_NO_SURFACE;
+ }
+#endif
+#endif
+ if (!context) {
+ // Create a new EGL context and bind it to the widget surface.
+ size = newSize;
+ context = qt_vg_create_context(widget);
+ if (!context)
+ return 0;
+ // We want a direct to window rendering surface if possible.
+#if defined(QVG_DIRECT_TO_WINDOW)
+ surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
+#endif
+#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
+ if (isPremultipliedContext(context)) {
+ surfaceProps.setValue
+ (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
+ } else {
+ surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
+ }
+#endif
+ if (!context->createSurface(widget, &surfaceProps)) {
+ qt_vg_destroy_context(context);
+ context = 0;
+ return 0;
+ }
+ needToSwap = true;
+#if defined(QVG_DIRECT_TO_WINDOW)
+ // Did we get a direct to window rendering surface?
+ EGLint buffer = 0;
+ if (eglQueryContext(context->display(), context->context(),
+ EGL_RENDER_BUFFER, &buffer) &&
+ buffer == EGL_SINGLE_BUFFER) {
+ needToSwap = false;
+ }
+#endif
+#if !defined(QVG_NO_PRESERVED_SWAP)
+ // Try to force the surface back buffer to preserve its contents.
+ if (needToSwap) {
+ eglGetError(); // Clear error state first.
+ eglSurfaceAttrib(context->display(), context->surface(),
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+ if (eglGetError() != EGL_SUCCESS) {
+ qWarning("QVG: could not enable preserved swap");
+ }
+ }
+#endif
+ windowSurface = context->surface();
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+ return context;
+}
+
+void QVGEGLWindowSurfaceDirect::beginPaint(QWidget *widget)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ qt_vg_make_current(context, windowSurface);
+ isPaintingActive = true;
+ }
+}
+
+void QVGEGLWindowSurfaceDirect::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(image);
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (needToSwap) {
+ if (!isPaintingActive)
+ qt_vg_make_current(context, windowSurface);
+ context->swapBuffers();
+ qt_vg_done_current(context);
+ } else if (isPaintingActive) {
+ vgFlush();
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif