Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/egl_gbm_backend.cpp
Show All 19 Lines | |||||
20 | #include "egl_gbm_backend.h" | 20 | #include "egl_gbm_backend.h" | ||
21 | // kwin | 21 | // kwin | ||
22 | #include "composite.h" | 22 | #include "composite.h" | ||
23 | #include "drm_backend.h" | 23 | #include "drm_backend.h" | ||
24 | #include "drm_output.h" | 24 | #include "drm_output.h" | ||
25 | #include "gbm_surface.h" | 25 | #include "gbm_surface.h" | ||
26 | #include "logging.h" | 26 | #include "logging.h" | ||
27 | #include "options.h" | 27 | #include "options.h" | ||
28 | #include "screencaststream.h" | ||||
28 | #include "screens.h" | 29 | #include "screens.h" | ||
30 | #include "wayland_server.h" | ||||
31 | | ||||
29 | // kwin libs | 32 | // kwin libs | ||
30 | #include <kwinglplatform.h> | 33 | #include <kwinglplatform.h> | ||
31 | // Qt | 34 | // Qt | ||
32 | #include <QOpenGLContext> | 35 | #include <QOpenGLContext> | ||
33 | // system | 36 | // system | ||
34 | #include <gbm.h> | 37 | #include <gbm.h> | ||
35 | 38 | | |||
36 | namespace KWin | 39 | namespace KWin | ||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Line(s) | 190 | if (eglSurface == EGL_NO_SURFACE) { | |||
188 | qCCritical(KWIN_DRM) << "Creating EGL surface failed"; | 191 | qCCritical(KWIN_DRM) << "Creating EGL surface failed"; | ||
189 | return EGL_NO_SURFACE; | 192 | return EGL_NO_SURFACE; | ||
190 | } | 193 | } | ||
191 | return eglSurface; | 194 | return eglSurface; | ||
192 | } | 195 | } | ||
193 | 196 | | |||
194 | bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput) | 197 | bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput) | ||
195 | { | 198 | { | ||
199 | if (output.output) { | ||||
200 | waylandServer()->screencasting()->removeSource(output.source); | ||||
201 | } | ||||
196 | output.output = drmOutput; | 202 | output.output = drmOutput; | ||
197 | const QSize size = drmOutput->hardwareTransforms() ? drmOutput->pixelSize() : | 203 | const QSize size = drmOutput->hardwareTransforms() ? drmOutput->pixelSize() : | ||
198 | drmOutput->modeSize(); | 204 | drmOutput->modeSize(); | ||
199 | 205 | | |||
200 | auto gbmSurface = createGbmSurface(size); | 206 | auto gbmSurface = createGbmSurface(size); | ||
201 | if (!gbmSurface) { | 207 | if (!gbmSurface) { | ||
202 | return false; | 208 | return false; | ||
203 | } | 209 | } | ||
204 | auto eglSurface = createEglSurface(gbmSurface); | 210 | auto eglSurface = createEglSurface(gbmSurface); | ||
205 | if (eglSurface == EGL_NO_SURFACE) { | 211 | if (eglSurface == EGL_NO_SURFACE) { | ||
206 | return false; | 212 | return false; | ||
207 | } | 213 | } | ||
208 | 214 | | |||
209 | // destroy previous surface | 215 | // destroy previous surface | ||
210 | if (output.eglSurface != EGL_NO_SURFACE) { | 216 | if (output.eglSurface != EGL_NO_SURFACE) { | ||
211 | if (surface() == output.eglSurface) { | 217 | if (surface() == output.eglSurface) { | ||
212 | setSurface(eglSurface); | 218 | setSurface(eglSurface); | ||
213 | } | 219 | } | ||
214 | eglDestroySurface(eglDisplay(), output.eglSurface); | 220 | eglDestroySurface(eglDisplay(), output.eglSurface); | ||
215 | } | 221 | } | ||
216 | output.eglSurface = eglSurface; | 222 | output.eglSurface = eglSurface; | ||
217 | output.gbmSurface = gbmSurface; | 223 | output.gbmSurface = gbmSurface; | ||
218 | 224 | | |||
225 | auto f = [this, drmOutput, size] (KWayland::Server::ScreencastingStreamInterface* waylandStream) { | ||||
226 | auto stream = new ScreenCastStream(size, this, this); | ||||
davidedmundson: where does stream get deleted in the case were things don't fail? | |||||
227 | | ||||
228 | if (stream->init()) { | ||||
229 | connect(waylandStream, &KWayland::Server::ScreencastingStreamInterface::stop, stream, &ScreenCastStream::stop); | ||||
230 | connect(stream, &ScreenCastStream::streamReady, waylandStream, &KWayland::Server::ScreencastingStreamInterface::sendCreated); | ||||
231 | connect(this, &EglGbmBackend::passBuffer, stream, [drmOutput, stream] (DrmOutput *output, DrmSurfaceBuffer* gbmbuf) { | ||||
232 | if (drmOutput == output) { | ||||
233 | auto bo = gbmbuf->getBo(); | ||||
234 | stream->recordFrame(bo, gbm_bo_get_width(bo), gbm_bo_get_height(bo), gbm_bo_get_stride(bo)); | ||||
235 | } | ||||
236 | }); | ||||
237 | connect(stream, &ScreenCastStream::stopStreaming, this, [waylandStream, stream] () { | ||||
238 | waylandStream->sendClosed(); | ||||
239 | delete stream; | ||||
240 | }); | ||||
241 | } else { | ||||
242 | waylandStream->sendFailed(stream->error()); | ||||
243 | delete stream; | ||||
244 | } | ||||
245 | }; | ||||
246 | const KWayland::Server::ScreencastingSource videoSource = {output.output->name(), QStringLiteral("video-display"), true, output.output->geometry(), size, f}; | ||||
247 | output.source = videoSource; | ||||
248 | waylandServer()->screencasting()->addSource(output.source); | ||||
249 | | ||||
219 | resetFramebuffer(output); | 250 | resetFramebuffer(output); | ||
220 | return true; | 251 | return true; | ||
221 | } | 252 | } | ||
222 | 253 | | |||
223 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | 254 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | ||
224 | { | 255 | { | ||
225 | Output newOutput; | 256 | Output newOutput; | ||
226 | if (resetOutput(newOutput, drmOutput)) { | 257 | if (resetOutput(newOutput, drmOutput)) { | ||
Show All 19 Lines | 276 | { | |||
246 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | 277 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | ||
247 | [drmOutput] (const Output &output) { | 278 | [drmOutput] (const Output &output) { | ||
248 | return output.output == drmOutput; | 279 | return output.output == drmOutput; | ||
249 | } | 280 | } | ||
250 | ); | 281 | ); | ||
251 | if (it == m_outputs.end()) { | 282 | if (it == m_outputs.end()) { | ||
252 | return; | 283 | return; | ||
253 | } | 284 | } | ||
285 | | ||||
286 | waylandServer()->screencasting()->removeSource(it->source); | ||||
287 | | ||||
254 | cleanupOutput(*it); | 288 | cleanupOutput(*it); | ||
255 | m_outputs.erase(it); | 289 | m_outputs.erase(it); | ||
256 | } | 290 | } | ||
257 | 291 | | |||
258 | const float vertices[] = { | 292 | const float vertices[] = { | ||
259 | -1.0f, 1.0f, | 293 | -1.0f, 1.0f, | ||
260 | -1.0f, -1.0f, | 294 | -1.0f, -1.0f, | ||
261 | 1.0f, -1.0f, | 295 | 1.0f, -1.0f, | ||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Line(s) | |||||
436 | { | 470 | { | ||
437 | Q_UNREACHABLE(); | 471 | Q_UNREACHABLE(); | ||
438 | // Not in use. This backend does per-screen rendering. | 472 | // Not in use. This backend does per-screen rendering. | ||
439 | } | 473 | } | ||
440 | 474 | | |||
441 | void EglGbmBackend::presentOnOutput(Output &output) | 475 | void EglGbmBackend::presentOnOutput(Output &output) | ||
442 | { | 476 | { | ||
443 | eglSwapBuffers(eglDisplay(), output.eglSurface); | 477 | eglSwapBuffers(eglDisplay(), output.eglSurface); | ||
444 | output.buffer = m_backend->createBuffer(output.gbmSurface); | 478 | auto surfaceBuffer = m_backend->createBuffer(output.gbmSurface); | ||
479 | output.buffer = surfaceBuffer; | ||||
445 | 480 | | |||
446 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(output.gbmSurface->surface())) { | 481 | if (gbm_surface_has_free_buffers(output.gbmSurface->surface())) { | ||
447 | // GBM surface is released on page flip so | 482 | // GBM surface is released on page flip so | ||
448 | // we should pass the buffer before it's presented. | 483 | // we should pass the buffer before it's presented. | ||
449 | m_remoteaccessManager->passBuffer(output.output, output.buffer); | 484 | | ||
485 | Q_EMIT passBuffer(output.output, surfaceBuffer); | ||||
450 | } | 486 | } | ||
451 | 487 | | |||
452 | m_backend->present(output.buffer, output.output); | 488 | m_backend->present(output.buffer, output.output); | ||
453 | 489 | | |||
454 | if (supportsBufferAge()) { | 490 | if (supportsBufferAge()) { | ||
455 | eglQuerySurface(eglDisplay(), output.eglSurface, EGL_BUFFER_AGE_EXT, &output.bufferAge); | 491 | eglQuerySurface(eglDisplay(), output.eglSurface, EGL_BUFFER_AGE_EXT, &output.bufferAge); | ||
456 | } | 492 | } | ||
457 | } | 493 | } | ||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |
where does stream get deleted in the case were things don't fail?