libkwineffects: handle GLTexture upload failures
This is required for properly dealing with GPU resets
This commit is contained in:
parent
572bc75de4
commit
16fb2848ed
14 changed files with 135 additions and 141 deletions
|
@ -94,97 +94,6 @@ GLTexture::GLTexture(std::unique_ptr<GLTexturePrivate> &&dd)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GLTexture::GLTexture(const QImage &image, GLenum target)
|
|
||||||
: d_ptr(new GLTexturePrivate())
|
|
||||||
{
|
|
||||||
Q_D(GLTexture);
|
|
||||||
|
|
||||||
if (image.isNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_target = target;
|
|
||||||
|
|
||||||
if (d->m_target != GL_TEXTURE_RECTANGLE_ARB) {
|
|
||||||
d->m_scale.setWidth(1.0 / image.width());
|
|
||||||
d->m_scale.setHeight(1.0 / image.height());
|
|
||||||
} else {
|
|
||||||
d->m_scale.setWidth(1.0);
|
|
||||||
d->m_scale.setHeight(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_size = image.size();
|
|
||||||
setContentTransform(TextureTransform::MirrorY);
|
|
||||||
d->m_canUseMipmaps = false;
|
|
||||||
d->m_mipLevels = 1;
|
|
||||||
|
|
||||||
d->updateMatrix();
|
|
||||||
|
|
||||||
const bool created = create();
|
|
||||||
Q_ASSERT(created);
|
|
||||||
bind();
|
|
||||||
|
|
||||||
if (!GLPlatform::instance()->isGLES()) {
|
|
||||||
QImage im;
|
|
||||||
GLenum internalFormat;
|
|
||||||
GLenum format;
|
|
||||||
GLenum type;
|
|
||||||
|
|
||||||
const QImage::Format index = image.format();
|
|
||||||
|
|
||||||
if (index < sizeof(formatTable) / sizeof(formatTable[0]) && formatTable[index].internalFormat
|
|
||||||
&& !(formatTable[index].type == GL_UNSIGNED_SHORT && !d->s_supportsTexture16Bit)) {
|
|
||||||
internalFormat = formatTable[index].internalFormat;
|
|
||||||
format = formatTable[index].format;
|
|
||||||
type = formatTable[index].type;
|
|
||||||
im = image;
|
|
||||||
} else {
|
|
||||||
im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
|
||||||
internalFormat = GL_RGBA8;
|
|
||||||
format = GL_BGRA;
|
|
||||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_internalFormat = internalFormat;
|
|
||||||
|
|
||||||
if (d->s_supportsTextureStorage) {
|
|
||||||
glTexStorage2D(d->m_target, 1, internalFormat, im.width(), im.height());
|
|
||||||
glTexSubImage2D(d->m_target, 0, 0, 0, im.width(), im.height(),
|
|
||||||
format, type, im.constBits());
|
|
||||||
d->m_immutable = true;
|
|
||||||
} else {
|
|
||||||
glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, d->m_mipLevels - 1);
|
|
||||||
glTexImage2D(d->m_target, 0, internalFormat, im.width(), im.height(), 0,
|
|
||||||
format, type, im.constBits());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d->m_internalFormat = GL_RGBA8;
|
|
||||||
|
|
||||||
if (d->s_supportsARGB32) {
|
|
||||||
const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
|
||||||
glTexImage2D(d->m_target, 0, GL_BGRA_EXT, im.width(), im.height(),
|
|
||||||
0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.constBits());
|
|
||||||
} else {
|
|
||||||
const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
|
|
||||||
glTexImage2D(d->m_target, 0, GL_RGBA, im.width(), im.height(),
|
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unbind();
|
|
||||||
setFilter(GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(const QPixmap &pixmap, GLenum target)
|
|
||||||
: GLTexture(pixmap.toImage(), target)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(const QString &fileName)
|
|
||||||
: GLTexture(QImage(fileName))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels, bool isImmutable)
|
GLTexture::GLTexture(GLuint textureId, GLenum internalFormat, const QSize &size, int levels, bool isImmutable)
|
||||||
: d_ptr(new GLTexturePrivate())
|
: d_ptr(new GLTexturePrivate())
|
||||||
{
|
{
|
||||||
|
@ -767,4 +676,74 @@ std::unique_ptr<GLTexture> GLTexture::allocate(GLenum internalFormat, const QSiz
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GLTexture> GLTexture::upload(const QImage &image)
|
||||||
|
{
|
||||||
|
if (image.isNull()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
GLuint texture = 0;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
if (texture == 0) {
|
||||||
|
qCWarning(LIBKWINGLUTILS, "generating OpenGL texture handle failed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
GLenum internalFormat;
|
||||||
|
bool immutable = false;
|
||||||
|
if (!GLPlatform::instance()->isGLES()) {
|
||||||
|
QImage im;
|
||||||
|
GLenum format;
|
||||||
|
GLenum type;
|
||||||
|
|
||||||
|
const QImage::Format index = image.format();
|
||||||
|
|
||||||
|
if (index < sizeof(formatTable) / sizeof(formatTable[0]) && formatTable[index].internalFormat
|
||||||
|
&& !(formatTable[index].type == GL_UNSIGNED_SHORT && !GLTexturePrivate::s_supportsTexture16Bit)) {
|
||||||
|
internalFormat = formatTable[index].internalFormat;
|
||||||
|
format = formatTable[index].format;
|
||||||
|
type = formatTable[index].type;
|
||||||
|
im = image;
|
||||||
|
} else {
|
||||||
|
im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||||
|
internalFormat = GL_RGBA8;
|
||||||
|
format = GL_BGRA;
|
||||||
|
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GLTexturePrivate::s_supportsTextureStorage) {
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, im.width(), im.height());
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, im.width(), im.height(),
|
||||||
|
format, type, im.constBits());
|
||||||
|
immutable = true;
|
||||||
|
} else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, im.width(), im.height(), 0,
|
||||||
|
format, type, im.constBits());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
internalFormat = GL_RGBA8;
|
||||||
|
|
||||||
|
if (GLTexturePrivate::s_supportsARGB32) {
|
||||||
|
const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, im.width(), im.height(),
|
||||||
|
0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.constBits());
|
||||||
|
} else {
|
||||||
|
const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(),
|
||||||
|
0, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
auto ret = std::make_unique<GLTexture>(texture, internalFormat, image.size(), 1, immutable);
|
||||||
|
ret->setContentTransform(TextureTransform::MirrorY);
|
||||||
|
ret->d_ptr->m_foreign = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GLTexture> GLTexture::upload(const QPixmap &pixmap)
|
||||||
|
{
|
||||||
|
return upload(pixmap.toImage());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
|
@ -49,9 +49,6 @@ class KWINGLUTILS_EXPORT GLTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GLTexture(GLenum target);
|
explicit GLTexture(GLenum target);
|
||||||
explicit GLTexture(const QImage &image, GLenum target = GL_TEXTURE_2D);
|
|
||||||
explicit GLTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D);
|
|
||||||
explicit GLTexture(const QString &fileName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -157,6 +154,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);
|
static std::unique_ptr<GLTexture> allocate(GLenum internalFormat, const QSize &size, int levels = 1, bool needsMutability = false);
|
||||||
|
static std::unique_ptr<GLTexture> upload(const QImage &image);
|
||||||
|
static std::unique_ptr<GLTexture> upload(const QPixmap &pixmap);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const std::unique_ptr<GLTexturePrivate> d_ptr;
|
const std::unique_ptr<GLTexturePrivate> d_ptr;
|
||||||
|
|
|
@ -407,10 +407,7 @@ void OffscreenQuickView::hide()
|
||||||
GLTexture *OffscreenQuickView::bufferAsTexture()
|
GLTexture *OffscreenQuickView::bufferAsTexture()
|
||||||
{
|
{
|
||||||
if (d->m_useBlit) {
|
if (d->m_useBlit) {
|
||||||
if (d->m_image.isNull()) {
|
d->m_textureExport = GLTexture::upload(d->m_image);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
d->m_textureExport.reset(new GLTexture(d->m_image));
|
|
||||||
} else {
|
} else {
|
||||||
if (!d->m_fbo) {
|
if (!d->m_fbo) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -77,7 +77,7 @@ bool BasicEGLSurfaceTextureInternal::updateFromImage(const QRegion ®ion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_texture) {
|
if (!m_texture) {
|
||||||
m_texture.reset(new GLTexture(image));
|
m_texture = GLTexture::upload(image);
|
||||||
} else {
|
} else {
|
||||||
const QRegion nativeRegion = scale(region, image.devicePixelRatio());
|
const QRegion nativeRegion = scale(region, image.devicePixelRatio());
|
||||||
for (const QRect &rect : nativeRegion) {
|
for (const QRect &rect : nativeRegion) {
|
||||||
|
@ -85,7 +85,7 @@ bool BasicEGLSurfaceTextureInternal::updateFromImage(const QRegion ®ion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return m_texture != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
|
@ -60,12 +60,10 @@ void BasicEGLSurfaceTextureWayland::update(const QRegion ®ion)
|
||||||
|
|
||||||
bool BasicEGLSurfaceTextureWayland::loadShmTexture(KWaylandServer::ShmClientBuffer *buffer)
|
bool BasicEGLSurfaceTextureWayland::loadShmTexture(KWaylandServer::ShmClientBuffer *buffer)
|
||||||
{
|
{
|
||||||
const QImage &image = buffer->data();
|
m_texture = GLTexture::upload(buffer->data());
|
||||||
if (Q_UNLIKELY(image.isNull())) {
|
if (!m_texture) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_texture.reset(new GLTexture(image));
|
|
||||||
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_texture->setContentTransform(TextureTransform::MirrorY);
|
m_texture->setContentTransform(TextureTransform::MirrorY);
|
||||||
|
|
|
@ -691,7 +691,10 @@ void BlurEffect::generateNoiseTexture()
|
||||||
// The noise texture looks distorted when not scaled with integer
|
// The noise texture looks distorted when not scaled with integer
|
||||||
noiseImage = noiseImage.scaled(noiseImage.size() * m_scalingFactor);
|
noiseImage = noiseImage.scaled(noiseImage.size() * m_scalingFactor);
|
||||||
|
|
||||||
m_noiseTexture.reset(new GLTexture(noiseImage));
|
m_noiseTexture = GLTexture::upload(noiseImage);
|
||||||
|
if (!m_noiseTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_noiseTexture->setFilter(GL_NEAREST);
|
m_noiseTexture->setFilter(GL_NEAREST);
|
||||||
m_noiseTexture->setWrapMode(GL_REPEAT);
|
m_noiseTexture->setWrapMode(GL_REPEAT);
|
||||||
}
|
}
|
||||||
|
@ -833,6 +836,9 @@ void BlurEffect::applyNoise(const ScreenData &data, const RenderTarget &renderTa
|
||||||
{
|
{
|
||||||
if (!m_noiseTexture) {
|
if (!m_noiseTexture) {
|
||||||
generateNoiseTexture();
|
generateNoiseTexture();
|
||||||
|
if (!m_noiseTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_shader->bind(BlurShader::NoiseSampleType);
|
m_shader->bind(BlurShader::NoiseSampleType);
|
||||||
|
|
|
@ -551,7 +551,7 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
|
||||||
if (cursorImage.isNull()) {
|
if (cursorImage.isNull()) {
|
||||||
m_cursor.texture = nullptr;
|
m_cursor.texture = nullptr;
|
||||||
} else {
|
} else {
|
||||||
m_cursor.texture = std::make_unique<GLTexture>(cursorImage.image());
|
m_cursor.texture = GLTexture::upload(cursorImage.image());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_cursor.texture) {
|
if (m_cursor.texture) {
|
||||||
|
|
|
@ -79,6 +79,9 @@ void ScreenEdgeEffect::paintScreen(const RenderTarget &renderTarget, const Rende
|
||||||
}
|
}
|
||||||
if (effects->isOpenGLCompositing()) {
|
if (effects->isOpenGLCompositing()) {
|
||||||
GLTexture *texture = glow->texture.get();
|
GLTexture *texture = glow->texture.get();
|
||||||
|
if (!texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::TransformColorspace);
|
ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::TransformColorspace);
|
||||||
|
@ -92,10 +95,10 @@ void ScreenEdgeEffect::paintScreen(const RenderTarget &renderTarget, const Rende
|
||||||
texture->render(glow->geometry.size(), scale);
|
texture->render(glow->geometry.size(), scale);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
} else if (effects->compositingType() == QPainterCompositing) {
|
} else if (effects->compositingType() == QPainterCompositing) {
|
||||||
QImage tmp(glow->image->size(), QImage::Format_ARGB32_Premultiplied);
|
QImage tmp(glow->image.size(), QImage::Format_ARGB32_Premultiplied);
|
||||||
tmp.fill(Qt::transparent);
|
tmp.fill(Qt::transparent);
|
||||||
QPainter p(&tmp);
|
QPainter p(&tmp);
|
||||||
p.drawImage(0, 0, *glow->image.get());
|
p.drawImage(0, 0, glow->image);
|
||||||
QColor color(Qt::transparent);
|
QColor color(Qt::transparent);
|
||||||
color.setAlphaF(opacity);
|
color.setAlphaF(opacity);
|
||||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||||
|
@ -140,9 +143,9 @@ void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, cons
|
||||||
effects->addRepaint(glow->geometry);
|
effects->addRepaint(glow->geometry);
|
||||||
if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) {
|
if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) {
|
||||||
if (effects->isOpenGLCompositing()) {
|
if (effects->isOpenGLCompositing()) {
|
||||||
glow->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
|
||||||
} else if (effects->compositingType() == QPainterCompositing) {
|
} else if (effects->compositingType() == QPainterCompositing) {
|
||||||
glow->image.reset(createEdgeGlow<QImage>(border, geometry.size()));
|
glow->image = createEdgeGlow(border, geometry.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,25 +175,23 @@ std::unique_ptr<Glow> ScreenEdgeEffect::createGlow(ElectricBorder border, qreal
|
||||||
if (effects->isOpenGLCompositing()) {
|
if (effects->isOpenGLCompositing()) {
|
||||||
effects->makeOpenGLContextCurrent();
|
effects->makeOpenGLContextCurrent();
|
||||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||||
glow->texture.reset(createCornerGlow<GLTexture>(border));
|
glow->texture = GLTexture::upload(createCornerGlow(border));
|
||||||
} else {
|
} else {
|
||||||
glow->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
|
||||||
}
|
|
||||||
if (glow->texture) {
|
|
||||||
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
|
||||||
}
|
}
|
||||||
if (!glow->texture) {
|
if (!glow->texture) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
} else if (effects->compositingType() == QPainterCompositing) {
|
} else if (effects->compositingType() == QPainterCompositing) {
|
||||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||||
glow->image.reset(createCornerGlow<QImage>(border));
|
glow->image = createCornerGlow(border);
|
||||||
glow->pictureSize = cornerGlowSize(border);
|
glow->pictureSize = cornerGlowSize(border);
|
||||||
} else {
|
} else {
|
||||||
glow->image.reset(createEdgeGlow<QImage>(border, geometry.size()));
|
glow->image = createEdgeGlow(border, geometry.size());
|
||||||
glow->pictureSize = geometry.size();
|
glow->pictureSize = geometry.size();
|
||||||
}
|
}
|
||||||
if (!glow->image) {
|
if (glow->image.isNull()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,22 +199,21 @@ std::unique_ptr<Glow> ScreenEdgeEffect::createGlow(ElectricBorder border, qreal
|
||||||
return glow;
|
return glow;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
QImage ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
||||||
T *ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
|
||||||
{
|
{
|
||||||
ensureGlowSvg();
|
ensureGlowSvg();
|
||||||
|
|
||||||
switch (border) {
|
switch (border) {
|
||||||
case ElectricTopLeft:
|
case ElectricTopLeft:
|
||||||
return new T(m_glow->pixmap(QStringLiteral("bottomright")).toImage());
|
return m_glow->pixmap(QStringLiteral("bottomright")).toImage();
|
||||||
case ElectricTopRight:
|
case ElectricTopRight:
|
||||||
return new T(m_glow->pixmap(QStringLiteral("bottomleft")).toImage());
|
return m_glow->pixmap(QStringLiteral("bottomleft")).toImage();
|
||||||
case ElectricBottomRight:
|
case ElectricBottomRight:
|
||||||
return new T(m_glow->pixmap(QStringLiteral("topleft")).toImage());
|
return m_glow->pixmap(QStringLiteral("topleft")).toImage();
|
||||||
case ElectricBottomLeft:
|
case ElectricBottomLeft:
|
||||||
return new T(m_glow->pixmap(QStringLiteral("topright")).toImage());
|
return m_glow->pixmap(QStringLiteral("topright")).toImage();
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return QImage{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,8 +235,7 @@ QSize ScreenEdgeEffect::cornerGlowSize(ElectricBorder border)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
QImage ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||||
T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
|
||||||
{
|
{
|
||||||
ensureGlowSvg();
|
ensureGlowSvg();
|
||||||
|
|
||||||
|
@ -268,7 +267,7 @@ T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||||
pixmapPosition = QPoint(size.width() - c.width(), 0);
|
pixmapPosition = QPoint(size.width() - c.width(), 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return QImage{};
|
||||||
}
|
}
|
||||||
QPixmap image(size);
|
QPixmap image(size);
|
||||||
image.fill(Qt::transparent);
|
image.fill(Qt::transparent);
|
||||||
|
@ -294,7 +293,7 @@ T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||||
p.drawPixmap(QPoint(pixmapPosition.x(), size.height() - r.height()), r);
|
p.drawPixmap(QPoint(pixmapPosition.x(), size.height() - r.height()), r);
|
||||||
}
|
}
|
||||||
p.end();
|
p.end();
|
||||||
return new T(image.toImage());
|
return image.toImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenEdgeEffect::isActive() const
|
bool ScreenEdgeEffect::isActive() const
|
||||||
|
|
|
@ -42,10 +42,8 @@ private Q_SLOTS:
|
||||||
private:
|
private:
|
||||||
void ensureGlowSvg();
|
void ensureGlowSvg();
|
||||||
std::unique_ptr<Glow> createGlow(ElectricBorder border, qreal factor, const QRect &geometry);
|
std::unique_ptr<Glow> createGlow(ElectricBorder border, qreal factor, const QRect &geometry);
|
||||||
template<typename T>
|
QImage createCornerGlow(ElectricBorder border);
|
||||||
T *createCornerGlow(ElectricBorder border);
|
QImage createEdgeGlow(ElectricBorder border, const QSize &size);
|
||||||
template<typename T>
|
|
||||||
T *createEdgeGlow(ElectricBorder border, const QSize &size);
|
|
||||||
QSize cornerGlowSize(ElectricBorder border);
|
QSize cornerGlowSize(ElectricBorder border);
|
||||||
Plasma::Svg *m_glow = nullptr;
|
Plasma::Svg *m_glow = nullptr;
|
||||||
std::map<ElectricBorder, std::unique_ptr<Glow>> m_borders;
|
std::map<ElectricBorder, std::unique_ptr<Glow>> m_borders;
|
||||||
|
@ -56,7 +54,7 @@ class Glow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<GLTexture> texture;
|
std::unique_ptr<GLTexture> texture;
|
||||||
std::unique_ptr<QImage> image;
|
QImage image;
|
||||||
QSize pictureSize;
|
QSize pictureSize;
|
||||||
qreal strength;
|
qreal strength;
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
|
|
|
@ -212,6 +212,9 @@ void StartupFeedbackEffect::paintScreen(const RenderTarget &renderTarget, const
|
||||||
default:
|
default:
|
||||||
return; // safety
|
return; // safety
|
||||||
}
|
}
|
||||||
|
if (!texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
GLShader *shader = nullptr;
|
GLShader *shader = nullptr;
|
||||||
|
@ -356,14 +359,20 @@ void StartupFeedbackEffect::prepareTextures(const QPixmap &pix)
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case BouncingFeedback:
|
case BouncingFeedback:
|
||||||
for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
m_bouncingTextures[i].reset(new GLTexture(scalePixmap(pix, BOUNCE_SIZES[i])));
|
m_bouncingTextures[i] = GLTexture::upload(scalePixmap(pix, BOUNCE_SIZES[i]));
|
||||||
|
if (!m_bouncingTextures[i]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_bouncingTextures[i]->setFilter(GL_LINEAR);
|
m_bouncingTextures[i]->setFilter(GL_LINEAR);
|
||||||
m_bouncingTextures[i]->setWrapMode(GL_CLAMP_TO_EDGE);
|
m_bouncingTextures[i]->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BlinkingFeedback:
|
case BlinkingFeedback:
|
||||||
case PassiveFeedback:
|
case PassiveFeedback:
|
||||||
m_texture.reset(new GLTexture(pix));
|
m_texture = GLTexture::upload(pix);
|
||||||
|
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);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -236,7 +236,7 @@ void TrackMouseEffect::loadTexture()
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (effects->isOpenGLCompositing()) {
|
if (effects->isOpenGLCompositing()) {
|
||||||
QImage img(f[i]);
|
QImage img(f[i]);
|
||||||
m_texture[i] = std::make_unique<GLTexture>(img);
|
m_texture[i] = GLTexture::upload(img);
|
||||||
m_lastRect[i].setSize(img.size());
|
m_lastRect[i].setSize(img.size());
|
||||||
}
|
}
|
||||||
if (effects->compositingType() == QPainterCompositing) {
|
if (effects->compositingType() == QPainterCompositing) {
|
||||||
|
|
|
@ -155,7 +155,10 @@ GLTexture *ZoomEffect::ensureCursorTexture()
|
||||||
m_cursorTextureDirty = false;
|
m_cursorTextureDirty = false;
|
||||||
const auto cursor = effects->cursorImage();
|
const auto cursor = effects->cursorImage();
|
||||||
if (!cursor.image().isNull()) {
|
if (!cursor.image().isNull()) {
|
||||||
m_cursorTexture = std::make_unique<GLTexture>(cursor.image());
|
m_cursorTexture = GLTexture::upload(cursor.image());
|
||||||
|
if (!m_cursorTexture) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
m_cursorTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
m_cursorTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ void ImageItemOpenGL::preprocess()
|
||||||
m_textureKey = m_image.cacheKey();
|
m_textureKey = m_image.cacheKey();
|
||||||
|
|
||||||
if (!m_texture || m_texture->size() != m_image.size()) {
|
if (!m_texture || m_texture->size() != m_image.size()) {
|
||||||
m_texture = std::make_unique<GLTexture>(m_image);
|
m_texture = GLTexture::upload(m_image);
|
||||||
} else {
|
} else {
|
||||||
m_texture->update(m_image);
|
m_texture->update(m_image);
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,10 @@ std::shared_ptr<GLTexture> DecorationShadowTextureCache::getTexture(ShadowTextur
|
||||||
}
|
}
|
||||||
Data d;
|
Data d;
|
||||||
d.providers << provider;
|
d.providers << provider;
|
||||||
d.texture = std::make_shared<GLTexture>(shadow->decorationShadowImage());
|
d.texture = GLTexture::upload(shadow->decorationShadowImage());
|
||||||
|
if (!d.texture) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
d.texture->setFilter(GL_LINEAR);
|
d.texture->setFilter(GL_LINEAR);
|
||||||
d.texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
d.texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
m_cache.insert(decoShadow.get(), d);
|
m_cache.insert(decoShadow.get(), d);
|
||||||
|
@ -252,7 +255,10 @@ void OpenGLShadowTextureProvider::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_texture = std::make_shared<GLTexture>(image);
|
m_texture = GLTexture::upload(image);
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue