source: trunk/src/opengl/qwindowsurface_x11gl.cpp@ 1023

Last change on this file since 1023 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: 7.8 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 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 <QTime>
43#include <QDebug>
44
45#include <private/qt_x11_p.h>
46#include <private/qimagepixmapcleanuphooks_p.h>
47
48#include "qwindowsurface_x11gl_p.h"
49#include "qpixmapdata_x11gl_p.h"
50
51QT_BEGIN_NAMESPACE
52
53QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
54 : QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window)
55{
56}
57
58QX11GLWindowSurface::~QX11GLWindowSurface()
59{
60 if (m_windowGC)
61 XFree(m_windowGC);
62 if (m_pixmapGC)
63 XFree(m_pixmapGC);
64}
65
66QPaintDevice *QX11GLWindowSurface::paintDevice()
67{
68 return &m_backBuffer;
69}
70
71extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp
72
73void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
74{
75 // We don't need to know the widget which initiated the flush. Instead we just use the offset
76 // to translate the widgetRegion:
77 Q_UNUSED(widget);
78
79 if (m_backBuffer.isNull()) {
80 qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything");
81 return;
82 }
83
84 Q_ASSERT(window()->size() != m_backBuffer.size());
85
86 // Wait for all GL rendering to the back buffer pixmap to complete before trying to
87 // copy it to the window. We do this by making sure the pixmap's context is current
88 // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
89 // block, just that "All rendering calls...are guaranteed to be executed before native
90 // rendering calls". This makes it potentially less expensive than glFinish.
91 QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
92 if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
93 ctx->makeCurrent();
94 eglWaitClient();
95
96 if (m_windowGC == 0) {
97 XGCValues attribs;
98 attribs.graphics_exposures = False;
99 m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs);
100 }
101
102 int rectCount;
103 XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount);
104 if (rectCount <= 0)
105 return;
106
107 XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
108
109 QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
110 XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
111 dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
112 dirtyRect.x(), dirtyRect.y());
113
114 // Make sure the blit of the update from the back buffer to the window completes
115 // before allowing rendering to start again to the back buffer. Otherwise the GPU
116 // might start rendering to the back buffer again while the blit takes place.
117 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
118}
119
120void QX11GLWindowSurface::setGeometry(const QRect &rect)
121{
122 if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
123 QX11GLPixmapData *pd = new QX11GLPixmapData;
124 QSize newSize = rect.size();
125 pd->resize(newSize.width(), newSize.height());
126 m_backBuffer = QPixmap(pd);
127 if (window()->testAttribute(Qt::WA_TranslucentBackground))
128 m_backBuffer.fill(Qt::transparent);
129 if (m_pixmapGC) {
130 XFreeGC(X11->display, m_pixmapGC);
131 m_pixmapGC = 0;
132 }
133 }
134
135 QWindowSurface::setGeometry(rect);
136}
137
138bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
139{
140 if (m_backBuffer.isNull())
141 return false;
142
143 Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
144
145 // Make sure all GL rendering is complete before starting the scroll operation:
146 QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
147 if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
148 ctx->makeCurrent();
149 eglWaitClient();
150
151 if (!m_pixmapGC)
152 m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
153
154 foreach (const QRect& rect, area.rects()) {
155 XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC,
156 rect.x(), rect.y(), rect.width(), rect.height(),
157 rect.x()+dx, rect.y()+dy);
158 }
159
160 // Make sure the scroll operation is complete before allowing GL rendering to resume
161 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
162
163 return true;
164}
165
166
167QPixmap QX11GLWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const
168{
169 if (!widget || m_backBuffer.isNull())
170 return QPixmap();
171
172 QRect srcRect;
173
174 // make sure the rect is inside the widget & clip to widget's rect
175 if (!rect.isEmpty())
176 srcRect = rect & widget->rect();
177 else
178 srcRect = widget->rect();
179
180 if (srcRect.isEmpty())
181 return QPixmap();
182
183 // If it's a child widget we have to translate the coordinates
184 if (widget != window())
185 srcRect.translate(widget->mapTo(window(), QPoint(0, 0)));
186
187 QPixmap::x11SetDefaultScreen(widget->x11Info().screen());
188
189 QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType);
190 pmd->resize(srcRect.width(), srcRect.height());
191 QPixmap px(pmd);
192
193 GC tmpGc = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
194
195 // Make sure all GL rendering is complete before copying the window
196 QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.pixmapData())->context();
197 if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
198 ctx->makeCurrent();
199 eglWaitClient();
200
201 // Copy srcRect from the backing store to the new pixmap
202 XSetGraphicsExposures(X11->display, tmpGc, False);
203 XCopyArea(X11->display, m_backBuffer.handle(), px.handle(), tmpGc,
204 srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0);
205 XFreeGC(X11->display, tmpGc);
206
207 // Wait until the copy has finised before allowing more rendering into the back buffer
208 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
209
210 return px;
211}
212
213QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.