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 47 Lines • ▼ Show 20 Line(s) | |||||
274 | void EglGbmBackend::present() | 274 | void EglGbmBackend::present() | ||
275 | { | 275 | { | ||
276 | for (auto &o: m_outputs) { | 276 | for (auto &o: m_outputs) { | ||
277 | makeContextCurrent(o); | 277 | makeContextCurrent(o); | ||
278 | presentOnOutput(o); | 278 | presentOnOutput(o); | ||
279 | } | 279 | } | ||
280 | } | 280 | } | ||
281 | 281 | | |||
282 | void EglGbmBackend::presentOnOutput(EglGbmBackend::Output &o) | 282 | void EglGbmBackend::presentOnOutput(EglGbmBackend::EglGbmOutput &o) | ||
283 | { | 283 | { | ||
284 | eglSwapBuffers(eglDisplay(), o.eglSurface); | 284 | eglSwapBuffers(eglDisplay(), o.eglSurface); | ||
285 | o.buffer = m_backend->createBuffer(o.gbmSurface); | 285 | o.buffer = m_backend->createBuffer(o.gbmSurface); | ||
286 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(o.gbmSurface->surface())) { | 286 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(o.gbmSurface->surface())) { | ||
287 | // GBM surface is released on page flip so | 287 | // GBM surface is released on page flip so | ||
288 | // we should pass the buffer before it's presented | 288 | // we should pass the buffer before it's presented | ||
289 | m_remoteaccessManager->passBuffer(o.output, o.buffer); | 289 | m_remoteaccessManager->passBuffer(o.output, o.buffer); | ||
290 | } | 290 | } | ||
Show All 19 Lines | |||||
310 | QRegion EglGbmBackend::prepareRenderingFrame() | 310 | QRegion EglGbmBackend::prepareRenderingFrame() | ||
311 | { | 311 | { | ||
312 | startRenderTimer(); | 312 | startRenderTimer(); | ||
313 | return QRegion(); | 313 | return QRegion(); | ||
314 | } | 314 | } | ||
315 | 315 | | |||
316 | QRegion EglGbmBackend::prepareRenderingForScreen(int screenId) | 316 | QRegion EglGbmBackend::prepareRenderingForScreen(int screenId) | ||
317 | { | 317 | { | ||
318 | const Output &o = m_outputs.at(screenId); | 318 | const EglGbmOutput &o = m_outputs.at(screenId); | ||
319 | makeContextCurrent(o); | 319 | makeContextCurrent(o); | ||
320 | if (supportsBufferAge()) { | 320 | if (supportsBufferAge()) { | ||
321 | QRegion region; | 321 | QRegion region; | ||
322 | 322 | | |||
323 | // Note: An age of zero means the buffer contents are undefined | 323 | // Note: An age of zero means the buffer contents are undefined | ||
324 | if (o.bufferAge > 0 && o.bufferAge <= o.damageHistory.count()) { | 324 | if (o.bufferAge > 0 && o.bufferAge <= o.damageHistory.count()) { | ||
325 | for (int i = 0; i < o.bufferAge - 1; i++) | 325 | for (int i = 0; i < o.bufferAge - 1; i++) | ||
326 | region |= o.damageHistory[i]; | 326 | region |= o.damageHistory[i]; | ||
Show All 9 Lines | |||||
336 | void EglGbmBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) | 336 | void EglGbmBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) | ||
337 | { | 337 | { | ||
338 | Q_UNUSED(renderedRegion) | 338 | Q_UNUSED(renderedRegion) | ||
339 | Q_UNUSED(damagedRegion) | 339 | Q_UNUSED(damagedRegion) | ||
340 | } | 340 | } | ||
341 | 341 | | |||
342 | void EglGbmBackend::endRenderingFrameForScreen(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) | 342 | void EglGbmBackend::endRenderingFrameForScreen(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) | ||
343 | { | 343 | { | ||
344 | Output &o = m_outputs[screenId]; | 344 | EglGbmOutput &o = m_outputs[screenId]; | ||
345 | if (damagedRegion.intersected(o.output->geometry()).isEmpty() && screenId == 0) { | 345 | if (damagedRegion.intersected(o.output->geometry()).isEmpty() && screenId == 0) { | ||
346 | 346 | | |||
347 | // If the damaged region of a window is fully occluded, the only | 347 | // If the damaged region of a window is fully occluded, the only | ||
348 | // rendering done, if any, will have been to repair a reused back | 348 | // rendering done, if any, will have been to repair a reused back | ||
349 | // buffer, making it identical to the front buffer. | 349 | // buffer, making it identical to the front buffer. | ||
350 | // | 350 | // | ||
351 | // In this case we won't post the back buffer. Instead we'll just | 351 | // In this case we won't post the back buffer. Instead we'll just | ||
352 | // set the buffer age to 1, so the repaired regions won't be | 352 | // 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?