libkwineffects: handle GLTexture allocation failures
This is required for properly dealing with GPU resets
This commit is contained in:
parent
bfc8bcb24a
commit
572bc75de4
21 changed files with 165 additions and 103 deletions
|
@ -104,7 +104,10 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
|
||||||
}
|
}
|
||||||
if (enableColormanagement) {
|
if (enableColormanagement) {
|
||||||
if (!m_surface.shadowBuffer) {
|
if (!m_surface.shadowBuffer) {
|
||||||
m_surface.shadowTexture = std::make_shared<GLTexture>(GL_RGBA16F, m_surface.gbmSwapchain->size());
|
m_surface.shadowTexture = GLTexture::allocate(GL_RGBA16F, m_surface.gbmSwapchain->size());
|
||||||
|
if (!m_surface.shadowTexture) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
m_surface.shadowBuffer = std::make_shared<GLFramebuffer>(m_surface.shadowTexture.get());
|
m_surface.shadowBuffer = std::make_shared<GLFramebuffer>(m_surface.shadowTexture.get());
|
||||||
}
|
}
|
||||||
return OutputLayerBeginFrameInfo{
|
return OutputLayerBeginFrameInfo{
|
||||||
|
|
|
@ -205,7 +205,10 @@ std::optional<OutputLayerBeginFrameInfo> X11WindowedEglCursorLayer::beginFrame()
|
||||||
const auto tmp = size().expandedTo(QSize(64, 64));
|
const auto tmp = size().expandedTo(QSize(64, 64));
|
||||||
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
||||||
if (!m_texture || m_texture->size() != bufferSize) {
|
if (!m_texture || m_texture->size() != bufferSize) {
|
||||||
m_texture = std::make_unique<GLTexture>(GL_RGBA8, bufferSize);
|
m_texture = GLTexture::allocate(GL_RGBA8, bufferSize);
|
||||||
|
if (!m_texture) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
|
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libkwineffects/kwineglimagetexture.h"
|
#include "libkwineffects/kwineglimagetexture.h"
|
||||||
|
#include "libkwineffects/kwingltexture_p.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <epoxy/egl.h>
|
#include <epoxy/egl.h>
|
||||||
|
@ -15,18 +16,13 @@
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
EGLImageTexture::EGLImageTexture(::EGLDisplay display, EGLImage image, int internalFormat, const QSize &size)
|
EGLImageTexture::EGLImageTexture(::EGLDisplay display, EGLImage image, uint textureId, int internalFormat, const QSize &size)
|
||||||
: GLTexture(internalFormat, size, 1, true)
|
: GLTexture(textureId, internalFormat, size, 1, true)
|
||||||
, m_image(image)
|
, m_image(image)
|
||||||
, m_display(display)
|
, m_display(display)
|
||||||
{
|
{
|
||||||
if (m_image == EGL_NO_IMAGE_KHR) {
|
d_ptr->m_foreign = false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setContentTransform(TextureTransform::MirrorY);
|
setContentTransform(TextureTransform::MirrorY);
|
||||||
bind();
|
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLImageTexture::~EGLImageTexture()
|
EGLImageTexture::~EGLImageTexture()
|
||||||
|
@ -34,4 +30,20 @@ EGLImageTexture::~EGLImageTexture()
|
||||||
eglDestroyImageKHR(m_display, m_image);
|
eglDestroyImageKHR(m_display, m_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<EGLImageTexture> EGLImageTexture::create(::EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size)
|
||||||
|
{
|
||||||
|
if (image == EGL_NO_IMAGE) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
GLuint texture = 0;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
if (!texture) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return std::make_shared<EGLImageTexture>(display, image, texture, internalFormat, size);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
|
@ -22,10 +22,11 @@ namespace KWin
|
||||||
class KWINGLUTILS_EXPORT EGLImageTexture : public GLTexture
|
class KWINGLUTILS_EXPORT EGLImageTexture : public GLTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EGLImageTexture(::EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size);
|
explicit EGLImageTexture(::EGLDisplay display, EGLImageKHR image, uint textureId, int internalFormat, const QSize &size);
|
||||||
~EGLImageTexture() override;
|
~EGLImageTexture() override;
|
||||||
|
|
||||||
private:
|
static std::shared_ptr<EGLImageTexture> create(::EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size);
|
||||||
|
|
||||||
EGLImageKHR m_image;
|
EGLImageKHR m_image;
|
||||||
::EGLDisplay m_display;
|
::EGLDisplay m_display;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "kwingltexture_p.h"
|
||||||
#include "libkwineffects/kwinconfig.h" // KWIN_HAVE_OPENGL
|
#include "libkwineffects/kwinconfig.h" // KWIN_HAVE_OPENGL
|
||||||
#include "libkwineffects/kwineffects.h"
|
#include "libkwineffects/kwineffects.h"
|
||||||
#include "libkwineffects/kwinglplatform.h"
|
#include "libkwineffects/kwinglplatform.h"
|
||||||
#include "libkwineffects/kwinglutils.h"
|
#include "libkwineffects/kwinglutils.h"
|
||||||
#include "libkwineffects/kwinglutils_funcs.h"
|
#include "libkwineffects/kwinglutils_funcs.h"
|
||||||
|
#include "logging_p.h"
|
||||||
#include "kwingltexture_p.h"
|
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
@ -185,56 +185,7 @@ GLTexture::GLTexture(const QString &fileName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GLTexture::GLTexture(GLenum internalFormat, int width, int height, int levels, bool needsMutability)
|
GLTexture::GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels, bool isImmutable)
|
||||||
: d_ptr(new GLTexturePrivate())
|
|
||||||
{
|
|
||||||
Q_D(GLTexture);
|
|
||||||
|
|
||||||
d->m_target = GL_TEXTURE_2D;
|
|
||||||
d->m_scale.setWidth(1.0 / width);
|
|
||||||
d->m_scale.setHeight(1.0 / height);
|
|
||||||
d->m_size = QSize(width, height);
|
|
||||||
d->m_canUseMipmaps = levels > 1;
|
|
||||||
d->m_mipLevels = levels;
|
|
||||||
d->m_filter = levels > 1 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
|
|
||||||
|
|
||||||
d->updateMatrix();
|
|
||||||
|
|
||||||
create();
|
|
||||||
bind();
|
|
||||||
|
|
||||||
if (!GLPlatform::instance()->isGLES()) {
|
|
||||||
if (d->s_supportsTextureStorage && !needsMutability) {
|
|
||||||
glTexStorage2D(d->m_target, levels, internalFormat, width, height);
|
|
||||||
d->m_immutable = true;
|
|
||||||
} else {
|
|
||||||
glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, levels - 1);
|
|
||||||
glTexImage2D(d->m_target, 0, internalFormat, width, height, 0,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
|
|
||||||
}
|
|
||||||
d->m_internalFormat = internalFormat;
|
|
||||||
} else {
|
|
||||||
// The format parameter in glTexSubImage() must match the internal format
|
|
||||||
// of the texture, so it's important that we allocate the texture with
|
|
||||||
// the format that will be used in update() and clear().
|
|
||||||
const GLenum format = d->s_supportsARGB32 ? GL_BGRA_EXT : GL_RGBA;
|
|
||||||
glTexImage2D(d->m_target, 0, format, width, height, 0,
|
|
||||||
format, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
|
|
||||||
// This is technically not true, but it means that code that calls
|
|
||||||
// internalFormat() won't need to be specialized for GLES2.
|
|
||||||
d->m_internalFormat = GL_RGBA8;
|
|
||||||
}
|
|
||||||
|
|
||||||
unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(GLenum internalFormat, const QSize &size, int levels, bool needsMutability)
|
|
||||||
: GLTexture(internalFormat, size.width(), size.height(), levels, needsMutability)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels)
|
|
||||||
: d_ptr(new GLTexturePrivate())
|
: d_ptr(new GLTexturePrivate())
|
||||||
{
|
{
|
||||||
Q_D(GLTexture);
|
Q_D(GLTexture);
|
||||||
|
@ -248,6 +199,7 @@ GLTexture::GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size,
|
||||||
d->m_mipLevels = levels;
|
d->m_mipLevels = levels;
|
||||||
d->m_filter = levels > 1 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
|
d->m_filter = levels > 1 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
|
||||||
d->m_internalFormat = internalFormat;
|
d->m_internalFormat = internalFormat;
|
||||||
|
d->m_immutable = isImmutable;
|
||||||
|
|
||||||
d->updateMatrix();
|
d->updateMatrix();
|
||||||
}
|
}
|
||||||
|
@ -777,4 +729,42 @@ QImage GLTexture::toImage() const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GLTexture> GLTexture::allocate(GLenum internalFormat, const QSize &size, int levels, bool needsMutability)
|
||||||
|
{
|
||||||
|
GLuint texture = 0;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
if (texture == 0) {
|
||||||
|
qCWarning(LIBKWINGLUTILS, "generating OpenGL texture handle failed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
bool immutable = false;
|
||||||
|
|
||||||
|
if (!GLPlatform::instance()->isGLES()) {
|
||||||
|
if (GLTexturePrivate::s_supportsTextureStorage && !needsMutability) {
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, size.width(), size.height());
|
||||||
|
immutable = true;
|
||||||
|
} else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels - 1);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(), 0,
|
||||||
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The format parameter in glTexSubImage() must match the internal format
|
||||||
|
// of the texture, so it's important that we allocate the texture with
|
||||||
|
// the format that will be used in update() and clear().
|
||||||
|
const GLenum format = GLTexturePrivate::s_supportsARGB32 ? GL_BGRA_EXT : GL_RGBA;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
|
||||||
|
format, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
|
||||||
|
// The internalFormat is technically not correct, but it means that code that calls
|
||||||
|
// internalFormat() won't need to be specialized for GLES2.
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
auto ret = std::make_unique<GLTexture>(texture, internalFormat, size, levels, immutable);
|
||||||
|
ret->d_ptr->m_foreign = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
|
@ -52,8 +52,6 @@ public:
|
||||||
explicit GLTexture(const QImage &image, GLenum target = GL_TEXTURE_2D);
|
explicit GLTexture(const QImage &image, GLenum target = GL_TEXTURE_2D);
|
||||||
explicit GLTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D);
|
explicit GLTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D);
|
||||||
explicit GLTexture(const QString &fileName);
|
explicit GLTexture(const QString &fileName);
|
||||||
GLTexture(GLenum internalFormat, int width, int height, int levels = 1, bool needsMutability = false);
|
|
||||||
explicit GLTexture(GLenum internalFormat, const QSize &size, int levels = 1, bool needsMutability = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the underlying texture object. Returns @c true if the texture has been created
|
* Creates the underlying texture object. Returns @c true if the texture has been created
|
||||||
|
@ -67,7 +65,7 @@ public:
|
||||||
* Management of the underlying texture remains the responsibility of the caller.
|
* Management of the underlying texture remains the responsibility of the caller.
|
||||||
* @since 5.18
|
* @since 5.18
|
||||||
*/
|
*/
|
||||||
explicit GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels = 1);
|
explicit GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels = 1, bool isImmutable = false);
|
||||||
virtual ~GLTexture();
|
virtual ~GLTexture();
|
||||||
|
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
|
@ -158,6 +156,8 @@ public:
|
||||||
*/
|
*/
|
||||||
static bool supportsFormatRG();
|
static bool supportsFormatRG();
|
||||||
|
|
||||||
|
static std::unique_ptr<GLTexture> allocate(GLenum internalFormat, const QSize &size, int levels = 1, bool needsMutability = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const std::unique_ptr<GLTexturePrivate> d_ptr;
|
const std::unique_ptr<GLTexturePrivate> d_ptr;
|
||||||
GLTexture(std::unique_ptr<GLTexturePrivate> &&dd);
|
GLTexture(std::unique_ptr<GLTexturePrivate> &&dd);
|
||||||
|
|
|
@ -97,7 +97,10 @@ void OffscreenData::maybeRender(EffectWindow *window)
|
||||||
QSize textureSize = logicalGeometry.toAlignedRect().size();
|
QSize textureSize = logicalGeometry.toAlignedRect().size();
|
||||||
|
|
||||||
if (!m_texture || m_texture->size() != textureSize) {
|
if (!m_texture || m_texture->size() != textureSize) {
|
||||||
m_texture.reset(new GLTexture(GL_RGBA8, textureSize));
|
m_texture = GLTexture::allocate(GL_RGBA8, textureSize);
|
||||||
|
if (!m_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_texture->setFilter(GL_LINEAR);
|
m_texture->setFilter(GL_LINEAR);
|
||||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
m_fbo.reset(new GLFramebuffer(m_texture.get()));
|
m_fbo.reset(new GLFramebuffer(m_texture.get()));
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -653,9 +653,12 @@ static PlatformCursorImage grabCursorOpenGL()
|
||||||
Cursor *cursor = Cursors::self()->currentCursor();
|
Cursor *cursor = Cursors::self()->currentCursor();
|
||||||
Output *output = workspace()->outputAt(cursor->pos());
|
Output *output = workspace()->outputAt(cursor->pos());
|
||||||
|
|
||||||
GLTexture texture(GL_RGBA8, (cursor->geometry().size() * output->scale()).toSize());
|
const auto texture = GLTexture::allocate(GL_RGBA8, (cursor->geometry().size() * output->scale()).toSize());
|
||||||
texture.setContentTransform(TextureTransform::MirrorY);
|
if (!texture) {
|
||||||
GLFramebuffer framebuffer(&texture);
|
return PlatformCursorImage{};
|
||||||
|
}
|
||||||
|
texture->setContentTransform(TextureTransform::MirrorY);
|
||||||
|
GLFramebuffer framebuffer(texture.get());
|
||||||
RenderTarget renderTarget(&framebuffer);
|
RenderTarget renderTarget(&framebuffer);
|
||||||
|
|
||||||
SceneDelegate delegate(scene, output);
|
SceneDelegate delegate(scene, output);
|
||||||
|
@ -663,7 +666,7 @@ static PlatformCursorImage grabCursorOpenGL()
|
||||||
scene->paint(renderTarget, infiniteRegion());
|
scene->paint(renderTarget, infiniteRegion());
|
||||||
scene->postPaint();
|
scene->postPaint();
|
||||||
|
|
||||||
QImage image = texture.toImage();
|
QImage image = texture->toImage();
|
||||||
image.setDevicePixelRatio(output->scale());
|
image.setDevicePixelRatio(output->scale());
|
||||||
|
|
||||||
return PlatformCursorImage(image, cursor->hotspot());
|
return PlatformCursorImage(image, cursor->hotspot());
|
||||||
|
|
|
@ -208,9 +208,9 @@ std::shared_ptr<GLTexture> EglContext::importDmaBufAsTexture(const DmaBufAttribu
|
||||||
{
|
{
|
||||||
EGLImageKHR image = m_display->importDmaBufAsImage(attributes);
|
EGLImageKHR image = m_display->importDmaBufAsImage(attributes);
|
||||||
if (image != EGL_NO_IMAGE_KHR) {
|
if (image != EGL_NO_IMAGE_KHR) {
|
||||||
return std::make_shared<EGLImageTexture>(m_display->handle(), image, glFormatForDrmFormat(attributes.format), QSize(attributes.width, attributes.height));
|
return EGLImageTexture::create(m_display->handle(), image, glFormatForDrmFormat(attributes.format), QSize(attributes.width, attributes.height));
|
||||||
} else {
|
} else {
|
||||||
qCWarning(KWIN_OPENGL) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString();
|
qCWarning(KWIN_OPENGL) << "Error creating EGLImageKHR: " << getEglErrorString();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,14 +430,17 @@ void ContrastEffect::doContrast(const RenderTarget &renderTarget, const RenderVi
|
||||||
|
|
||||||
// Create a scratch texture and copy the area in the back buffer that we're
|
// Create a scratch texture and copy the area in the back buffer that we're
|
||||||
// going to blur into it
|
// going to blur into it
|
||||||
GLTexture scratch(GL_RGBA8, r.width(), r.height());
|
const auto scratch = GLTexture::allocate(GL_RGBA8, r.size().toSize());
|
||||||
scratch.setFilter(GL_LINEAR);
|
if (!scratch) {
|
||||||
scratch.setWrapMode(GL_CLAMP_TO_EDGE);
|
return;
|
||||||
scratch.bind();
|
}
|
||||||
|
scratch->setFilter(GL_LINEAR);
|
||||||
|
scratch->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
scratch->bind();
|
||||||
|
|
||||||
const QRectF sg = viewport.mapToRenderTarget(viewport.renderRect());
|
const QRectF sg = viewport.mapToRenderTarget(viewport.renderRect());
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (r.x() - sg.x()), (sg.height() - (r.y() - sg.y() + r.height())),
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (r.x() - sg.x()), (sg.height() - (r.y() - sg.y() + r.height())),
|
||||||
scratch.width(), scratch.height());
|
scratch->width(), scratch->height());
|
||||||
|
|
||||||
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
|
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
|
||||||
|
|
||||||
|
@ -465,7 +468,7 @@ void ContrastEffect::doContrast(const RenderTarget &renderTarget, const RenderVi
|
||||||
|
|
||||||
vbo->draw(GL_TRIANGLES, 0, actualShape.rectCount() * 6);
|
vbo->draw(GL_TRIANGLES, 0, actualShape.rectCount() * 6);
|
||||||
|
|
||||||
scratch.unbind();
|
scratch->unbind();
|
||||||
|
|
||||||
vbo->unbindArrays();
|
vbo->unbindArrays();
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ bool BlurEffect::updateTexture(EffectScreen *screen, const RenderTarget &renderT
|
||||||
data.renderTargetTextures.reserve(m_downSampleIterations + 2);
|
data.renderTargetTextures.reserve(m_downSampleIterations + 2);
|
||||||
|
|
||||||
for (int i = 0; i <= m_downSampleIterations; i++) {
|
for (int i = 0; i <= m_downSampleIterations; i++) {
|
||||||
data.renderTargetTextures.push_back(std::make_unique<GLTexture>(textureFormat, screenSize / (1 << i)));
|
data.renderTargetTextures.push_back(GLTexture::allocate(textureFormat, screenSize / (1 << i)));
|
||||||
data.renderTargetTextures.back()->setFilter(GL_LINEAR);
|
data.renderTargetTextures.back()->setFilter(GL_LINEAR);
|
||||||
data.renderTargetTextures.back()->setWrapMode(GL_CLAMP_TO_EDGE);
|
data.renderTargetTextures.back()->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ bool BlurEffect::updateTexture(EffectScreen *screen, const RenderTarget &renderT
|
||||||
}
|
}
|
||||||
|
|
||||||
// This last set is used as a temporary helper texture
|
// This last set is used as a temporary helper texture
|
||||||
data.renderTargetTextures.push_back(std::make_unique<GLTexture>(textureFormat, screenSize));
|
data.renderTargetTextures.push_back(GLTexture::allocate(textureFormat, screenSize));
|
||||||
data.renderTargetTextures.back()->setFilter(GL_LINEAR);
|
data.renderTargetTextures.back()->setFilter(GL_LINEAR);
|
||||||
data.renderTargetTextures.back()->setWrapMode(GL_CLAMP_TO_EDGE);
|
data.renderTargetTextures.back()->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,10 @@ void MagnifierEffect::zoomIn()
|
||||||
}
|
}
|
||||||
if (effects->isOpenGLCompositing() && !m_texture) {
|
if (effects->isOpenGLCompositing() && !m_texture) {
|
||||||
effects->makeOpenGLContextCurrent();
|
effects->makeOpenGLContextCurrent();
|
||||||
m_texture = std::make_unique<GLTexture>(GL_RGBA8, m_magnifierSize.width(), m_magnifierSize.height());
|
m_texture = GLTexture::allocate(GL_RGBA8, m_magnifierSize);
|
||||||
|
if (!m_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_texture->setContentTransform(TextureTransforms());
|
m_texture->setContentTransform(TextureTransforms());
|
||||||
m_fbo = std::make_unique<GLFramebuffer>(m_texture.get());
|
m_fbo = std::make_unique<GLFramebuffer>(m_texture.get());
|
||||||
}
|
}
|
||||||
|
@ -238,7 +241,10 @@ void MagnifierEffect::toggle()
|
||||||
}
|
}
|
||||||
if (effects->isOpenGLCompositing() && !m_texture) {
|
if (effects->isOpenGLCompositing() && !m_texture) {
|
||||||
effects->makeOpenGLContextCurrent();
|
effects->makeOpenGLContextCurrent();
|
||||||
m_texture = std::make_unique<GLTexture>(GL_RGBA8, m_magnifierSize.width(), m_magnifierSize.height());
|
m_texture = GLTexture::allocate(GL_RGBA8, m_magnifierSize);
|
||||||
|
if (!m_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_texture->setContentTransform(TextureTransforms());
|
m_texture->setContentTransform(TextureTransforms());
|
||||||
m_fbo = std::make_unique<GLFramebuffer>(m_texture.get());
|
m_fbo = std::make_unique<GLFramebuffer>(m_texture.get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,10 @@ std::chrono::nanoseconds RegionScreenCastSource::clock() const
|
||||||
void RegionScreenCastSource::ensureTexture()
|
void RegionScreenCastSource::ensureTexture()
|
||||||
{
|
{
|
||||||
if (!m_renderedTexture) {
|
if (!m_renderedTexture) {
|
||||||
m_renderedTexture.reset(new GLTexture(GL_RGBA8, textureSize()));
|
m_renderedTexture = GLTexture::allocate(GL_RGBA8, textureSize());
|
||||||
|
if (!m_renderedTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_target.reset(new GLFramebuffer(m_renderedTexture.get()));
|
m_target.reset(new GLFramebuffer(m_renderedTexture.get()));
|
||||||
const auto allOutputs = workspace()->outputs();
|
const auto allOutputs = workspace()->outputs();
|
||||||
for (auto output : allOutputs) {
|
for (auto output : allOutputs) {
|
||||||
|
|
|
@ -83,8 +83,11 @@ static void grabTexture(GLTexture *texture, spa_data *spa, spa_video_format form
|
||||||
constexpr auto everythingExceptY = TextureTransforms() | TextureTransform::MirrorX | TextureTransform::Rotate90 | TextureTransform::Rotate180 | TextureTransform::Rotate270;
|
constexpr auto everythingExceptY = TextureTransforms() | TextureTransform::MirrorX | TextureTransform::Rotate90 | TextureTransform::Rotate180 | TextureTransform::Rotate270;
|
||||||
if (texture->contentTransforms() & everythingExceptY) {
|
if (texture->contentTransforms() & everythingExceptY) {
|
||||||
// need to transform the texture to a usable transformation first
|
// need to transform the texture to a usable transformation first
|
||||||
GLTexture backingTexture(GL_RGBA8, size);
|
const auto backingTexture = GLTexture::allocate(GL_RGBA8, size);
|
||||||
GLFramebuffer fbo(&backingTexture);
|
if (!backingTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLFramebuffer fbo(backingTexture.get());
|
||||||
|
|
||||||
ShaderBinder shaderBinder(ShaderTrait::MapTexture);
|
ShaderBinder shaderBinder(ShaderTrait::MapTexture);
|
||||||
QMatrix4x4 projectionMatrix;
|
QMatrix4x4 projectionMatrix;
|
||||||
|
@ -94,7 +97,7 @@ static void grabTexture(GLTexture *texture, spa_data *spa, spa_video_format form
|
||||||
GLFramebuffer::pushFramebuffer(&fbo);
|
GLFramebuffer::pushFramebuffer(&fbo);
|
||||||
texture->render(size, 1);
|
texture->render(size, 1);
|
||||||
GLFramebuffer::popFramebuffer();
|
GLFramebuffer::popFramebuffer();
|
||||||
doGrabTexture(&backingTexture, spa, format);
|
doGrabTexture(backingTexture.get(), spa, format);
|
||||||
} else {
|
} else {
|
||||||
doGrabTexture(texture, spa, format);
|
doGrabTexture(texture, spa, format);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,14 @@ QSize WindowScreenCastSource::textureSize() const
|
||||||
|
|
||||||
void WindowScreenCastSource::render(spa_data *spa, spa_video_format format)
|
void WindowScreenCastSource::render(spa_data *spa, spa_video_format format)
|
||||||
{
|
{
|
||||||
GLTexture offscreenTexture(hasAlphaChannel() ? GL_RGBA8 : GL_RGB8, textureSize());
|
const auto offscreenTexture = GLTexture::allocate(hasAlphaChannel() ? GL_RGBA8 : GL_RGB8, textureSize());
|
||||||
GLFramebuffer offscreenTarget(&offscreenTexture);
|
if (!offscreenTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLFramebuffer offscreenTarget(offscreenTexture.get());
|
||||||
|
|
||||||
render(&offscreenTarget);
|
render(&offscreenTarget);
|
||||||
grabTexture(&offscreenTexture, spa, format);
|
grabTexture(offscreenTexture.get(), spa, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowScreenCastSource::render(GLFramebuffer *target)
|
void WindowScreenCastSource::render(GLFramebuffer *target)
|
||||||
|
|
|
@ -240,7 +240,10 @@ void ScreenShotEffect::takeScreenShot(ScreenShotWindowData *screenshot)
|
||||||
std::unique_ptr<GLTexture> offscreenTexture;
|
std::unique_ptr<GLTexture> offscreenTexture;
|
||||||
std::unique_ptr<GLFramebuffer> target;
|
std::unique_ptr<GLFramebuffer> target;
|
||||||
if (effects->isOpenGLCompositing()) {
|
if (effects->isOpenGLCompositing()) {
|
||||||
offscreenTexture.reset(new GLTexture(GL_RGBA8, QSizeF(geometry.size() * devicePixelRatio).toSize()));
|
offscreenTexture = GLTexture::allocate(GL_RGBA8, QSizeF(geometry.size() * devicePixelRatio).toSize());
|
||||||
|
if (!offscreenTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
offscreenTexture->setFilter(GL_LINEAR);
|
offscreenTexture->setFilter(GL_LINEAR);
|
||||||
offscreenTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
offscreenTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
target.reset(new GLFramebuffer(offscreenTexture.get()));
|
target.reset(new GLFramebuffer(offscreenTexture.get()));
|
||||||
|
@ -364,14 +367,17 @@ QImage ScreenShotEffect::blitScreenshot(const RenderTarget &renderTarget, const
|
||||||
image = QImage(nativeSize, QImage::Format_ARGB32);
|
image = QImage(nativeSize, QImage::Format_ARGB32);
|
||||||
|
|
||||||
if (GLFramebuffer::blitSupported() && !GLPlatform::instance()->isGLES()) {
|
if (GLFramebuffer::blitSupported() && !GLPlatform::instance()->isGLES()) {
|
||||||
GLTexture texture(GL_RGBA8, nativeSize.width(), nativeSize.height());
|
const auto texture = GLTexture::allocate(GL_RGBA8, nativeSize);
|
||||||
GLFramebuffer target(&texture);
|
if (!texture) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
GLFramebuffer target(texture.get());
|
||||||
target.blitFromFramebuffer(viewport.mapToRenderTarget(geometry));
|
target.blitFromFramebuffer(viewport.mapToRenderTarget(geometry));
|
||||||
// copy content from framebuffer into image
|
// copy content from framebuffer into image
|
||||||
texture.bind();
|
texture->bind();
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
static_cast<GLvoid *>(image.bits()));
|
static_cast<GLvoid *>(image.bits()));
|
||||||
texture.unbind();
|
texture->unbind();
|
||||||
} else {
|
} else {
|
||||||
glReadPixels(0, 0, nativeSize.width(), nativeSize.height(), GL_RGBA,
|
glReadPixels(0, 0, nativeSize.width(), nativeSize.height(), GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, static_cast<GLvoid *>(image.bits()));
|
GL_UNSIGNED_BYTE, static_cast<GLvoid *>(image.bits()));
|
||||||
|
|
|
@ -84,7 +84,11 @@ void ScreenTransformEffect::addScreen(EffectScreen *screen)
|
||||||
auto &state = m_states[screen];
|
auto &state = m_states[screen];
|
||||||
state.m_oldTransform = screen->transform();
|
state.m_oldTransform = screen->transform();
|
||||||
state.m_oldGeometry = screen->geometry();
|
state.m_oldGeometry = screen->geometry();
|
||||||
state.m_prev.texture.reset(new GLTexture(GL_RGBA8, screen->geometry().size() * screen->devicePixelRatio()));
|
state.m_prev.texture = GLTexture::allocate(GL_RGBA8, screen->geometry().size() * screen->devicePixelRatio());
|
||||||
|
if (!state.m_prev.texture) {
|
||||||
|
m_states.remove(screen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
state.m_prev.framebuffer.reset(new GLFramebuffer(state.m_prev.texture.get()));
|
state.m_prev.framebuffer.reset(new GLFramebuffer(state.m_prev.texture.get()));
|
||||||
|
|
||||||
// Rendering the current scene into a texture
|
// Rendering the current scene into a texture
|
||||||
|
@ -193,7 +197,11 @@ void ScreenTransformEffect::paintScreen(const RenderTarget &renderTarget, const
|
||||||
// Render the screen in an offscreen texture.
|
// Render the screen in an offscreen texture.
|
||||||
const QSize nativeSize = screen->geometry().size() * screen->devicePixelRatio();
|
const QSize nativeSize = screen->geometry().size() * screen->devicePixelRatio();
|
||||||
if (!it->m_current.texture || it->m_current.texture->size() != nativeSize) {
|
if (!it->m_current.texture || it->m_current.texture->size() != nativeSize) {
|
||||||
it->m_current.texture.reset(new GLTexture(GL_RGBA8, nativeSize));
|
it->m_current.texture = GLTexture::allocate(GL_RGBA8, nativeSize);
|
||||||
|
if (!it->m_current.texture) {
|
||||||
|
m_states.remove(screen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
it->m_current.framebuffer.reset(new GLFramebuffer(it->m_current.texture.get()));
|
it->m_current.framebuffer.reset(new GLFramebuffer(it->m_current.texture.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,10 @@ ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &r
|
||||||
|
|
||||||
const GLenum textureFormat = renderTarget.colorDescription() == ColorDescription::sRGB ? GL_RGBA8 : GL_RGBA16F;
|
const GLenum textureFormat = renderTarget.colorDescription() == ColorDescription::sRGB ? GL_RGBA8 : GL_RGBA16F;
|
||||||
if (!data.texture || data.texture->size() != nativeSize || data.texture->internalFormat() != textureFormat) {
|
if (!data.texture || data.texture->size() != nativeSize || data.texture->internalFormat() != textureFormat) {
|
||||||
data.texture.reset(new GLTexture(textureFormat, nativeSize));
|
data.texture = GLTexture::allocate(textureFormat, nativeSize);
|
||||||
|
if (!data.texture) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
data.texture->setFilter(GL_LINEAR);
|
data.texture->setFilter(GL_LINEAR);
|
||||||
data.texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
data.texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
data.framebuffer = std::make_unique<GLFramebuffer>(data.texture.get());
|
data.framebuffer = std::make_unique<GLFramebuffer>(data.texture.get());
|
||||||
|
@ -278,6 +281,9 @@ ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &r
|
||||||
void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, EffectScreen *screen)
|
void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, EffectScreen *screen)
|
||||||
{
|
{
|
||||||
OffscreenData *offscreenData = ensureOffscreenData(renderTarget, viewport, screen);
|
OffscreenData *offscreenData = ensureOffscreenData(renderTarget, viewport, screen);
|
||||||
|
if (!offscreenData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Render the scene in an offscreen texture and then upscale it.
|
// Render the scene in an offscreen texture and then upscale it.
|
||||||
RenderTarget offscreenRenderTarget(offscreenData->framebuffer.get(), renderTarget.colorDescription());
|
RenderTarget offscreenRenderTarget(offscreenData->framebuffer.get(), renderTarget.colorDescription());
|
||||||
|
|
|
@ -42,7 +42,10 @@ void CursorDelegateOpenGL::paint(const RenderTarget &renderTarget, const QRegion
|
||||||
// Render the cursor scene in an offscreen render target.
|
// Render the cursor scene in an offscreen render target.
|
||||||
const QSize bufferSize = (Cursors::self()->currentCursor()->rect().size() * scale).toSize();
|
const QSize bufferSize = (Cursors::self()->currentCursor()->rect().size() * scale).toSize();
|
||||||
if (!m_texture || m_texture->size() != bufferSize) {
|
if (!m_texture || m_texture->size() != bufferSize) {
|
||||||
m_texture = std::make_unique<GLTexture>(renderTarget.framebuffer()->colorAttachment()->internalFormat(), bufferSize);
|
m_texture = GLTexture::allocate(renderTarget.framebuffer()->colorAttachment()->internalFormat(), bufferSize);
|
||||||
|
if (!m_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
|
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,7 @@ void SceneOpenGLDecorationRenderer::renderPart(const QRect &rect, const QRect &p
|
||||||
const QPoint &textureOffset,
|
const QPoint &textureOffset,
|
||||||
qreal devicePixelRatio, bool rotated)
|
qreal devicePixelRatio, bool rotated)
|
||||||
{
|
{
|
||||||
if (!rect.isValid()) {
|
if (!rect.isValid() || !m_texture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We allow partial decoration updates and it might just so happen that the
|
// We allow partial decoration updates and it might just so happen that the
|
||||||
|
@ -457,7 +457,10 @@ void SceneOpenGLDecorationRenderer::resizeTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!size.isEmpty()) {
|
if (!size.isEmpty()) {
|
||||||
m_texture.reset(new GLTexture(GL_RGBA8, size.width(), size.height()));
|
m_texture = GLTexture::allocate(GL_RGBA8, size);
|
||||||
|
if (!m_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_texture->setContentTransform(TextureTransform::MirrorY);
|
m_texture->setContentTransform(TextureTransform::MirrorY);
|
||||||
m_texture->setFilter(GL_LINEAR);
|
m_texture->setFilter(GL_LINEAR);
|
||||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
|
|
@ -380,7 +380,10 @@ void WindowThumbnailItem::updateOffscreenTexture()
|
||||||
textureSize *= m_devicePixelRatio;
|
textureSize *= m_devicePixelRatio;
|
||||||
|
|
||||||
if (!m_offscreenTexture || m_offscreenTexture->size() != textureSize) {
|
if (!m_offscreenTexture || m_offscreenTexture->size() != textureSize) {
|
||||||
m_offscreenTexture.reset(new GLTexture(GL_RGBA8, textureSize));
|
m_offscreenTexture = GLTexture::allocate(GL_RGBA8, textureSize);
|
||||||
|
if (!m_offscreenTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_offscreenTexture->setFilter(GL_LINEAR);
|
m_offscreenTexture->setFilter(GL_LINEAR);
|
||||||
m_offscreenTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
m_offscreenTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
m_offscreenTarget.reset(new GLFramebuffer(m_offscreenTexture.get()));
|
m_offscreenTarget.reset(new GLFramebuffer(m_offscreenTexture.get()));
|
||||||
|
|
Loading…
Reference in a new issue