68 |
70 |
69 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp |
71 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp |
70 |
72 |
71 void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset) |
73 void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset) |
72 { |
74 { |
73 // qDebug("QX11GLWindowSurface::flush()"); |
75 // We don't need to know the widget which initiated the flush. Instead we just use the offset |
74 QTime startTime = QTime::currentTime(); |
76 // to translate the widgetRegion: |
|
77 Q_UNUSED(widget); |
|
78 |
75 if (m_backBuffer.isNull()) { |
79 if (m_backBuffer.isNull()) { |
76 qDebug("QHarmattanWindowSurface::flush() - backBuffer is null, not flushing anything"); |
80 qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything"); |
77 return; |
81 return; |
78 } |
82 } |
79 |
83 |
80 QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft(); |
84 Q_ASSERT(window()->size() != m_backBuffer.size()); |
81 QRegion windowRegion(widgetRegion); |
85 |
82 QRect boundingRect = widgetRegion.boundingRect(); |
86 // Wait for all GL rendering to the back buffer pixmap to complete before trying to |
83 if (!widgetOffset.isNull()) |
87 // copy it to the window. We do this by making sure the pixmap's context is current |
84 windowRegion.translate(-widgetOffset); |
88 // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to |
85 QRect windowBoundingRect = windowRegion.boundingRect(); |
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 } |
86 |
101 |
87 int rectCount; |
102 int rectCount; |
88 XRectangle *rects = (XRectangle *)qt_getClipRects(windowRegion, rectCount); |
103 XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount); |
89 if (rectCount <= 0) |
104 if (rectCount <= 0) |
90 return; |
105 return; |
91 // qDebug() << "XSetClipRectangles"; |
106 |
92 // for (int i = 0; i < num; ++i) |
107 XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded); |
93 // qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; |
108 |
94 |
109 QRect dirtyRect = widgetRegion.boundingRect().translated(-offset); |
95 if (m_GC == 0) { |
110 XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC, |
96 m_GC = XCreateGC(X11->display, m_window->handle(), 0, 0); |
111 dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), |
97 XSetGraphicsExposures(X11->display, m_GC, False); |
112 dirtyRect.x(), dirtyRect.y()); |
98 } |
113 |
99 |
114 // Make sure the blit of the update from the back buffer to the window completes |
100 XSetClipRectangles(X11->display, m_GC, 0, 0, rects, rectCount, YXBanded); |
115 // before allowing rendering to start again to the back buffer. Otherwise the GPU |
101 XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_GC, |
116 // might start rendering to the back buffer again while the blit takes place. |
102 boundingRect.x() + offset.x(), boundingRect.y() + offset.y(), |
117 eglWaitNative(EGL_CORE_NATIVE_ENGINE); |
103 boundingRect.width(), boundingRect.height(), |
|
104 windowBoundingRect.x(), windowBoundingRect.y()); |
|
105 } |
118 } |
106 |
119 |
107 void QX11GLWindowSurface::setGeometry(const QRect &rect) |
120 void QX11GLWindowSurface::setGeometry(const QRect &rect) |
108 { |
121 { |
109 if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) { |
122 if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) { |
|
123 QX11GLPixmapData *pd = new QX11GLPixmapData; |
110 QSize newSize = rect.size(); |
124 QSize newSize = rect.size(); |
111 // QSize newSize(1024,512); |
|
112 qDebug() << "QX11GLWindowSurface::setGeometry() - creating a pixmap of size" << newSize; |
|
113 QX11GLPixmapData *pd = new QX11GLPixmapData; |
|
114 pd->resize(newSize.width(), newSize.height()); |
125 pd->resize(newSize.width(), newSize.height()); |
115 m_backBuffer = QPixmap(pd); |
126 m_backBuffer = QPixmap(pd); |
116 } |
127 if (window()->testAttribute(Qt::WA_TranslucentBackground)) |
117 |
128 m_backBuffer.fill(Qt::transparent); |
118 // if (gc) |
129 if (m_pixmapGC) { |
119 // XFreeGC(X11->display, gc); |
130 XFreeGC(X11->display, m_pixmapGC); |
120 // gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0); |
131 m_pixmapGC = 0; |
121 // XSetGraphicsExposures(X11->display, gc, False); |
132 } |
|
133 } |
|
134 |
122 QWindowSurface::setGeometry(rect); |
135 QWindowSurface::setGeometry(rect); |
123 } |
136 } |
124 |
137 |
125 bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy) |
138 bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy) |
126 { |
139 { |
127 Q_UNUSED(area); |
140 if (m_backBuffer.isNull()) |
128 Q_UNUSED(dx); |
141 return false; |
129 Q_UNUSED(dy); |
142 |
130 return false; |
143 Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class); |
131 } |
144 |
132 |
145 // Make sure all GL rendering is complete before starting the scroll operation: |
133 /* |
146 QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context(); |
134 void QX11GLWindowSurface::beginPaint(const QRegion ®ion) |
147 if (QGLContext::currentContext() != ctx && ctx && ctx->isValid()) |
135 { |
148 ctx->makeCurrent(); |
136 } |
149 eglWaitClient(); |
137 |
150 |
138 void QX11GLWindowSurface::endPaint(const QRegion ®ion) |
151 if (!m_pixmapGC) |
139 { |
152 m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0); |
140 } |
153 |
141 |
154 foreach (const QRect& rect, area.rects()) { |
142 QImage *QX11GLWindowSurface::buffer(const QWidget *widget) |
155 XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC, |
143 { |
156 rect.x(), rect.y(), rect.width(), rect.height(), |
144 } |
157 rect.x()+dx, rect.y()+dy); |
145 */ |
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 |
|
167 QPixmap 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 } |
146 |
212 |
147 QT_END_NAMESPACE |
213 QT_END_NAMESPACE |