Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/egl_gbm_backend.cpp
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | |||||
42 | { | 42 | { | ||
43 | // Egl is always direct rendering | 43 | // Egl is always direct rendering | ||
44 | setIsDirectRendering(true); | 44 | setIsDirectRendering(true); | ||
45 | setSyncsToVBlank(true); | 45 | setSyncsToVBlank(true); | ||
46 | connect(m_backend, &DrmBackend::outputAdded, this, &EglGbmBackend::createOutput); | 46 | connect(m_backend, &DrmBackend::outputAdded, this, &EglGbmBackend::createOutput); | ||
47 | connect(m_backend, &DrmBackend::outputRemoved, this, | 47 | connect(m_backend, &DrmBackend::outputRemoved, this, | ||
48 | [this] (DrmOutput *output) { | 48 | [this] (DrmOutput *output) { | ||
49 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | 49 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | ||
50 | [output] (const Output &o) { | 50 | [output] (const EglGbmOutput &o) { | ||
51 | return o.output == output; | 51 | return o.output == output; | ||
52 | } | 52 | } | ||
53 | ); | 53 | ); | ||
54 | if (it == m_outputs.end()) { | 54 | if (it == m_outputs.end()) { | ||
55 | return; | 55 | return; | ||
56 | } | 56 | } | ||
57 | cleanupOutput(*it); | 57 | cleanupOutput(*it); | ||
58 | m_outputs.erase(it); | 58 | m_outputs.erase(it); | ||
Show All 9 Lines | |||||
68 | void EglGbmBackend::cleanupSurfaces() | 68 | void EglGbmBackend::cleanupSurfaces() | ||
69 | { | 69 | { | ||
70 | for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { | 70 | for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { | ||
71 | cleanupOutput(*it); | 71 | cleanupOutput(*it); | ||
72 | } | 72 | } | ||
73 | m_outputs.clear(); | 73 | m_outputs.clear(); | ||
74 | } | 74 | } | ||
75 | 75 | | |||
76 | void EglGbmBackend::cleanupOutput(const Output &o) | 76 | void EglGbmBackend::cleanupOutput(const EglGbmOutput &o) | ||
77 | { | 77 | { | ||
78 | o.output->releaseGbm(); | 78 | o.output->releaseGbm(); | ||
79 | 79 | | |||
80 | if (o.eglSurface != EGL_NO_SURFACE) { | 80 | if (o.eglSurface != EGL_NO_SURFACE) { | ||
81 | eglDestroySurface(eglDisplay(), o.eglSurface); | 81 | eglDestroySurface(eglDisplay(), o.eglSurface); | ||
82 | } | 82 | } | ||
83 | } | 83 | } | ||
84 | 84 | | |||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Line(s) | |||||
137 | { | 137 | { | ||
138 | initBufferConfigs(); | 138 | initBufferConfigs(); | ||
139 | 139 | | |||
140 | if (!createContext()) { | 140 | if (!createContext()) { | ||
141 | return false; | 141 | return false; | ||
142 | } | 142 | } | ||
143 | 143 | | |||
144 | const auto outputs = m_backend->outputs(); | 144 | const auto outputs = m_backend->outputs(); | ||
145 | for (DrmOutput *drmOutput: outputs) { | 145 | for (Output *drmOutput: outputs) { | ||
146 | createOutput(drmOutput); | 146 | createOutput(qobject_cast<DrmOutput*>(drmOutput)); | ||
graesslin: Does the class need a DrmOutput or could it be changed to operate on Output instead? | |||||
147 | } | 147 | } | ||
148 | if (m_outputs.isEmpty()) { | 148 | if (m_outputs.isEmpty()) { | ||
149 | qCCritical(KWIN_DRM) << "Create Window Surfaces failed"; | 149 | qCCritical(KWIN_DRM) << "Create Window Surfaces failed"; | ||
150 | return false; | 150 | return false; | ||
151 | } | 151 | } | ||
152 | // set our first surface as the one for the abstract backend, just to make it happy | 152 | // set our first surface as the one for the abstract backend, just to make it happy | ||
153 | setSurface(m_outputs.first().eglSurface); | 153 | setSurface(m_outputs.first().eglSurface); | ||
154 | 154 | | |||
155 | return makeContextCurrent(m_outputs.first()); | 155 | return makeContextCurrent(m_outputs.first()); | ||
156 | } | 156 | } | ||
157 | 157 | | |||
158 | void EglGbmBackend::initRemotePresent() | 158 | void EglGbmBackend::initRemotePresent() | ||
159 | { | 159 | { | ||
160 | if (qEnvironmentVariableIsSet("KWIN_NO_REMOTE")) { | 160 | if (qEnvironmentVariableIsSet("KWIN_NO_REMOTE")) { | ||
161 | return; | 161 | return; | ||
162 | } | 162 | } | ||
163 | 163 | | |||
164 | qCDebug(KWIN_DRM) << "Support for remote access enabled"; | 164 | qCDebug(KWIN_DRM) << "Support for remote access enabled"; | ||
165 | m_remoteaccessManager.reset(new RemoteAccessManager); | 165 | m_remoteaccessManager.reset(new RemoteAccessManager); | ||
166 | } | 166 | } | ||
167 | 167 | | |||
168 | bool EglGbmBackend::resetOutput(Output &o, DrmOutput *drmOutput) | 168 | bool EglGbmBackend::resetOutput(EglGbmOutput &o, DrmOutput *drmOutput) | ||
169 | { | 169 | { | ||
170 | o.output = drmOutput; | 170 | o.output = drmOutput; | ||
171 | auto size = drmOutput->pixelSize(); | 171 | auto size = drmOutput->pixelSize(); | ||
172 | 172 | | |||
173 | auto gbmSurface = std::make_shared<GbmSurface>(m_backend->gbmDevice(), size.width(), size.height(), | 173 | auto gbmSurface = std::make_shared<GbmSurface>(m_backend->gbmDevice(), size.width(), size.height(), | ||
174 | GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); | 174 | GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); | ||
175 | if (!gbmSurface) { | 175 | if (!gbmSurface) { | ||
176 | qCCritical(KWIN_DRM) << "Create gbm surface failed"; | 176 | qCCritical(KWIN_DRM) << "Create gbm surface failed"; | ||
Show All 14 Lines | 183 | } else { | |||
191 | o.eglSurface = eglSurface; | 191 | o.eglSurface = eglSurface; | ||
192 | o.gbmSurface = gbmSurface; | 192 | o.gbmSurface = gbmSurface; | ||
193 | } | 193 | } | ||
194 | return true; | 194 | return true; | ||
195 | } | 195 | } | ||
196 | 196 | | |||
197 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | 197 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | ||
198 | { | 198 | { | ||
199 | Output o; | 199 | EglGbmOutput o; | ||
200 | if (resetOutput(o, drmOutput)) { | 200 | if (resetOutput(o, drmOutput)) { | ||
201 | connect(drmOutput, &DrmOutput::modeChanged, this, | 201 | connect(drmOutput, &DrmOutput::modeChanged, this, | ||
202 | [drmOutput, this] { | 202 | [drmOutput, this] { | ||
203 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | 203 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | ||
204 | [drmOutput] (const auto &o) { | 204 | [drmOutput] (const auto &o) { | ||
205 | return o.output == drmOutput; | 205 | return o.output == drmOutput; | ||
206 | } | 206 | } | ||
207 | ); | 207 | ); | ||
208 | if (it == m_outputs.end()) { | 208 | if (it == m_outputs.end()) { | ||
209 | return; | 209 | return; | ||
210 | } | 210 | } | ||
211 | resetOutput(*it, drmOutput); | 211 | resetOutput(*it, drmOutput); | ||
212 | } | 212 | } | ||
213 | ); | 213 | ); | ||
214 | m_outputs << o; | 214 | m_outputs << o; | ||
215 | } | 215 | } | ||
216 | } | 216 | } | ||
217 | 217 | | |||
218 | bool EglGbmBackend::makeContextCurrent(const Output &output) | 218 | bool EglGbmBackend::makeContextCurrent(const EglGbmOutput &output) | ||
219 | { | 219 | { | ||
220 | const EGLSurface surface = output.eglSurface; | 220 | const EGLSurface surface = output.eglSurface; | ||
221 | if (surface == EGL_NO_SURFACE) { | 221 | if (surface == EGL_NO_SURFACE) { | ||
222 | return false; | 222 | return false; | ||
223 | } | 223 | } | ||
224 | if (eglMakeCurrent(eglDisplay(), surface, surface, context()) == EGL_FALSE) { | 224 | if (eglMakeCurrent(eglDisplay(), surface, surface, context()) == EGL_FALSE) { | ||
225 | qCCritical(KWIN_DRM) << "Make Context Current failed"; | 225 | qCCritical(KWIN_DRM) << "Make Context Current failed"; | ||
226 | return false; | 226 | return false; | ||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Line(s) | |||||
298 | void EglGbmBackend::present() | 298 | void EglGbmBackend::present() | ||
299 | { | 299 | { | ||
300 | for (auto &o: m_outputs) { | 300 | for (auto &o: m_outputs) { | ||
301 | makeContextCurrent(o); | 301 | makeContextCurrent(o); | ||
302 | presentOnOutput(o); | 302 | presentOnOutput(o); | ||
303 | } | 303 | } | ||
304 | } | 304 | } | ||
305 | 305 | | |||
306 | void EglGbmBackend::presentOnOutput(EglGbmBackend::Output &o) | 306 | void EglGbmBackend::presentOnOutput(EglGbmBackend::EglGbmOutput &o) | ||
307 | { | 307 | { | ||
308 | eglSwapBuffers(eglDisplay(), o.eglSurface); | 308 | eglSwapBuffers(eglDisplay(), o.eglSurface); | ||
309 | o.buffer = m_backend->createBuffer(o.gbmSurface); | 309 | o.buffer = m_backend->createBuffer(o.gbmSurface); | ||
310 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(o.gbmSurface->surface())) { | 310 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(o.gbmSurface->surface())) { | ||
311 | // GBM surface is released on page flip so | 311 | // GBM surface is released on page flip so | ||
312 | // we should pass the buffer before it's presented | 312 | // we should pass the buffer before it's presented | ||
313 | m_remoteaccessManager->passBuffer(o.output, o.buffer); | 313 | m_remoteaccessManager->passBuffer(o.output, o.buffer); | ||
314 | } | 314 | } | ||
Show All 19 Lines | |||||
334 | QRegion EglGbmBackend::prepareRenderingFrame() | 334 | QRegion EglGbmBackend::prepareRenderingFrame() | ||
335 | { | 335 | { | ||
336 | startRenderTimer(); | 336 | startRenderTimer(); | ||
337 | return QRegion(); | 337 | return QRegion(); | ||
338 | } | 338 | } | ||
339 | 339 | | |||
340 | QRegion EglGbmBackend::prepareRenderingForScreen(int screenId) | 340 | QRegion EglGbmBackend::prepareRenderingForScreen(int screenId) | ||
341 | { | 341 | { | ||
342 | const Output &o = m_outputs.at(screenId); | 342 | const EglGbmOutput &o = m_outputs.at(screenId); | ||
343 | makeContextCurrent(o); | 343 | makeContextCurrent(o); | ||
344 | if (supportsBufferAge()) { | 344 | if (supportsBufferAge()) { | ||
345 | QRegion region; | 345 | QRegion region; | ||
346 | 346 | | |||
347 | // Note: An age of zero means the buffer contents are undefined | 347 | // Note: An age of zero means the buffer contents are undefined | ||
348 | if (o.bufferAge > 0 && o.bufferAge <= o.damageHistory.count()) { | 348 | if (o.bufferAge > 0 && o.bufferAge <= o.damageHistory.count()) { | ||
349 | for (int i = 0; i < o.bufferAge - 1; i++) | 349 | for (int i = 0; i < o.bufferAge - 1; i++) | ||
350 | region |= o.damageHistory[i]; | 350 | region |= o.damageHistory[i]; | ||
Show All 9 Lines | |||||
360 | void EglGbmBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) | 360 | void EglGbmBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) | ||
361 | { | 361 | { | ||
362 | Q_UNUSED(renderedRegion) | 362 | Q_UNUSED(renderedRegion) | ||
363 | Q_UNUSED(damagedRegion) | 363 | Q_UNUSED(damagedRegion) | ||
364 | } | 364 | } | ||
365 | 365 | | |||
366 | void EglGbmBackend::endRenderingFrameForScreen(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) | 366 | void EglGbmBackend::endRenderingFrameForScreen(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) | ||
367 | { | 367 | { | ||
368 | Output &o = m_outputs[screenId]; | 368 | EglGbmOutput &o = m_outputs[screenId]; | ||
369 | if (damagedRegion.intersected(o.output->geometry()).isEmpty() && screenId == 0) { | 369 | if (damagedRegion.intersected(o.output->geometry()).isEmpty() && screenId == 0) { | ||
370 | 370 | | |||
371 | // If the damaged region of a window is fully occluded, the only | 371 | // If the damaged region of a window is fully occluded, the only | ||
372 | // rendering done, if any, will have been to repair a reused back | 372 | // rendering done, if any, will have been to repair a reused back | ||
373 | // buffer, making it identical to the front buffer. | 373 | // buffer, making it identical to the front buffer. | ||
374 | // | 374 | // | ||
375 | // In this case we won't post the back buffer. Instead we'll just | 375 | // In this case we won't post the back buffer. Instead we'll just | ||
376 | // set the buffer age to 1, so the repaired regions won't be | 376 | // set the buffer age to 1, so the repaired regions won't be | ||
▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines |
Does the class need a DrmOutput or could it be changed to operate on Output instead?