diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 24292079a..939542625 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -475,9 +475,18 @@ void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap throw love::Exception("Invalid rectangle dimensions (x=%d, y=%d, w=%d, h=%d) for %dx%d Texture.", rect.x, rect.y, rect.w, rect.h, mipw, miph); } - // We don't currently support partial updates of compressed textures. if (isPixelFormatCompressed(d->getFormat()) && (rect.x != 0 || rect.y != 0 || rect.w != mipw || rect.h != miph)) - throw love::Exception("Compressed textures only support replacing the entire Texture."); + { + const PixelFormatInfo &info = getPixelFormatInfo(d->getFormat()); + int bw = (int) info.blockWidth; + int bh = (int) info.blockHeight; + if (rect.x % bw != 0 || rect.y % bh != 0 || rect.w % bw != 0 || rect.h % bh != 0) + { + const char *name = nullptr; + love::getConstant(d->getFormat(), name); + throw love::Exception("Compressed texture format %s only supports replacing a sub-rectangle with offset and dimensions that are a multiple of %d x %d.", name, bw, bh); + } + } Graphics::flushBatchedDrawsGlobal(); diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 4bc97a4f8..79d39783e 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -466,13 +466,16 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s if (isPixelFormatCompressed(pixelformat)) { - if (r.x != 0 || r.y != 0) - throw love::Exception("x and y parameters must be 0 for compressed textures."); - if (texType == TEXTURE_2D || texType == TEXTURE_CUBE) - glCompressedTexImage2D(gltarget, level, fmt.internalformat, r.w, r.h, 0, size, data); + { + // Possible issues on some very old drivers if TexSubImage is used. + if (r.x != 0 || r.y != 0 || r.w != getPixelWidth(level) || r.h != getPixelHeight(level)) + glCompressedTexSubImage2D(gltarget, level, r.x, r.y, r.w, r.h, fmt.internalformat, size, data); + else + glCompressedTexImage2D(gltarget, level, fmt.internalformat, r.w, r.h, 0, size, data); + } else if (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME) - glCompressedTexSubImage3D(gltarget, level, 0, 0, slice, r.w, r.h, 1, fmt.internalformat, size, data); + glCompressedTexSubImage3D(gltarget, level, r.x, r.y, slice, r.w, r.h, 1, fmt.internalformat, size, data); } else {