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)
|
||||
: d_ptr(new GLTexturePrivate())
|
||||
{
|
||||
|
@ -767,4 +676,74 @@ std::unique_ptr<GLTexture> GLTexture::allocate(GLenum internalFormat, const QSiz
|
|||
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
|
||||
|
|
|
@ -49,9 +49,6 @@ class KWINGLUTILS_EXPORT GLTexture
|
|||
{
|
||||
public:
|
||||
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
|
||||
|
@ -157,6 +154,8 @@ public:
|
|||
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> upload(const QImage &image);
|
||||
static std::unique_ptr<GLTexture> upload(const QPixmap &pixmap);
|
||||
|
||||
protected:
|
||||
const std::unique_ptr<GLTexturePrivate> d_ptr;
|
||||
|
|
|
@ -407,10 +407,7 @@ void OffscreenQuickView::hide()
|
|||
GLTexture *OffscreenQuickView::bufferAsTexture()
|
||||
{
|
||||
if (d->m_useBlit) {
|
||||
if (d->m_image.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
d->m_textureExport.reset(new GLTexture(d->m_image));
|
||||
d->m_textureExport = GLTexture::upload(d->m_image);
|
||||
} else {
|
||||
if (!d->m_fbo) {
|
||||
return nullptr;
|
||||
|
|
|
@ -77,7 +77,7 @@ bool BasicEGLSurfaceTextureInternal::updateFromImage(const QRegion ®ion)
|
|||
}
|
||||
|
||||
if (!m_texture) {
|
||||
m_texture.reset(new GLTexture(image));
|
||||
m_texture = GLTexture::upload(image);
|
||||
} else {
|
||||
const QRegion nativeRegion = scale(region, image.devicePixelRatio());
|
||||
for (const QRect &rect : nativeRegion) {
|
||||
|
@ -85,7 +85,7 @@ bool BasicEGLSurfaceTextureInternal::updateFromImage(const QRegion ®ion)
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_texture != nullptr;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -60,12 +60,10 @@ void BasicEGLSurfaceTextureWayland::update(const QRegion ®ion)
|
|||
|
||||
bool BasicEGLSurfaceTextureWayland::loadShmTexture(KWaylandServer::ShmClientBuffer *buffer)
|
||||
{
|
||||
const QImage &image = buffer->data();
|
||||
if (Q_UNLIKELY(image.isNull())) {
|
||||
m_texture = GLTexture::upload(buffer->data());
|
||||
if (!m_texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_texture.reset(new GLTexture(image));
|
||||
m_texture->setFilter(GL_LINEAR);
|
||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
m_texture->setContentTransform(TextureTransform::MirrorY);
|
||||
|
|
|
@ -691,7 +691,10 @@ void BlurEffect::generateNoiseTexture()
|
|||
// The noise texture looks distorted when not scaled with integer
|
||||
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->setWrapMode(GL_REPEAT);
|
||||
}
|
||||
|
@ -833,6 +836,9 @@ void BlurEffect::applyNoise(const ScreenData &data, const RenderTarget &renderTa
|
|||
{
|
||||
if (!m_noiseTexture) {
|
||||
generateNoiseTexture();
|
||||
if (!m_noiseTexture) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_shader->bind(BlurShader::NoiseSampleType);
|
||||
|
|
|
@ -551,7 +551,7 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
|
|||
if (cursorImage.isNull()) {
|
||||
m_cursor.texture = nullptr;
|
||||
} else {
|
||||
m_cursor.texture = std::make_unique<GLTexture>(cursorImage.image());
|
||||
m_cursor.texture = GLTexture::upload(cursorImage.image());
|
||||
}
|
||||
}
|
||||
if (m_cursor.texture) {
|
||||
|
|
|
@ -79,6 +79,9 @@ void ScreenEdgeEffect::paintScreen(const RenderTarget &renderTarget, const Rende
|
|||
}
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
GLTexture *texture = glow->texture.get();
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
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);
|
||||
glDisable(GL_BLEND);
|
||||
} 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);
|
||||
QPainter p(&tmp);
|
||||
p.drawImage(0, 0, *glow->image.get());
|
||||
p.drawImage(0, 0, glow->image);
|
||||
QColor color(Qt::transparent);
|
||||
color.setAlphaF(opacity);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
|
@ -140,9 +143,9 @@ void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, cons
|
|||
effects->addRepaint(glow->geometry);
|
||||
if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) {
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
glow->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
||||
glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
|
||||
} 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()) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->texture.reset(createCornerGlow<GLTexture>(border));
|
||||
glow->texture = GLTexture::upload(createCornerGlow(border));
|
||||
} else {
|
||||
glow->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
||||
}
|
||||
if (glow->texture) {
|
||||
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
|
||||
}
|
||||
if (!glow->texture) {
|
||||
return nullptr;
|
||||
}
|
||||
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
} else if (effects->compositingType() == QPainterCompositing) {
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->image.reset(createCornerGlow<QImage>(border));
|
||||
glow->image = createCornerGlow(border);
|
||||
glow->pictureSize = cornerGlowSize(border);
|
||||
} else {
|
||||
glow->image.reset(createEdgeGlow<QImage>(border, geometry.size()));
|
||||
glow->image = createEdgeGlow(border, geometry.size());
|
||||
glow->pictureSize = geometry.size();
|
||||
}
|
||||
if (!glow->image) {
|
||||
if (glow->image.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -198,22 +199,21 @@ std::unique_ptr<Glow> ScreenEdgeEffect::createGlow(ElectricBorder border, qreal
|
|||
return glow;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
||||
QImage ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
||||
{
|
||||
ensureGlowSvg();
|
||||
|
||||
switch (border) {
|
||||
case ElectricTopLeft:
|
||||
return new T(m_glow->pixmap(QStringLiteral("bottomright")).toImage());
|
||||
return m_glow->pixmap(QStringLiteral("bottomright")).toImage();
|
||||
case ElectricTopRight:
|
||||
return new T(m_glow->pixmap(QStringLiteral("bottomleft")).toImage());
|
||||
return m_glow->pixmap(QStringLiteral("bottomleft")).toImage();
|
||||
case ElectricBottomRight:
|
||||
return new T(m_glow->pixmap(QStringLiteral("topleft")).toImage());
|
||||
return m_glow->pixmap(QStringLiteral("topleft")).toImage();
|
||||
case ElectricBottomLeft:
|
||||
return new T(m_glow->pixmap(QStringLiteral("topright")).toImage());
|
||||
return m_glow->pixmap(QStringLiteral("topright")).toImage();
|
||||
default:
|
||||
return nullptr;
|
||||
return QImage{};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,8 +235,7 @@ QSize ScreenEdgeEffect::cornerGlowSize(ElectricBorder border)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||
QImage ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||
{
|
||||
ensureGlowSvg();
|
||||
|
||||
|
@ -268,7 +267,7 @@ T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
|||
pixmapPosition = QPoint(size.width() - c.width(), 0);
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
return QImage{};
|
||||
}
|
||||
QPixmap image(size);
|
||||
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.end();
|
||||
return new T(image.toImage());
|
||||
return image.toImage();
|
||||
}
|
||||
|
||||
bool ScreenEdgeEffect::isActive() const
|
||||
|
|
|
@ -42,10 +42,8 @@ private Q_SLOTS:
|
|||
private:
|
||||
void ensureGlowSvg();
|
||||
std::unique_ptr<Glow> createGlow(ElectricBorder border, qreal factor, const QRect &geometry);
|
||||
template<typename T>
|
||||
T *createCornerGlow(ElectricBorder border);
|
||||
template<typename T>
|
||||
T *createEdgeGlow(ElectricBorder border, const QSize &size);
|
||||
QImage createCornerGlow(ElectricBorder border);
|
||||
QImage createEdgeGlow(ElectricBorder border, const QSize &size);
|
||||
QSize cornerGlowSize(ElectricBorder border);
|
||||
Plasma::Svg *m_glow = nullptr;
|
||||
std::map<ElectricBorder, std::unique_ptr<Glow>> m_borders;
|
||||
|
@ -56,7 +54,7 @@ class Glow
|
|||
{
|
||||
public:
|
||||
std::unique_ptr<GLTexture> texture;
|
||||
std::unique_ptr<QImage> image;
|
||||
QImage image;
|
||||
QSize pictureSize;
|
||||
qreal strength;
|
||||
QRect geometry;
|
||||
|
|
|
@ -212,6 +212,9 @@ void StartupFeedbackEffect::paintScreen(const RenderTarget &renderTarget, const
|
|||
default:
|
||||
return; // safety
|
||||
}
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLShader *shader = nullptr;
|
||||
|
@ -356,14 +359,20 @@ void StartupFeedbackEffect::prepareTextures(const QPixmap &pix)
|
|||
switch (m_type) {
|
||||
case BouncingFeedback:
|
||||
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]->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
break;
|
||||
case BlinkingFeedback:
|
||||
case PassiveFeedback:
|
||||
m_texture.reset(new GLTexture(pix));
|
||||
m_texture = GLTexture::upload(pix);
|
||||
if (!m_texture) {
|
||||
return;
|
||||
}
|
||||
m_texture->setFilter(GL_LINEAR);
|
||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
break;
|
||||
|
|
|
@ -236,7 +236,7 @@ void TrackMouseEffect::loadTexture()
|
|||
for (int i = 0; i < 2; ++i) {
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
QImage img(f[i]);
|
||||
m_texture[i] = std::make_unique<GLTexture>(img);
|
||||
m_texture[i] = GLTexture::upload(img);
|
||||
m_lastRect[i].setSize(img.size());
|
||||
}
|
||||
if (effects->compositingType() == QPainterCompositing) {
|
||||
|
|
|
@ -155,7 +155,10 @@ GLTexture *ZoomEffect::ensureCursorTexture()
|
|||
m_cursorTextureDirty = false;
|
||||
const auto cursor = effects->cursorImage();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ void ImageItemOpenGL::preprocess()
|
|||
m_textureKey = m_image.cacheKey();
|
||||
|
||||
if (!m_texture || m_texture->size() != m_image.size()) {
|
||||
m_texture = std::make_unique<GLTexture>(m_image);
|
||||
m_texture = GLTexture::upload(m_image);
|
||||
} else {
|
||||
m_texture->update(m_image);
|
||||
}
|
||||
|
|
|
@ -162,7 +162,10 @@ std::shared_ptr<GLTexture> DecorationShadowTextureCache::getTexture(ShadowTextur
|
|||
}
|
||||
Data d;
|
||||
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->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
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->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
|
||||
|
|
Loading…
Reference in a new issue