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] (const KWayland::Server::ScreencastingSource &videoSource, wl_resource *r) { | ||||
226 | auto stream = new ScreenCastStream(videoSource.geometry().size(), this, this); | ||||
davidedmundson: where does stream get deleted in the case were things don't fail? | |||||
227 | if (stream->init()) { | ||||
228 | connect(stream, &ScreenCastStream::streamReady, this, [videoSource, r, stream] (int nodeid) { | ||||
229 | waylandServer()->screencasting()->sendCreated(r, nodeid, videoSource.sourceId()); | ||||
230 | connect(waylandServer()->screencasting(), &KWayland::Server::ScreencastingInterface::stop, stream, [stream] (uint nodeid) { | ||||
231 | if (nodeid == stream->nodeId()) | ||||
232 | stream->stop(); | ||||
233 | }); | ||||
234 | }); | ||||
235 | connect(this, &EglGbmBackend::passBuffer, stream, [drmOutput, stream] (DrmOutput *output, DrmSurfaceBuffer* gbmbuf) { | ||||
236 | if (drmOutput == output) { | ||||
237 | auto bo = gbmbuf->getBo(); | ||||
238 | stream->recordFrame(bo, gbm_bo_get_width(bo), gbm_bo_get_height(bo), gbm_bo_get_stride(bo)); | ||||
239 | } | ||||
240 | }); | ||||
241 | connect(stream, &ScreenCastStream::stopStreaming, this, [videoSource, r] (int nodeid) { | ||||
242 | waylandServer()->screencasting()->sendClosed(r, nodeid); | ||||
243 | }); | ||||
244 | } else { | ||||
245 | waylandServer()->screencasting()->sendFailed(r, videoSource.sourceId(), stream->error()); | ||||
246 | delete stream; | ||||
247 | } | ||||
248 | }; | ||||
249 | const KWayland::Server::ScreencastingSource videoSource = {output.output->name(), QStringLiteral("video-display"), true, output.output->geometry(), f}; | ||||
250 | output.source = videoSource; | ||||
251 | waylandServer()->screencasting()->addSource(output.source); | ||||
252 | | ||||
219 | resetFramebuffer(output); | 253 | resetFramebuffer(output); | ||
220 | return true; | 254 | return true; | ||
221 | } | 255 | } | ||
222 | 256 | | |||
223 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | 257 | void EglGbmBackend::createOutput(DrmOutput *drmOutput) | ||
224 | { | 258 | { | ||
225 | Output newOutput; | 259 | Output newOutput; | ||
226 | if (resetOutput(newOutput, drmOutput)) { | 260 | if (resetOutput(newOutput, drmOutput)) { | ||
Show All 19 Lines | 279 | { | |||
246 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | 280 | auto it = std::find_if(m_outputs.begin(), m_outputs.end(), | ||
247 | [drmOutput] (const Output &output) { | 281 | [drmOutput] (const Output &output) { | ||
248 | return output.output == drmOutput; | 282 | return output.output == drmOutput; | ||
249 | } | 283 | } | ||
250 | ); | 284 | ); | ||
251 | if (it == m_outputs.end()) { | 285 | if (it == m_outputs.end()) { | ||
252 | return; | 286 | return; | ||
253 | } | 287 | } | ||
288 | | ||||
289 | waylandServer()->screencasting()->removeSource(it->source); | ||||
290 | | ||||
254 | cleanupOutput(*it); | 291 | cleanupOutput(*it); | ||
255 | m_outputs.erase(it); | 292 | m_outputs.erase(it); | ||
256 | } | 293 | } | ||
257 | 294 | | |||
258 | const float vertices[] = { | 295 | const float vertices[] = { | ||
259 | -1.0f, 1.0f, | 296 | -1.0f, 1.0f, | ||
260 | -1.0f, -1.0f, | 297 | -1.0f, -1.0f, | ||
261 | 1.0f, -1.0f, | 298 | 1.0f, -1.0f, | ||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Line(s) | |||||
436 | { | 473 | { | ||
437 | Q_UNREACHABLE(); | 474 | Q_UNREACHABLE(); | ||
438 | // Not in use. This backend does per-screen rendering. | 475 | // Not in use. This backend does per-screen rendering. | ||
439 | } | 476 | } | ||
440 | 477 | | |||
441 | void EglGbmBackend::presentOnOutput(Output &output) | 478 | void EglGbmBackend::presentOnOutput(Output &output) | ||
442 | { | 479 | { | ||
443 | eglSwapBuffers(eglDisplay(), output.eglSurface); | 480 | eglSwapBuffers(eglDisplay(), output.eglSurface); | ||
444 | output.buffer = m_backend->createBuffer(output.gbmSurface); | 481 | auto surfaceBuffer = m_backend->createBuffer(output.gbmSurface); | ||
482 | output.buffer = surfaceBuffer; | ||||
445 | 483 | | |||
446 | if(m_remoteaccessManager && gbm_surface_has_free_buffers(output.gbmSurface->surface())) { | 484 | if (gbm_surface_has_free_buffers(output.gbmSurface->surface())) { | ||
447 | // GBM surface is released on page flip so | 485 | // GBM surface is released on page flip so | ||
448 | // we should pass the buffer before it's presented. | 486 | // we should pass the buffer before it's presented. | ||
449 | m_remoteaccessManager->passBuffer(output.output, output.buffer); | 487 | | ||
488 | Q_EMIT passBuffer(output.output, surfaceBuffer); | ||||
450 | } | 489 | } | ||
451 | 490 | | |||
452 | m_backend->present(output.buffer, output.output); | 491 | m_backend->present(output.buffer, output.output); | ||
453 | 492 | | |||
454 | if (supportsBufferAge()) { | 493 | if (supportsBufferAge()) { | ||
455 | eglQuerySurface(eglDisplay(), output.eglSurface, EGL_BUFFER_AGE_EXT, &output.bufferAge); | 494 | eglQuerySurface(eglDisplay(), output.eglSurface, EGL_BUFFER_AGE_EXT, &output.bufferAge); | ||
456 | } | 495 | } | ||
457 | } | 496 | } | ||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |
where does stream get deleted in the case were things don't fail?