source: trunk/src/opengl/qgl_x11egl.cpp@ 636

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

trunk: Merged in qt 4.6.1 sources.

File size: 23.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 QtOpenGL 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 "qgl.h"
43#include <private/qt_x11_p.h>
44#include <private/qpixmap_x11_p.h>
45#include <private/qimagepixmapcleanuphooks_p.h>
46#include <private/qgl_p.h>
47#include <private/qpaintengine_opengl_p.h>
48#include "qgl_egl_p.h"
49#include "qcolormap.h"
50#include <QDebug>
51
52
53QT_BEGIN_NAMESPACE
54
55bool QGLFormat::hasOpenGLOverlays()
56{
57 return false;
58}
59
60void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
61{
62 if (device->devType() == QInternal::Image)
63 props.setPixelFormat(static_cast<QImage *>(device)->format());
64}
65
66// Chooses the EGL config and creates the EGL context
67bool QGLContext::chooseContext(const QGLContext* shareContext)
68{
69 Q_D(QGLContext);
70
71 if (!device())
72 return false;
73
74 int devType = device()->devType();
75
76 // Get the display and initialize it.
77 if (d->eglContext == 0) {
78 d->eglContext = new QEglContext();
79 d->eglContext->setApi(QEgl::OpenGL);
80 if (!d->eglContext->openDisplay(device())) {
81 delete d->eglContext;
82 d->eglContext = 0;
83 return false;
84 }
85
86 // Construct the configuration we need for this surface.
87 QEglProperties configProps;
88 qt_egl_set_format(configProps, devType, d->glFormat);
89 qt_egl_add_platform_config(configProps, device());
90 configProps.setRenderableType(QEgl::OpenGL);
91
92#if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
93 if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
94 qDebug("Setting EGL_BUFFER_SIZE to 16");
95 configProps.setValue(EGL_BUFFER_SIZE, 16);
96 configProps.setValue(EGL_ALPHA_SIZE, 0);
97 }
98
99 if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
100 delete d->eglContext;
101 d->eglContext = 0;
102 return false;
103 }
104#else
105 QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
106 if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
107 configProps.setValue(EGL_RED_SIZE, 5);
108 configProps.setValue(EGL_GREEN_SIZE, 6);
109 configProps.setValue(EGL_BLUE_SIZE, 5);
110 configProps.setValue(EGL_ALPHA_SIZE, 0);
111 matchType = QEgl::ExactPixelFormat;
112 }
113
114 // Search for a matching configuration, reducing the complexity
115 // each time until we get something that matches.
116 if (!d->eglContext->chooseConfig(configProps, matchType)) {
117 delete d->eglContext;
118 d->eglContext = 0;
119 return false;
120 }
121#endif
122
123// qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
124// qDebug() << QEglProperties(d->eglContext->config()).toString();
125
126 // Create a new context for the configuration.
127 if (!d->eglContext->createContext
128 (shareContext ? shareContext->d_func()->eglContext : 0)) {
129 delete d->eglContext;
130 d->eglContext = 0;
131 return false;
132 }
133 d->sharing = d->eglContext->isSharing();
134 if (d->sharing && shareContext)
135 const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
136
137#if defined(EGL_VERSION_1_1)
138 if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
139 eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
140#endif
141 }
142
143 // Inform the higher layers about the actual format properties.
144 qt_egl_update_format(*(d->eglContext), d->glFormat);
145
146 return true;
147}
148
149void QGLWidget::resizeEvent(QResizeEvent *)
150{
151 Q_D(QGLWidget);
152 if (!isValid())
153 return;
154 makeCurrent();
155 if (!d->glcx->initialized())
156 glInit();
157 resizeGL(width(), height());
158 //handle overlay
159}
160
161const QGLContext* QGLWidget::overlayContext() const
162{
163 return 0;
164}
165
166void QGLWidget::makeOverlayCurrent()
167{
168 //handle overlay
169}
170
171void QGLWidget::updateOverlayGL()
172{
173 //handle overlay
174}
175
176//#define QT_DEBUG_X11_VISUAL_SELECTION 1
177
178bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
179{
180 bool foundVisualIsArgb = useArgbVisual;
181
182#ifdef QT_DEBUG_X11_VISUAL_SELECTION
183 qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
184#endif
185
186 memset(&vi, 0, sizeof(XVisualInfo));
187
188 EGLint eglConfigColorSize;
189 eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
190
191 // Check to see if EGL is suggesting an appropriate visual id:
192 EGLint nativeVisualId;
193 eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
194 vi.visualid = nativeVisualId;
195
196 if (vi.visualid) {
197 // EGL has suggested a visual id, so get the rest of the visual info for that id:
198 XVisualInfo *chosenVisualInfo;
199 int matchingCount = 0;
200 chosenVisualInfo = XGetVisualInfo(x11Info.display(), VisualIDMask, &vi, &matchingCount);
201 if (chosenVisualInfo) {
202#if !defined(QT_NO_XRENDER)
203 if (useArgbVisual) {
204 // Check to make sure the visual provided by EGL is ARGB
205 XRenderPictFormat *format;
206 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
207 if (format->type == PictTypeDirect && format->direct.alphaMask) {
208#ifdef QT_DEBUG_X11_VISUAL_SELECTION
209 qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
210#endif
211 foundVisualIsArgb = true;
212 vi = *chosenVisualInfo;
213 }
214 else {
215 qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
216 nativeVisualId, (int)config);
217 vi.visualid = 0;
218 }
219 } else
220#endif
221 {
222 if (eglConfigColorSize == chosenVisualInfo->depth) {
223#ifdef QT_DEBUG_X11_VISUAL_SELECTION
224 qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
225#endif
226 vi = *chosenVisualInfo;
227 } else
228 qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
229 nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
230 }
231 XFree(chosenVisualInfo);
232 }
233 else {
234 qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
235 nativeVisualId, (int)config);
236 vi.visualid = 0;
237 }
238 }
239
240 // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
241 // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
242
243#if !defined(QT_NO_XRENDER)
244 if (vi.visualid == 0 && useArgbVisual) {
245 // Try to use XRender to find an ARGB visual we can use
246 vi.screen = x11Info.screen();
247 vi.depth = 32; //### We might at some point (soon) get ARGB4444
248 vi.c_class = TrueColor;
249 XVisualInfo *matchingVisuals;
250 int matchingCount = 0;
251 matchingVisuals = XGetVisualInfo(x11Info.display(),
252 VisualScreenMask|VisualDepthMask|VisualClassMask,
253 &vi, &matchingCount);
254
255 for (int i = 0; i < matchingCount; ++i) {
256 XRenderPictFormat *format;
257 format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
258 if (format->type == PictTypeDirect && format->direct.alphaMask) {
259 vi = matchingVisuals[i];
260 foundVisualIsArgb = true;
261#ifdef QT_DEBUG_X11_VISUAL_SELECTION
262 qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
263#endif
264 break;
265 }
266 }
267 XFree(matchingVisuals);
268 }
269#endif
270
271 if (vi.visualid == 0) {
272 EGLint depth;
273 eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &depth);
274 int err;
275 err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
276 if (err == 0) {
277 qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!",
278 (int)config, depth);
279 depth = x11Info.depth();
280 err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
281 if (err == 0) {
282 qWarning("Error: Couldn't get any matching X visual!");
283 return false;
284 } else
285 qWarning(" - Falling back to X11 suggested depth (%d)", depth);
286 }
287#ifdef QT_DEBUG_X11_VISUAL_SELECTION
288 else
289 qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
290#endif
291
292 // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
293 if (useArgbVisual)
294 foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
295 }
296
297#ifdef QT_DEBUG_X11_VISUAL_SELECTION
298 qDebug("Visual Info:");
299 qDebug(" bits_per_rgb=%d", vi.bits_per_rgb);
300 qDebug(" red_mask=0x%x", vi.red_mask);
301 qDebug(" green_mask=0x%x", vi.green_mask);
302 qDebug(" blue_mask=0x%x", vi.blue_mask);
303 qDebug(" colormap_size=%d", vi.colormap_size);
304 qDebug(" c_class=%d", vi.c_class);
305 qDebug(" depth=%d", vi.depth);
306 qDebug(" screen=%d", vi.screen);
307 qDebug(" visualid=%d", vi.visualid);
308#endif
309 return foundVisualIsArgb;
310}
311
312void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
313{
314 Q_D(QGLWidget);
315 if (context == 0) {
316 qWarning("QGLWidget::setContext: Cannot set null context");
317 return;
318 }
319 if (!context->deviceIsPixmap() && context->device() != this) {
320 qWarning("QGLWidget::setContext: Context must refer to this widget");
321 return;
322 }
323
324 if (d->glcx)
325 d->glcx->doneCurrent();
326 QGLContext* oldcx = d->glcx;
327 d->glcx = context;
328
329 if (parentWidget()) {
330 // force creation of delay-created widgets
331 parentWidget()->winId();
332 if (parentWidget()->x11Info().screen() != x11Info().screen())
333 d_func()->xinfo = parentWidget()->d_func()->xinfo;
334 }
335
336 // If the application has set WA_TranslucentBackground and not explicitly set
337 // the alpha buffer size to zero, modify the format so it have an alpha channel
338 QGLFormat& fmt = d->glcx->d_func()->glFormat;
339 const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
340 if (tryArgbVisual && fmt.alphaBufferSize() == -1)
341 fmt.setAlphaBufferSize(1);
342
343 bool createFailed = false;
344 if (!d->glcx->isValid()) {
345 // Create the QGLContext here, which in turn chooses the EGL config
346 // and creates the EGL context:
347 if (!d->glcx->create(shareContext ? shareContext : oldcx))
348 createFailed = true;
349 }
350 if (createFailed) {
351 if (deleteOldContext)
352 delete oldcx;
353 return;
354 }
355
356 if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
357 if (deleteOldContext)
358 delete oldcx;
359 return;
360 }
361
362 bool visible = isVisible();
363 if (visible)
364 hide();
365
366 XVisualInfo vi;
367 QEglContext *eglContext = d->glcx->d_func()->eglContext;
368 bool usingArgbVisual = qt_egl_setup_x11_visual(vi, eglContext->display(), eglContext->config(),
369 x11Info(), tryArgbVisual);
370
371 XSetWindowAttributes a;
372
373 Window p = RootWindow(x11Info().display(), x11Info().screen());
374 if (parentWidget())
375 p = parentWidget()->winId();
376
377 QColormap colmap = QColormap::instance(vi.screen);
378 a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
379 a.border_pixel = colmap.pixel(Qt::black);
380
381 unsigned int valueMask = CWBackPixel|CWBorderPixel;
382 if (usingArgbVisual) {
383 a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone);
384 valueMask |= CWColormap;
385 }
386
387 Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(),
388 0, vi.depth, InputOutput, vi.visual, valueMask, &a);
389
390 if (deleteOldContext)
391 delete oldcx;
392 oldcx = 0;
393
394 create(w); // Create with the ID of the window we've just created
395
396
397 // Create the EGL surface to draw into.
398 QGLContextPrivate *ctxpriv = d->glcx->d_func();
399 ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(this);
400 if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
401 delete ctxpriv->eglContext;
402 ctxpriv->eglContext = 0;
403 return;
404 }
405
406 d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
407
408 if (visible)
409 show();
410
411 XFlush(X11->display);
412 d->glcx->setWindowCreated(true);
413}
414
415void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget)
416{
417 Q_Q(QGLWidget);
418
419 initContext(context, shareWidget);
420
421 if(q->isValid() && glcx->format().hasOverlay()) {
422 //no overlay
423 qWarning("QtOpenGL ES doesn't currently support overlays");
424 }
425}
426
427void QGLWidgetPrivate::cleanupColormaps()
428{
429}
430
431const QGLColormap & QGLWidget::colormap() const
432{
433 return d_func()->cmap;
434}
435
436void QGLWidget::setColormap(const QGLColormap &)
437{
438}
439
440void QGLExtensions::init()
441{
442 static bool init_done = false;
443
444 if (init_done)
445 return;
446 init_done = true;
447
448 // We need a context current to initialize the extensions.
449 QGLWidget tmpWidget;
450 tmpWidget.makeCurrent();
451
452 init_extensions();
453
454 tmpWidget.doneCurrent();
455}
456
457// Re-creates the EGL surface if the window ID has changed or if force is true
458void QGLWidgetPrivate::recreateEglSurface(bool force)
459{
460 Q_Q(QGLWidget);
461
462 Window currentId = q->winId();
463
464 if ( force || (currentId != eglSurfaceWindowId) ) {
465 // The window id has changed so we need to re-create the EGL surface
466 QEglContext *ctx = glcx->d_func()->eglContext;
467 EGLSurface surface = glcx->d_func()->eglSurface;
468 if (surface != EGL_NO_SURFACE)
469 ctx->destroySurface(surface); // Will force doneCurrent() if nec.
470 surface = ctx->createSurface(q);
471 if (surface == EGL_NO_SURFACE)
472 qWarning("Error creating EGL window surface: 0x%x", eglGetError());
473 glcx->d_func()->eglSurface = surface;
474
475 eglSurfaceWindowId = currentId;
476 }
477}
478
479// Selects which configs should be used
480EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly)
481{
482 // Cache the configs we select as they wont change:
483 static EGLConfig roPixmapRGBConfig = 0;
484 static EGLConfig roPixmapRGBAConfig = 0;
485 static EGLConfig rwPixmapRGBConfig = 0;
486 static EGLConfig rwPixmapRGBAConfig = 0;
487
488 EGLConfig* targetConfig;
489
490 if (hasAlpha) {
491 if (readOnly)
492 targetConfig = &roPixmapRGBAConfig;
493 else
494 targetConfig = &rwPixmapRGBAConfig;
495 }
496 else {
497 if (readOnly)
498 targetConfig = &roPixmapRGBConfig;
499 else
500 targetConfig = &rwPixmapRGBConfig;
501 }
502
503 if (*targetConfig == 0) {
504 QEglProperties configAttribs;
505 configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
506 configAttribs.setRenderableType(QEgl::OpenGL);
507 if (hasAlpha)
508 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
509 else
510 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
511
512 // If this is going to be a render target, it needs to have a depth, stencil & sample buffer
513 if (!readOnly) {
514 configAttribs.setValue(EGL_DEPTH_SIZE, 1);
515 configAttribs.setValue(EGL_STENCIL_SIZE, 1);
516 configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
517 }
518
519 EGLint configCount = 0;
520 do {
521 eglChooseConfig(QEglContext::defaultDisplay(0), configAttribs.properties(), targetConfig, 1, &configCount);
522 if (configCount > 0) {
523 // Got one
524 qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
525 << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
526
527// QEglProperties configProps(*targetConfig);
528// qDebug() << configProps.toString();
529 break;
530 }
531 qWarning("choosePixmapConfig() - No suitible config found, reducing requirements");
532 } while (configAttribs.reduceConfiguration());
533 }
534
535 if (*targetConfig == 0)
536 qWarning("choosePixmapConfig() - Couldn't find a suitable config");
537
538 return *targetConfig;
539}
540
541bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly)
542{
543 Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
544 QX11PixmapData* pixmapData = static_cast<QX11PixmapData*>(pmd);
545
546 bool hasAlpha = pixmapData->hasAlphaChannel();
547
548 EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly);
549
550 QEglProperties pixmapAttribs;
551
552 // If the pixmap can't be bound to a texture, it's pretty useless
553 pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
554 if (hasAlpha)
555 pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
556 else
557 pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
558
559 EGLSurface pixmapSurface;
560 pixmapSurface = eglCreatePixmapSurface(QEglContext::defaultDisplay(0),
561 pixmapConfig,
562 (EGLNativePixmapType) pixmapData->handle(),
563 pixmapAttribs.properties());
564// qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
565// pixmapSurface, pixmapData->handle());
566 if (pixmapSurface == EGL_NO_SURFACE) {
567 qWarning() << "Failed to create a pixmap surface using config" << (int)pixmapConfig
568 << ":" << QEglContext::errorString(eglGetError());
569 return false;
570 }
571
572 static bool doneOnce = false;
573 if (!doneOnce) {
574 // Make sure QGLTextureCache is instanciated so it can install cleanup hooks
575 // which cleanup the EGL surface.
576 QGLTextureCache::instance();
577 doneOnce = true;
578 }
579
580 Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
581 pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
582 QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
583
584 return true;
585}
586
587
588QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key,
589 QGLContext::BindOptions options)
590{
591 Q_Q(QGLContext);
592
593 // The EGL texture_from_pixmap has no facility to invert the y coordinate
594 if (!(options & QGLContext::CanFlipNativePixmapBindOption))
595 return 0;
596
597 Q_ASSERT(pd->classId() == QPixmapData::X11Class);
598
599 static bool checkedForTFP = false;
600 static bool haveTFP = false;
601
602 if (!checkedForTFP) {
603 // Check for texture_from_pixmap egl extension
604 checkedForTFP = true;
605 if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
606 eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
607 {
608 qDebug("Found texture_from_pixmap EGL extension!");
609 haveTFP = true;
610 }
611 }
612
613 if (!haveTFP)
614 return 0;
615
616 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
617
618 bool hasAlpha = pixmapData->hasAlphaChannel();
619
620 // Check to see if the surface is still valid
621 if (pixmapData->gl_surface &&
622 hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
623 {
624 // Surface is invalid!
625 destroyGlSurfaceForPixmap(pixmapData);
626 }
627
628 if (pixmapData->gl_surface == 0) {
629 bool success = qt_createEGLSurfaceForPixmap(pixmapData, true);
630 if (!success) {
631 haveTFP = false;
632 return 0;
633 }
634 }
635
636 Q_ASSERT(pixmapData->gl_surface);
637
638 GLuint textureId;
639 glGenTextures(1, &textureId);
640 glBindTexture(GL_TEXTURE_2D, textureId);
641
642 // bind the egl pixmap surface to a texture
643 EGLBoolean success;
644 success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
645 if (success == EGL_FALSE) {
646 qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
647 eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface);
648 pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
649 haveTFP = false;
650 return 0;
651 }
652
653 QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
654 pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
655
656 // We assume the cost of bound pixmaps is zero
657 QGLTextureCache::instance()->insert(q, key, texture, 0);
658
659 glBindTexture(GL_TEXTURE_2D, textureId);
660 return texture;
661}
662
663void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
664{
665 Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
666 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
667 if (pixmapData->gl_surface) {
668 EGLBoolean success;
669 success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
670 if (success == EGL_FALSE) {
671 qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
672 << QEglContext::errorString(eglGetError());
673 }
674 pixmapData->gl_surface = 0;
675 }
676}
677
678void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
679{
680 Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
681 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
682 if (pixmapData->gl_surface) {
683 EGLBoolean success;
684 success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
685 (EGLSurface)pixmapData->gl_surface,
686 EGL_BACK_BUFFER);
687 if (success == EGL_FALSE) {
688 qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
689 << QEglContext::errorString(eglGetError());
690 }
691 }
692}
693
694QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.