source: trunk/src/openvg/qwindowsurface_vgegl.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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