Browse Source

Relax Texture:replacePixels sub-rect restriction for compressed textures.

Alex Szpakowski 3 years ago
parent
commit
4195911680
2 changed files with 19 additions and 7 deletions
  1. 11 2
      src/modules/graphics/Texture.cpp
  2. 8 5
      src/modules/graphics/opengl/Texture.cpp

+ 11 - 2
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();
 

+ 8 - 5
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
 	{