source: trunk/src/openvg/qwindowsurface_vgegl.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 22.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenVG module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwindowsurface_vgegl_p.h"
43#include "qpaintengine_vg_p.h"
44#include "qpixmapdata_vg_p.h"
45#include "qvgimagepool_p.h"
46#include "qvg_p.h"
47
48#if !defined(QT_NO_EGL)
49
50QT_BEGIN_NAMESPACE
51
52// Turn off "direct to window" rendering if EGL cannot support it.
53#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER)
54#if defined(QVG_DIRECT_TO_WINDOW)
55#undef QVG_DIRECT_TO_WINDOW
56#endif
57#endif
58
59// Determine if preserved window contents should be used.
60#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED)
61#if !defined(QVG_NO_PRESERVED_SWAP)
62#define QVG_NO_PRESERVED_SWAP 1
63#endif
64#endif
65
66VGImageFormat qt_vg_config_to_vg_format(QEglContext *context)
67{
68 return qt_vg_image_to_vg_format
69 (qt_vg_config_to_image_format(context));
70}
71
72QImage::Format qt_vg_config_to_image_format(QEglContext *context)
73{
74 EGLint red = 0;
75 EGLint green = 0;
76 EGLint blue = 0;
77 EGLint alpha = 0;
78 context->configAttrib(EGL_RED_SIZE, &red);
79 context->configAttrib(EGL_GREEN_SIZE, &green);
80 context->configAttrib(EGL_BLUE_SIZE, &blue);
81 context->configAttrib(EGL_ALPHA_SIZE, &alpha);
82 QImage::Format argbFormat;
83#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
84 EGLint type = 0;
85 context->configAttrib(EGL_SURFACE_TYPE, &type);
86 if ((type & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0)
87 argbFormat = QImage::Format_ARGB32_Premultiplied;
88 else
89 argbFormat = QImage::Format_ARGB32;
90#else
91 argbFormat = QImage::Format_ARGB32;
92#endif
93 if (red == 8 && green == 8 && blue == 8 && alpha == 8)
94 return argbFormat;
95 else if (red == 8 && green == 8 && blue == 8 && alpha == 0)
96 return QImage::Format_RGB32;
97 else if (red == 5 && green == 6 && blue == 5 && alpha == 0)
98 return QImage::Format_RGB16;
99 else if (red == 4 && green == 4 && blue == 4 && alpha == 4)
100 return QImage::Format_ARGB4444_Premultiplied;
101 else
102 return argbFormat; // XXX
103}
104
105#if !defined(QVG_NO_SINGLE_CONTEXT)
106
107class QVGSharedContext
108{
109public:
110 QVGSharedContext();
111 ~QVGSharedContext();
112
113 QEglContext *context;
114 int refCount;
115 int widgetRefCount;
116 QVGPaintEngine *engine;
117 EGLSurface surface;
118 QVGPixmapData *firstPixmap;
119};
120
121QVGSharedContext::QVGSharedContext()
122 : context(0)
123 , refCount(0)
124 , widgetRefCount(0)
125 , engine(0)
126 , surface(EGL_NO_SURFACE)
127 , firstPixmap(0)
128{
129}
130
131QVGSharedContext::~QVGSharedContext()
132{
133 // Don't accidentally destroy the QEglContext if the reference
134 // count falls to zero while deleting the paint engine.
135 ++refCount;
136
137 if (context)
138 context->makeCurrent(qt_vg_shared_surface());
139 delete engine;
140 if (context)
141 context->doneCurrent();
142 if (context && surface != EGL_NO_SURFACE)
143 context->destroySurface(surface);
144 delete context;
145}
146
147Q_GLOBAL_STATIC(QVGSharedContext, sharedContext);
148
149QVGPaintEngine *qt_vg_create_paint_engine(void)
150{
151 QVGSharedContext *shared = sharedContext();
152 if (!shared->engine)
153 shared->engine = new QVGPaintEngine();
154 return shared->engine;
155}
156
157void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
158{
159 Q_UNUSED(engine);
160}
161
162void qt_vg_register_pixmap(QVGPixmapData *pd)
163{
164 QVGSharedContext *shared = sharedContext();
165 pd->next = shared->firstPixmap;
166 pd->prev = 0;
167 if (shared->firstPixmap)
168 shared->firstPixmap->prev = pd;
169 shared->firstPixmap = pd;
170}
171
172void qt_vg_unregister_pixmap(QVGPixmapData *pd)
173{
174 if (pd->next)
175 pd->next->prev = pd->prev;
176 if (pd->prev) {
177 pd->prev->next = pd->next;
178 } else {
179 QVGSharedContext *shared = sharedContext();
180 shared->firstPixmap = pd->next;
181 }
182}
183
184#else
185
186QVGPaintEngine *qt_vg_create_paint_engine(void)
187{
188 return new QVGPaintEngine();
189}
190
191void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
192{
193 delete engine;
194}
195
196void qt_vg_register_pixmap(QVGPixmapData *pd)
197{
198 Q_UNUSED(pd);
199}
200
201void qt_vg_unregister_pixmap(QVGPixmapData *pd)
202{
203 Q_UNUSED(pd);
204}
205
206#endif
207
208#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
209
210static bool isPremultipliedContext(const QEglContext *context)
211{
212 EGLint value = 0;
213 if (context->configAttrib(EGL_SURFACE_TYPE, &value))
214 return (value & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0;
215 else
216 return false;
217}
218
219#endif
220
221static QEglContext *createContext(QPaintDevice *device)
222{
223 QEglContext *context;
224
225 // Create the context object and open the display.
226 context = new QEglContext();
227 context->setApi(QEgl::OpenVG);
228 if (!context->openDisplay(device)) {
229 delete context;
230 return 0;
231 }
232
233 // Set the swap interval for the display.
234 QByteArray interval = qgetenv("QT_VG_SWAP_INTERVAL");
235 if (!interval.isEmpty())
236 eglSwapInterval(context->display(), interval.toInt());
237 else
238 eglSwapInterval(context->display(), 1);
239
240#ifdef EGL_RENDERABLE_TYPE
241 // Has the user specified an explicit EGL configuration to use?
242 QByteArray configId = qgetenv("QT_VG_EGL_CONFIG");
243 if (!configId.isEmpty()) {
244 EGLint cfgId = configId.toInt();
245 EGLint properties[] = {
246 EGL_CONFIG_ID, cfgId,
247 EGL_NONE
248 };
249 EGLint matching = 0;
250 EGLConfig cfg;
251 if (eglChooseConfig
252 (context->display(), properties, &cfg, 1, &matching) &&
253 matching > 0) {
254 // Check that the selected configuration actually supports OpenVG
255 // and then create the context with it.
256 EGLint id = 0;
257 EGLint type = 0;
258 eglGetConfigAttrib
259 (context->display(), cfg, EGL_CONFIG_ID, &id);
260 eglGetConfigAttrib
261 (context->display(), cfg, EGL_RENDERABLE_TYPE, &type);
262 if (cfgId == id && (type & EGL_OPENVG_BIT) != 0) {
263 context->setConfig(cfg);
264 if (!context->createContext()) {
265 delete context;
266 return 0;
267 }
268 return context;
269 } else {
270 qWarning("QT_VG_EGL_CONFIG: %d is not a valid OpenVG configuration", int(cfgId));
271 }
272 }
273 }
274#endif
275
276 // Choose an appropriate configuration for rendering into the device.
277 QEglProperties configProps;
278 configProps.setPaintDeviceFormat(device);
279 int redSize = configProps.value(EGL_RED_SIZE);
280 if (redSize == EGL_DONT_CARE || redSize == 0)
281 configProps.setPixelFormat(QImage::Format_ARGB32); // XXX
282#ifndef QVG_SCISSOR_CLIP
283 // If we are using the mask to clip, then explicitly request a mask.
284 configProps.setValue(EGL_ALPHA_MASK_SIZE, 1);
285#endif
286#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
287 configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
288 EGL_VG_ALPHA_FORMAT_PRE_BIT);
289 configProps.setRenderableType(QEgl::OpenVG);
290 if (!context->chooseConfig(configProps)) {
291 // Try again without the "pre" bit.
292 configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
293 if (!context->chooseConfig(configProps)) {
294 delete context;
295 return 0;
296 }
297 }
298#else
299 configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
300 configProps.setRenderableType(QEgl::OpenVG);
301 if (!context->chooseConfig(configProps)) {
302 delete context;
303 return 0;
304 }
305#endif
306
307 // Construct a new EGL context for the selected configuration.
308 if (!context->createContext()) {
309 delete context;
310 return 0;
311 }
312
313 return context;
314}
315
316#if !defined(QVG_NO_SINGLE_CONTEXT)
317
318QEglContext *qt_vg_create_context(QPaintDevice *device, int devType)
319{
320 QVGSharedContext *shared = sharedContext();
321 if (devType == QInternal::Widget)
322 ++(shared->widgetRefCount);
323 if (shared->context) {
324 ++(shared->refCount);
325 return shared->context;
326 } else {
327 shared->context = createContext(device);
328 shared->refCount = 1;
329 return shared->context;
330 }
331}
332
333static void qt_vg_destroy_shared_context(QVGSharedContext *shared)
334{
335 shared->context->makeCurrent(qt_vg_shared_surface());
336 delete shared->engine;
337 shared->engine = 0;
338 shared->context->doneCurrent();
339 if (shared->surface != EGL_NO_SURFACE) {
340 eglDestroySurface(shared->context->display(), shared->surface);
341 shared->surface = EGL_NO_SURFACE;
342 }
343 delete shared->context;
344 shared->context = 0;
345}
346
347void qt_vg_hibernate_pixmaps(QVGSharedContext *shared)
348{
349 // Artificially increase the reference count to prevent the
350 // context from being destroyed until after we have finished
351 // the hibernation process.
352 ++(shared->refCount);
353
354 // We need a context current to hibernate the VGImage objects.
355 shared->context->makeCurrent(qt_vg_shared_surface());
356
357 // Scan all QVGPixmapData objects in the system and hibernate them.
358 QVGPixmapData *pd = shared->firstPixmap;
359 while (pd != 0) {
360 pd->hibernate();
361 pd = pd->next;
362 }
363
364 // Hibernate any remaining VGImage's in the image pool.
365 QVGImagePool::instance()->hibernate();
366
367 // Don't need the current context any more.
368 shared->context->lazyDoneCurrent();
369
370 // Decrease the reference count and destroy the context if necessary.
371 if (--(shared->refCount) <= 0)
372 qt_vg_destroy_shared_context(shared);
373}
374
375void qt_vg_destroy_context(QEglContext *context, int devType)
376{
377 QVGSharedContext *shared = sharedContext();
378 if (shared->context != context) {
379 // This is not the shared context. Shouldn't happen!
380 delete context;
381 return;
382 }
383 if (devType == QInternal::Widget)
384 --(shared->widgetRefCount);
385 if (--(shared->refCount) <= 0) {
386 qt_vg_destroy_shared_context(shared);
387 } else if (shared->widgetRefCount <= 0 && devType == QInternal::Widget) {
388 // All of the widget window surfaces have been destroyed
389 // but we still have VG pixmaps active. Ask them to hibernate
390 // to free up GPU resources until a widget is shown again.
391 // This may eventually cause the EGLContext to be destroyed
392 // because nothing in the system needs a context, which will
393 // free up even more GPU resources.
394 qt_vg_hibernate_pixmaps(shared);
395 }
396}
397
398EGLSurface qt_vg_shared_surface(void)
399{
400 QVGSharedContext *shared = sharedContext();
401 if (shared->surface == EGL_NO_SURFACE) {
402 EGLint attribs[7];
403 attribs[0] = EGL_WIDTH;
404 attribs[1] = 16;
405 attribs[2] = EGL_HEIGHT;
406 attribs[3] = 16;
407#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
408 if (isPremultipliedContext(shared->context)) {
409 attribs[4] = EGL_VG_ALPHA_FORMAT;
410 attribs[5] = EGL_VG_ALPHA_FORMAT_PRE;
411 attribs[6] = EGL_NONE;
412 } else
413#endif
414 {
415 attribs[4] = EGL_NONE;
416 }
417 shared->surface = eglCreatePbufferSurface
418 (shared->context->display(), shared->context->config(), attribs);
419 }
420 return shared->surface;
421}
422
423#else
424
425QEglContext *qt_vg_create_context(QPaintDevice *device, int devType)
426{
427 Q_UNUSED(devType);
428 return createContext(device);
429}
430
431void qt_vg_destroy_context(QEglContext *context, int devType)
432{
433 Q_UNUSED(devType);
434 delete context;
435}
436
437EGLSurface qt_vg_shared_surface(void)
438{
439 return EGL_NO_SURFACE;
440}
441
442#endif
443
444QVGEGLWindowSurfacePrivate::QVGEGLWindowSurfacePrivate(QWindowSurface *win)
445{
446 winSurface = win;
447 engine = 0;
448}
449
450QVGEGLWindowSurfacePrivate::~QVGEGLWindowSurfacePrivate()
451{
452 // Destroy the paint engine if it hasn't been destroyed already.
453 destroyPaintEngine();
454}
455
456QVGPaintEngine *QVGEGLWindowSurfacePrivate::paintEngine()
457{
458 if (!engine)
459 engine = qt_vg_create_paint_engine();
460 return engine;
461}
462
463VGImage QVGEGLWindowSurfacePrivate::surfaceImage() const
464{
465 return VG_INVALID_HANDLE;
466}
467
468void QVGEGLWindowSurfacePrivate::destroyPaintEngine()
469{
470 if (engine) {
471 qt_vg_destroy_paint_engine(engine);
472 engine = 0;
473 }
474}
475
476QSize QVGEGLWindowSurfacePrivate::windowSurfaceSize(QWidget *widget) const
477{
478 Q_UNUSED(widget);
479
480 QRect rect = winSurface->geometry();
481 QSize newSize = rect.size();
482
483#if defined(Q_WS_QWS)
484 // Account for the widget mask, if any.
485 if (widget && !widget->mask().isEmpty()) {
486 const QRegion region = widget->mask()
487 & rect.translated(-widget->geometry().topLeft());
488 newSize = region.boundingRect().size();
489 }
490#endif
491
492 return newSize;
493}
494
495#if defined(QVG_VGIMAGE_BACKBUFFERS)
496
497QVGEGLWindowSurfaceVGImage::QVGEGLWindowSurfaceVGImage(QWindowSurface *win)
498 : QVGEGLWindowSurfacePrivate(win)
499 , context(0)
500 , backBuffer(VG_INVALID_HANDLE)
501 , backBufferSurface(EGL_NO_SURFACE)
502 , recreateBackBuffer(false)
503 , isPaintingActive(false)
504 , windowSurface(EGL_NO_SURFACE)
505{
506}
507
508QVGEGLWindowSurfaceVGImage::~QVGEGLWindowSurfaceVGImage()
509{
510 destroyPaintEngine();
511 if (context) {
512 if (backBufferSurface != EGL_NO_SURFACE) {
513 // We need a current context to be able to destroy the image.
514 // We use the shared surface because the native window handle
515 // associated with "windowSurface" may have been destroyed already.
516 context->makeCurrent(qt_vg_shared_surface());
517 context->destroySurface(backBufferSurface);
518 vgDestroyImage(backBuffer);
519 context->doneCurrent();
520 }
521 if (windowSurface != EGL_NO_SURFACE)
522 context->destroySurface(windowSurface);
523 qt_vg_destroy_context(context, QInternal::Widget);
524 }
525}
526
527QEglContext *QVGEGLWindowSurfaceVGImage::ensureContext(QWidget *widget)
528{
529 QSize newSize = windowSurfaceSize(widget);
530 if (context && size != newSize) {
531 // The surface size has changed, so we need to recreate
532 // the back buffer. Keep the same context and paint engine.
533 size = newSize;
534 if (isPaintingActive)
535 context->doneCurrent();
536 isPaintingActive = false;
537 recreateBackBuffer = true;
538 }
539 if (!context) {
540 // Create a new EGL context. We create the surface in beginPaint().
541 size = newSize;
542 context = qt_vg_create_context(widget, QInternal::Widget);
543 if (!context)
544 return 0;
545 isPaintingActive = false;
546 }
547 return context;
548}
549
550void QVGEGLWindowSurfaceVGImage::beginPaint(QWidget *widget)
551{
552 QEglContext *context = ensureContext(widget);
553 if (context) {
554 if (recreateBackBuffer || backBufferSurface == EGL_NO_SURFACE) {
555 // Create a VGImage object to act as the back buffer
556 // for this window. We have to create the VGImage with a
557 // current context, so activate the main surface for the window.
558 context->makeCurrent(mainSurface());
559 recreateBackBuffer = false;
560 if (backBufferSurface != EGL_NO_SURFACE) {
561 eglDestroySurface(context->display(), backBufferSurface);
562 backBufferSurface = EGL_NO_SURFACE;
563 }
564 if (backBuffer != VG_INVALID_HANDLE) {
565 vgDestroyImage(backBuffer);
566 }
567 VGImageFormat format = qt_vg_config_to_vg_format(context);
568 backBuffer = vgCreateImage
569 (format, size.width(), size.height(),
570 VG_IMAGE_QUALITY_FASTER);
571 if (backBuffer != VG_INVALID_HANDLE) {
572 // Create an EGL surface for rendering into the VGImage.
573 backBufferSurface = eglCreatePbufferFromClientBuffer
574 (context->display(), EGL_OPENVG_IMAGE,
575 (EGLClientBuffer)(backBuffer),
576 context->config(), NULL);
577 if (backBufferSurface == EGL_NO_SURFACE) {
578 vgDestroyImage(backBuffer);
579 backBuffer = VG_INVALID_HANDLE;
580 }
581 }
582 }
583 if (backBufferSurface != EGL_NO_SURFACE)
584 context->makeCurrent(backBufferSurface);
585 else
586 context->makeCurrent(mainSurface());
587 isPaintingActive = true;
588 }
589}
590
591void QVGEGLWindowSurfaceVGImage::endPaint
592 (QWidget *widget, const QRegion& region, QImage *image)
593{
594 Q_UNUSED(region);
595 Q_UNUSED(image);
596 QEglContext *context = ensureContext(widget);
597 if (context) {
598 if (backBufferSurface != EGL_NO_SURFACE) {
599 if (isPaintingActive)
600 vgFlush();
601 context->lazyDoneCurrent();
602 }
603 isPaintingActive = false;
604 }
605}
606
607VGImage QVGEGLWindowSurfaceVGImage::surfaceImage() const
608{
609 return backBuffer;
610}
611
612EGLSurface QVGEGLWindowSurfaceVGImage::mainSurface() const
613{
614 if (windowSurface != EGL_NO_SURFACE)
615 return windowSurface;
616 else
617 return qt_vg_shared_surface();
618}
619
620#endif // QVG_VGIMAGE_BACKBUFFERS
621
622QVGEGLWindowSurfaceDirect::QVGEGLWindowSurfaceDirect(QWindowSurface *win)
623 : QVGEGLWindowSurfacePrivate(win)
624 , context(0)
625 , isPaintingActive(false)
626 , needToSwap(false)
627 , windowSurface(EGL_NO_SURFACE)
628{
629}
630
631QVGEGLWindowSurfaceDirect::~QVGEGLWindowSurfaceDirect()
632{
633 destroyPaintEngine();
634 if (context) {
635 if (windowSurface != EGL_NO_SURFACE)
636 context->destroySurface(windowSurface);
637 qt_vg_destroy_context(context, QInternal::Widget);
638 }
639}
640
641QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
642{
643 QSize newSize = windowSurfaceSize(widget);
644 QEglProperties surfaceProps;
645
646#if defined(QVG_RECREATE_ON_SIZE_CHANGE)
647#if !defined(QVG_NO_SINGLE_CONTEXT)
648 if (context && size != newSize) {
649 // The surface size has changed, so we need to recreate it.
650 // We can keep the same context and paint engine.
651 size = newSize;
652 if (isPaintingActive)
653 context->doneCurrent();
654 context->destroySurface(windowSurface);
655#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
656 if (isPremultipliedContext(context)) {
657 surfaceProps.setValue
658 (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
659 } else {
660 surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
661 }
662#endif
663 windowSurface = context->createSurface(widget, &surfaceProps);
664 isPaintingActive = false;
665 }
666#else
667 if (context && size != newSize) {
668 // The surface size has changed, so we need to recreate
669 // the EGL context for the widget. We also need to recreate
670 // the surface's paint engine if context sharing is not
671 // enabled because we cannot reuse the existing paint objects
672 // in the new context.
673 qt_vg_destroy_paint_engine(engine);
674 engine = 0;
675 context->destroySurface(windowSurface);
676 qt_vg_destroy_context(context, QInternal::Widget);
677 context = 0;
678 windowSurface = EGL_NO_SURFACE;
679 }
680#endif
681#endif
682 if (!context) {
683 // Create a new EGL context and bind it to the widget surface.
684 size = newSize;
685 context = qt_vg_create_context(widget, QInternal::Widget);
686 if (!context)
687 return 0;
688 // We want a direct to window rendering surface if possible.
689#if defined(QVG_DIRECT_TO_WINDOW)
690 surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
691#endif
692#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
693 if (isPremultipliedContext(context)) {
694 surfaceProps.setValue
695 (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
696 } else {
697 surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
698 }
699#endif
700 EGLSurface surface = context->createSurface(widget, &surfaceProps);
701 if (surface == EGL_NO_SURFACE) {
702 qt_vg_destroy_context(context, QInternal::Widget);
703 context = 0;
704 return 0;
705 }
706 needToSwap = true;
707#if defined(QVG_DIRECT_TO_WINDOW)
708 // Did we get a direct to window rendering surface?
709 EGLint buffer = 0;
710 if (eglQueryContext(context->display(), context->context(),
711 EGL_RENDER_BUFFER, &buffer) &&
712 buffer == EGL_SINGLE_BUFFER) {
713 needToSwap = false;
714 }
715#endif
716#if !defined(QVG_NO_PRESERVED_SWAP)
717 // Try to force the surface back buffer to preserve its contents.
718 if (needToSwap) {
719 eglGetError(); // Clear error state first.
720 eglSurfaceAttrib(context->display(), surface,
721 EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
722 if (eglGetError() != EGL_SUCCESS) {
723 qWarning("QVG: could not enable preserved swap");
724 }
725 }
726#endif
727 windowSurface = surface;
728 isPaintingActive = false;
729 }
730 return context;
731}
732
733void QVGEGLWindowSurfaceDirect::beginPaint(QWidget *widget)
734{
735 QEglContext *context = ensureContext(widget);
736 if (context) {
737 context->makeCurrent(windowSurface);
738 isPaintingActive = true;
739 }
740}
741
742void QVGEGLWindowSurfaceDirect::endPaint
743 (QWidget *widget, const QRegion& region, QImage *image)
744{
745 Q_UNUSED(region);
746 Q_UNUSED(image);
747 QEglContext *context = ensureContext(widget);
748 if (context) {
749 if (needToSwap) {
750 if (!isPaintingActive)
751 context->makeCurrent(windowSurface);
752 context->swapBuffers(windowSurface);
753 context->lazyDoneCurrent();
754 } else if (isPaintingActive) {
755 vgFlush();
756 context->lazyDoneCurrent();
757 }
758 isPaintingActive = false;
759 }
760}
761
762QT_END_NAMESPACE
763
764#endif
Note: See TracBrowser for help on using the repository browser.