Changeset View
Changeset View
Standalone View
Standalone View
plugins/scenes/opengl/scene_opengl.cpp
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Line(s) | |||||
47 | #include "screens.h" | 47 | #include "screens.h" | ||
48 | #include "cursor.h" | 48 | #include "cursor.h" | ||
49 | #include "decorations/decoratedclient.h" | 49 | #include "decorations/decoratedclient.h" | ||
50 | #include <logging.h> | 50 | #include <logging.h> | ||
51 | 51 | | |||
52 | #include <KWaylandServer/buffer_interface.h> | 52 | #include <KWaylandServer/buffer_interface.h> | ||
53 | #include <KWaylandServer/subcompositor_interface.h> | 53 | #include <KWaylandServer/subcompositor_interface.h> | ||
54 | #include <KWaylandServer/surface_interface.h> | 54 | #include <KWaylandServer/surface_interface.h> | ||
55 | #include <KWaylandServer/screencast_interface.h> | ||||
55 | 56 | | |||
56 | #include <array> | 57 | #include <array> | ||
57 | #include <cmath> | 58 | #include <cmath> | ||
58 | #include <cstddef> | 59 | #include <cstddef> | ||
59 | #include <unistd.h> | 60 | #include <unistd.h> | ||
60 | 61 | | |||
61 | #include <QDBusConnection> | 62 | #include <QDBusConnection> | ||
62 | #include <QDBusConnectionInterface> | 63 | #include <QDBusConnectionInterface> | ||
63 | #include <QDBusInterface> | 64 | #include <QDBusInterface> | ||
64 | #include <QGraphicsScale> | 65 | #include <QGraphicsScale> | ||
65 | #include <QPainter> | 66 | #include <QPainter> | ||
66 | #include <QStringList> | 67 | #include <QStringList> | ||
67 | #include <QVector2D> | 68 | #include <QVector2D> | ||
68 | #include <QVector4D> | 69 | #include <QVector4D> | ||
69 | #include <QMatrix4x4> | 70 | #include <QMatrix4x4> | ||
70 | 71 | | |||
71 | #include <KLocalizedString> | 72 | #include <KLocalizedString> | ||
72 | #include <KNotification> | 73 | #include <KNotification> | ||
73 | #include <KProcess> | 74 | #include <KProcess> | ||
74 | 75 | | |||
76 | #include "screencaststream.h" | ||||
77 | | ||||
75 | // HACK: workaround for libepoxy < 1.3 | 78 | // HACK: workaround for libepoxy < 1.3 | ||
76 | #ifndef GL_GUILTY_CONTEXT_RESET | 79 | #ifndef GL_GUILTY_CONTEXT_RESET | ||
77 | #define GL_GUILTY_CONTEXT_RESET 0x8253 | 80 | #define GL_GUILTY_CONTEXT_RESET 0x8253 | ||
78 | #endif | 81 | #endif | ||
79 | #ifndef GL_INNOCENT_CONTEXT_RESET | 82 | #ifndef GL_INNOCENT_CONTEXT_RESET | ||
80 | #define GL_INNOCENT_CONTEXT_RESET 0x8254 | 83 | #define GL_INNOCENT_CONTEXT_RESET 0x8254 | ||
81 | #endif | 84 | #endif | ||
82 | #ifndef GL_UNKNOWN_CONTEXT_RESET | 85 | #ifndef GL_UNKNOWN_CONTEXT_RESET | ||
▲ Show 20 Lines • Show All 1440 Lines • ▼ Show 20 Line(s) | 1407 | { | |||
1523 | vbo->unbindArrays(); | 1526 | vbo->unbindArrays(); | ||
1524 | 1527 | | |||
1525 | setBlendEnabled(false); | 1528 | setBlendEnabled(false); | ||
1526 | 1529 | | |||
1527 | if (!data.shader) | 1530 | if (!data.shader) | ||
1528 | ShaderManager::instance()->popShader(); | 1531 | ShaderManager::instance()->popShader(); | ||
1529 | 1532 | | |||
1530 | endRenderWindow(); | 1533 | endRenderWindow(); | ||
1534 | Q_EMIT painted(); | ||||
1535 | } | ||||
1536 | | ||||
1537 | static void recordFrame(OpenGLWindowPixmap* pixmap, ScreenCastStream* stream) | ||||
1538 | { | ||||
1539 | auto pwStream = stream->pwStream; | ||||
1540 | struct pw_buffer *buffer = pw_stream_dequeue_buffer(pwStream); | ||||
1541 | | ||||
1542 | if (!buffer) { | ||||
1543 | qCDebug(KWIN_OPENGL) << "Failed to record frame: couldn't obtain PipeWire buffer"; | ||||
1544 | return; | ||||
1531 | } | 1545 | } | ||
1532 | 1546 | | |||
1547 | struct spa_buffer *spa_buffer = buffer->buffer; | ||||
1548 | struct spa_data *spa_data = spa_buffer->datas; | ||||
1549 | | ||||
1550 | const auto s = pixmap->texture()->size(); | ||||
1551 | | ||||
1552 | uint8_t *data = (uint8_t *) spa_data[0].data; | ||||
1553 | if (!data) { | ||||
1554 | qCWarning(KWIN_OPENGL) << "Failed to record frame: invalid buffer data"; | ||||
1555 | pw_stream_queue_buffer(pwStream, buffer); | ||||
1556 | return; | ||||
1557 | } | ||||
1558 | | ||||
1559 | if (spa_buffer->datas[0].type != SPA_DATA_DmaBuf && !data) { | ||||
1560 | pw_stream_queue_buffer(pwStream, buffer); | ||||
1561 | return; | ||||
1562 | } | ||||
1563 | | ||||
1564 | GLint streamStride; | ||||
1565 | glGetIntegerv(GL_PACK_ROW_LENGTH, &streamStride); | ||||
1566 | if (streamStride == 0) { | ||||
1567 | streamStride = SPA_ROUND_UP_N (s.width() * stream->bytesPerPixel(), 4); | ||||
1568 | } | ||||
1569 | if (uint(streamStride * s.height()) > spa_data->maxsize) { | ||||
1570 | qCDebug(KWIN_OPENGL) << "Failed to record frame: window is too big"; | ||||
1571 | pw_stream_queue_buffer(pwStream, buffer); | ||||
1572 | return; | ||||
1573 | } | ||||
1574 | | ||||
1575 | pixmap->texture()->bind(); | ||||
1576 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | ||||
1577 | pixmap->texture()->unbind(); | ||||
1578 | | ||||
1579 | spa_data[0].chunk->offset = 0; | ||||
1580 | spa_data[0].chunk->size = spa_data[0].maxsize; | ||||
1581 | spa_data[0].chunk->stride = streamStride; | ||||
1582 | | ||||
1583 | pw_stream_queue_buffer(pwStream, buffer); | ||||
1584 | } | ||||
1585 | | ||||
1586 | void OpenGLWindow::startStreaming(KWaylandServer::ScreencastStreamInterface * waylandStream) | ||||
1587 | { | ||||
1588 | auto stream = new ScreenCastStream(size(), m_scene); | ||||
1589 | if (stream->init(4)) { | ||||
1590 | QObject::connect(waylandStream, &KWaylandServer::ScreencastStreamInterface::stop, stream, &ScreenCastStream::stop); | ||||
1591 | QObject::connect(stream, &ScreenCastStream::streamReady, waylandStream, [this, waylandStream] (quint32 nodeId) { | ||||
1592 | waylandStream->sendCreated(nodeId, size()); | ||||
1593 | }); | ||||
1594 | connect(this, &OpenGLWindow::painted, stream, [this, stream] () { | ||||
1595 | recordFrame(windowPixmap<OpenGLWindowPixmap>(), stream); | ||||
1596 | }); | ||||
1597 | QObject::connect(stream, &ScreenCastStream::stopStreaming, waylandStream, [waylandStream, stream] () { | ||||
1598 | waylandStream->sendClosed(); | ||||
1599 | delete stream; | ||||
1600 | }); | ||||
1601 | } else { | ||||
1602 | waylandStream->sendFailed(stream->error()); | ||||
1603 | delete stream; | ||||
1604 | } | ||||
1605 | } | ||||
1533 | 1606 | | |||
1534 | //**************************************** | 1607 | //**************************************** | ||
1535 | // OpenGLWindowPixmap | 1608 | // OpenGLWindowPixmap | ||
1536 | //**************************************** | 1609 | //**************************************** | ||
1537 | 1610 | | |||
1538 | OpenGLWindowPixmap::OpenGLWindowPixmap(Scene::Window *window, SceneOpenGL* scene) | 1611 | OpenGLWindowPixmap::OpenGLWindowPixmap(Scene::Window *window, SceneOpenGL* scene) | ||
1539 | : WindowPixmap(window) | 1612 | : WindowPixmap(window) | ||
1540 | , m_texture(scene->createTexture()) | 1613 | , m_texture(scene->createTexture()) | ||
▲ Show 20 Lines • Show All 1181 Lines • Show Last 20 Lines |