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

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

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

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