pipewire: Fix downloading software-rotated textures
At the moment we'll be setting the YInverted setting, but in practice that won't have any effect as it only changes the render matrix and we'll end up streaming inverted textures. This change addresses it by rendering it into another texture first to resolve this situation and then download that new texture instead.
This commit is contained in:
parent
67ec16c335
commit
c07182490d
3 changed files with 38 additions and 0 deletions
|
@ -721,6 +721,7 @@ GLPlatform::GLPlatform()
|
|||
m_limitedGLSL(false),
|
||||
m_textureNPOT(false),
|
||||
m_limitedNPOT(false),
|
||||
m_packInvert(false),
|
||||
m_virtualMachine(false),
|
||||
m_preferBufferSubData(false),
|
||||
m_platformInterface(NoOpenGLPlatformInterface),
|
||||
|
@ -801,6 +802,7 @@ void GLPlatform::detect(OpenGLPlatformInterface platformInterface)
|
|||
|
||||
m_chipset = QByteArrayLiteral("Unknown");
|
||||
m_preferBufferSubData = false;
|
||||
m_packInvert = m_extensions.contains("GL_MESA_pack_invert");
|
||||
|
||||
|
||||
// Mesa classic drivers
|
||||
|
@ -1200,6 +1202,9 @@ bool GLPlatform::supports(GLFeature feature) const
|
|||
case LimitedNPOT:
|
||||
return m_limitedNPOT;
|
||||
|
||||
case PackInvert:
|
||||
return m_packInvert;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,11 @@ enum GLFeature {
|
|||
* - GL_CLAMP_TO_BORDER
|
||||
*/
|
||||
LimitedNPOT,
|
||||
|
||||
/**
|
||||
* Set if the extension GL_MESA_pack_invert is present
|
||||
*/
|
||||
PackInvert,
|
||||
};
|
||||
|
||||
enum Driver {
|
||||
|
@ -444,6 +449,7 @@ private:
|
|||
bool m_limitedGLSL: 1;
|
||||
bool m_textureNPOT: 1;
|
||||
bool m_limitedNPOT: 1;
|
||||
bool m_packInvert: 1;
|
||||
bool m_virtualMachine: 1;
|
||||
bool m_preferBufferSubData: 1;
|
||||
OpenGLPlatformInterface m_platformInterface;
|
||||
|
|
|
@ -327,6 +327,19 @@ static GLTexture *copyTexture(GLTexture *texture)
|
|||
return copy;
|
||||
}
|
||||
|
||||
// in-place vertical mirroring
|
||||
static void mirrorVertically(uchar *data, int height, int stride)
|
||||
{
|
||||
const int halfHeight = height / 2;
|
||||
std::vector<uchar> temp(stride);
|
||||
for (int y = 0; y < halfHeight; ++y) {
|
||||
auto cur = &data[y * stride], dest = &data[(height - y - 1) * stride];
|
||||
memcpy(temp.data(), cur, stride);
|
||||
memcpy(cur, dest, stride);
|
||||
memcpy(dest, temp.data(), stride);
|
||||
}
|
||||
}
|
||||
|
||||
void PipeWireStream::recordFrame(GLTexture *frameTexture, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT(!m_stopped);
|
||||
|
@ -383,6 +396,12 @@ void PipeWireStream::recordFrame(GLTexture *frameTexture, const QRegion &damaged
|
|||
|
||||
spa_data->chunk->size = bufferSize;
|
||||
spa_data->chunk->stride = stride;
|
||||
const bool invertNeededAndSupported = frameTexture->isYInverted() && GLPlatform::instance()->supports(PackInvert);
|
||||
GLboolean prev;
|
||||
if (invertNeededAndSupported) {
|
||||
glGetBooleanv(GL_PACK_INVERT_MESA, &prev);
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
|
||||
}
|
||||
|
||||
frameTexture->bind();
|
||||
if (GLPlatform::instance()->isGLES()) {
|
||||
|
@ -392,6 +411,14 @@ void PipeWireStream::recordFrame(GLTexture *frameTexture, const QRegion &damaged
|
|||
} else {
|
||||
glGetTexImage(frameTexture->target(), 0, m_hasAlpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
if (invertNeededAndSupported) {
|
||||
if (!prev) {
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, prev);
|
||||
}
|
||||
} else if (frameTexture->isYInverted()) {
|
||||
mirrorVertically(data, size.height(), stride);
|
||||
}
|
||||
auto cursor = Cursors::self()->currentCursor();
|
||||
if (m_cursor.mode == KWaylandServer::ScreencastV1Interface::Embedded && m_cursor.viewport.contains(cursor->pos())) {
|
||||
QImage dest(data, size.width(), size.height(), QImage::Format_RGBA8888_Premultiplied);
|
||||
|
|
Loading…
Reference in a new issue