[Scummvm-git-logs] scummvm master -> 0a4460ba343fb394f2385559bab90b404140dd25

criezy criezy at scummvm.org
Thu Mar 25 01:15:38 UTC 2021


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
8f8eebc427 AGS: Optimize blitting
0a4460ba34 AGS: Optimize non-stretched draw


Commit: 8f8eebc427297d179978b254ba5b16cef657eb35
    https://github.com/scummvm/scummvm/commit/8f8eebc427297d179978b254ba5b16cef657eb35
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2021-03-25T01:10:45Z

Commit Message:
AGS: Optimize blitting

The check on the mask color is now done before decomposing
the color to its RGB values. This avoids doing the decomposition
for the transparent pixels.

Blitting on a surface with the same pixel format now also
skips the color decomposition and directly copies the color
values.

Changed paths:
    engines/ags/lib/allegro/surface.cpp
    engines/ags/lib/allegro/surface.h


diff --git a/engines/ags/lib/allegro/surface.cpp b/engines/ags/lib/allegro/surface.cpp
index da09f2f301..1c3651ddd7 100644
--- a/engines/ags/lib/allegro/surface.cpp
+++ b/engines/ags/lib/allegro/surface.cpp
@@ -106,7 +106,6 @@ void BITMAP::floodfill(int x, int y, int color) {
 }
 
 const int SCALE_THRESHOLD = 0x100;
-#define IS_TRANSPARENT(R, G, B) ((R) == 255 && (G) == 0 && (B) == 255)
 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
 
 void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
@@ -139,23 +138,25 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 	const int scaleY = SCALE_THRESHOLD * srcRect.height() / dstRect.height();
 	const int xDir = horizFlip ? -1 : 1;
 	bool useTint = (tintRed >= 0 && tintGreen >= 0 && tintBlue >= 0);
+	bool sameFormat = (src.format == format);
 
 	byte rSrc, gSrc, bSrc, aSrc;
 	byte rDest = 0, gDest = 0, bDest = 0, aDest = 0;
-	uint32 pal[PALETTE_COUNT];
-
-	Graphics::PixelFormat srcFormat = src.format;
-	if (srcFormat.bytesPerPixel == 1) {
-		for (int i = 0; i < PALETTE_COUNT; ++i)
-			pal[i] = format.RGBToColor(
-				VGA_COLOR_TRANS(_G(current_palette)[i].r),
-				VGA_COLOR_TRANS(_G(current_palette)[i].g),
-				VGA_COLOR_TRANS(_G(current_palette)[i].b));
-		srcFormat = format;
-		// If we are skipping transparency, color 0 is skipped.
-		// Set it to transparent color to simplify the check below.
-		if (skipTrans)
-			pal[0] = format.RGBToColor(0xff, 0, 0xff);
+
+	PALETTE palette;
+	if (src.format.bytesPerPixel == 1 && format.bytesPerPixel != 1) {
+		for (int i = 0; i < PAL_SIZE; ++i) {
+			palette[i].r = VGA_COLOR_TRANS(_G(current_palette)[i].r);
+			palette[i].g = VGA_COLOR_TRANS(_G(current_palette)[i].g);
+			palette[i].b = VGA_COLOR_TRANS(_G(current_palette)[i].b);
+		}
+	}
+
+	uint32 transColor = 0, alphaMask = 0xff;
+	if (skipTrans && src.format.bytesPerPixel != 1) {
+		transColor = src.format.ARGBToColor(0, 255, 0, 255);
+		alphaMask = src.format.ARGBToColor(255, 0, 0, 0);
+		alphaMask = ~alphaMask;
 	}
 
 	int xStart = (dstRect.left < destRect.left) ? dstRect.left - destRect.left : 0;
@@ -178,17 +179,35 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 				continue;
 
 			const byte *srcVal = srcP + xDir * (scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel);
+			uint32 srcCol = getColor(srcVal, src.format.bytesPerPixel);
+
+			// Check if this is a transparent color we should skip
+			if (skipTrans && ((srcCol & alphaMask) == transColor))
+				continue;
+
 			byte *destVal = (byte *)&destP[destX * format.bytesPerPixel];
 
-			if (src.format.bytesPerPixel == 1 && format.bytesPerPixel == 1) {
-				if (!skipTrans || *srcVal != 0)
-					*destVal = *srcVal;
+			// When blitting to the same format we can just copy the color
+			if (format.bytesPerPixel == 1) {
+				*destVal = srcCol;
+				continue;
+			} else if (sameFormat && srcAlpha == -1) {
+				if (format.bytesPerPixel == 4)
+					*(uint32 *)destVal = srcCol;
+				else
+					*(uint16 *)destVal = srcCol;
 				continue;
 			}
-			srcFormat.colorToARGB(getColor(srcVal, src.format.bytesPerPixel, pal), aSrc, rSrc, gSrc, bSrc);
 
-			if (skipTrans && IS_TRANSPARENT(rSrc, gSrc, bSrc))
-				continue;
+			// We need the rgb values to do blending and/or convert between formats
+			if (src.format.bytesPerPixel == 1) {
+				const RGB& rgb = palette[srcCol];
+				aSrc = 0xff;
+				rSrc = rgb.r;
+				gSrc = rgb.g;
+				bSrc = rgb.b;
+			} else
+				src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
 
 			if (srcAlpha == -1) {
 				// This means we don't use blending.
@@ -208,7 +227,7 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 					aSrc = srcAlpha;
 				} else {
 					// TODO: move this to blendPixel to only do it when needed?
-					format.colorToARGB(getColor(destVal, format.bytesPerPixel, nullptr), aDest, rDest, gDest, bDest);
+					format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
 				}
 				blendPixel(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, srcAlpha);
 			}
diff --git a/engines/ags/lib/allegro/surface.h b/engines/ags/lib/allegro/surface.h
index a855857608..1d91048c4a 100644
--- a/engines/ags/lib/allegro/surface.h
+++ b/engines/ags/lib/allegro/surface.h
@@ -247,17 +247,16 @@ private:
 	void blendTintSprite(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha, bool light) const ;
 
 
-	inline uint32 getColor(const byte *data, byte bpp, uint32* palette) const {
+	inline uint32 getColor(const byte *data, byte bpp) const {
 		switch (bpp) {
 		case 1:
-			assert(palette);
-			return palette[*data];
+			return *data;
 		case 2:
 			return *(const uint16 *)data;
 		case 4:
 			return *(const uint32 *)data;
 		default:
-			error("Unknown format");
+			error("Unsupported format in BITMAP::getColor");
 		}
 	}
 };


Commit: 0a4460ba343fb394f2385559bab90b404140dd25
    https://github.com/scummvm/scummvm/commit/0a4460ba343fb394f2385559bab90b404140dd25
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2021-03-25T01:10:45Z

Commit Message:
AGS: Optimize non-stretched draw

Changed paths:
    engines/ags/lib/allegro/gfx.cpp
    engines/ags/lib/allegro/surface.cpp
    engines/ags/lib/allegro/surface.h


diff --git a/engines/ags/lib/allegro/gfx.cpp b/engines/ags/lib/allegro/gfx.cpp
index 9bb2bb5488..88f7e98e5f 100644
--- a/engines/ags/lib/allegro/gfx.cpp
+++ b/engines/ags/lib/allegro/gfx.cpp
@@ -104,76 +104,69 @@ int bitmap_mask_color(BITMAP *bmp) {
 
 void blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
 	dest->draw(src, Common::Rect(src_x, src_y, src_x + width, src_y + height),
-		Common::Rect(dst_x, dst_y, dst_x + width, dst_y + height),
-		false, false, false, -1);
+		dst_x, dst_y, false, false, false, -1);
 }
 
 void stretch_blit(const BITMAP *src, BITMAP *dest,
 		int source_x, int source_y, int source_width, int source_height,
 		int dest_x, int dest_y, int dest_width, int dest_height) {
-	dest->draw(src,
+	dest->stretchDraw(src,
 		Common::Rect(source_x, source_y, source_x + source_width, source_y + source_height),
 		Common::Rect(dest_x, dest_y, dest_x + dest_width, dest_y + dest_height),
-		false, false, false, -1);
+		false, -1);
 }
 
 void masked_blit(const BITMAP *src, BITMAP *dest, int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
 	assert(src->format == dest->format);
 
 	dest->draw(src, Common::Rect(src_x, src_y, src_x + width, src_y + height),
-		Common::Rect(dst_x, dst_y, dst_x + width, dst_y + height),
-		false, false, true, -1);
+		dst_x, dst_y, false, false, true, -1);
 }
 
 void masked_stretch_blit(const BITMAP *src, BITMAP *dest,
 		int source_x, int source_y, int source_width, int source_height,
 		int dest_x, int dest_y, int dest_width, int dest_height) {
-	dest->draw(src,
+	dest->stretchDraw(src,
 		Common::Rect(source_x, source_y, source_x + source_width, source_y + source_height),
 		Common::Rect(dest_x, dest_y, dest_x + dest_width, dest_y + dest_height),
-		false, false, true, -1);
+		true, -1);
 }
 
 void draw_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		false, false, true, -1);
+		x, y, false, false, true, -1);
 }
 
 void stretch_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int w, int h) {
-	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
+	bmp->stretchDraw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
 		Common::Rect(x, y, x + w, y + h),
-		false, false, true, -1);
+		true, -1);
 }
 
 void draw_trans_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		false, false, true, _G(trans_blend_alpha));
+		x, y, false, false, true, _G(trans_blend_alpha));
 }
 
 void draw_lit_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int color) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		false, false, true, color, _G(trans_blend_red), _G(trans_blend_green), _G(trans_blend_blue));
+		x, y, false, false, true, color,
+		_G(trans_blend_red), _G(trans_blend_green), _G(trans_blend_blue));
 }
 
 void draw_sprite_h_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		true, false, true, -1);
+		x, y, true, false, true, -1);
 }
 
 void draw_sprite_v_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		false, true, true, -1);
+		x, y, false, true, true, -1);
 }
 
 void draw_sprite_vh_flip(BITMAP *bmp, const BITMAP *sprite, int x, int y) {
 	bmp->draw(sprite, Common::Rect(0, 0, sprite->w, sprite->h),
-		Common::Rect(x, y, x + sprite->w, y + sprite->h),
-		true, true, true, -1);
+		x, y, true, true, true, -1);
 }
 
 void rotate_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, fixed angle) {
diff --git a/engines/ags/lib/allegro/surface.cpp b/engines/ags/lib/allegro/surface.cpp
index 1c3651ddd7..8c5d577d93 100644
--- a/engines/ags/lib/allegro/surface.cpp
+++ b/engines/ags/lib/allegro/surface.cpp
@@ -109,7 +109,7 @@ const int SCALE_THRESHOLD = 0x100;
 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
 
 void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
-		const Common::Rect &dstRect, bool horizFlip, bool vertFlip,
+		int dstX, int dstY, bool horizFlip, bool vertFlip,
 		bool skipTrans, int srcAlpha, int tintRed, int tintGreen,
 		int tintBlue) {
 	assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 4 ||
@@ -121,6 +121,7 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 		return;
 
 	// Figure out the dest area that will be updated
+	Common::Rect dstRect(dstX, dstY, dstX + srcRect.width(), dstY + srcRect.height());
 	Common::Rect destRect = dstRect.findIntersectingRect(
 		Common::Rect(cl, ct, cr, cb));
 	if (destRect.isEmpty())
@@ -134,8 +135,6 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 	Graphics::Surface destArea = dest.getSubArea(destRect);
 
 	// Define scaling and other stuff used by the drawing loops
-	const int scaleX = SCALE_THRESHOLD * srcRect.width() / dstRect.width();
-	const int scaleY = SCALE_THRESHOLD * srcRect.height() / dstRect.height();
 	const int xDir = horizFlip ? -1 : 1;
 	bool useTint = (tintRed >= 0 && tintGreen >= 0 && tintBlue >= 0);
 	bool sameFormat = (src.format == format);
@@ -162,23 +161,21 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 	int xStart = (dstRect.left < destRect.left) ? dstRect.left - destRect.left : 0;
 	int yStart = (dstRect.top < destRect.top) ? dstRect.top - destRect.top : 0;
 
-	for (int destY = yStart, yCtr = 0, scaleYCtr = 0; yCtr < dstRect.height();
-			++destY, ++yCtr, scaleYCtr += scaleY) {
+	for (int destY = yStart, yCtr = 0; yCtr < dstRect.height(); ++destY, ++yCtr) {
 		if (destY < 0 || destY >= destArea.h)
 			continue;
 		byte *destP = (byte *)destArea.getBasePtr(0, destY);
 		const byte *srcP = (const byte *)src.getBasePtr(
 			horizFlip ? srcRect.right - 1 : srcRect.left,
-			vertFlip ? srcRect.bottom - 1 - scaleYCtr / SCALE_THRESHOLD :
-			srcRect.top + scaleYCtr / SCALE_THRESHOLD);
+			vertFlip ? srcRect.bottom - 1 - yCtr :
+			srcRect.top + yCtr);
 
 		// Loop through the pixels of the row
-		for (int destX = xStart, xCtr = 0, scaleXCtr = 0; xCtr < dstRect.width();
-				++destX, ++xCtr, scaleXCtr += scaleX) {
+		for (int destX = xStart, xCtr = 0, xCtrBpp = 0; xCtr < dstRect.width(); ++destX, ++xCtr, xCtrBpp += src.format.bytesPerPixel) {
 			if (destX < 0 || destX >= destArea.w)
 				continue;
 
-			const byte *srcVal = srcP + xDir * (scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel);
+			const byte *srcVal = srcP + xDir * xCtrBpp;
 			uint32 srcCol = getColor(srcVal, src.format.bytesPerPixel);
 
 			// Check if this is a transparent color we should skip
@@ -241,6 +238,122 @@ void BITMAP::draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
 	}
 }
 
+void BITMAP::stretchDraw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
+		const Common::Rect &dstRect, bool skipTrans, int srcAlpha) {
+	assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 4 ||
+		(format.bytesPerPixel == 1 && srcBitmap->format.bytesPerPixel == 1));
+
+	// Allegro disables draw when the clipping rect has negative width/height.
+	// Common::Rect instead asserts, which we don't want.
+	if (cr <= cl || cb <= ct)
+		return;
+
+	// Figure out the dest area that will be updated
+	Common::Rect destRect = dstRect.findIntersectingRect(
+		Common::Rect(cl, ct, cr, cb));
+	if (destRect.isEmpty())
+		// Area is entirely outside the clipping area, so nothing to draw
+		return;
+
+	// Get source and dest surface. Note that for the destination we create
+	// a temporary sub-surface based on the allowed clipping area
+	const Graphics::ManagedSurface &src = **srcBitmap;
+	Graphics::ManagedSurface &dest = *_owner;
+	Graphics::Surface destArea = dest.getSubArea(destRect);
+
+	// Define scaling and other stuff used by the drawing loops
+	const int scaleX = SCALE_THRESHOLD * srcRect.width() / dstRect.width();
+	const int scaleY = SCALE_THRESHOLD * srcRect.height() / dstRect.height();
+	bool sameFormat = (src.format == format);
+
+	byte rSrc, gSrc, bSrc, aSrc;
+	byte rDest = 0, gDest = 0, bDest = 0, aDest = 0;
+
+	PALETTE palette;
+	if (src.format.bytesPerPixel == 1 && format.bytesPerPixel != 1) {
+		for (int i = 0; i < PAL_SIZE; ++i) {
+			palette[i].r = VGA_COLOR_TRANS(_G(current_palette)[i].r);
+			palette[i].g = VGA_COLOR_TRANS(_G(current_palette)[i].g);
+			palette[i].b = VGA_COLOR_TRANS(_G(current_palette)[i].b);
+		}
+	}
+
+	uint32 transColor = 0, alphaMask = 0xff;
+	if (skipTrans && src.format.bytesPerPixel != 1) {
+		transColor = src.format.ARGBToColor(0, 255, 0, 255);
+		alphaMask = src.format.ARGBToColor(255, 0, 0, 0);
+		alphaMask = ~alphaMask;
+	}
+
+	int xStart = (dstRect.left < destRect.left) ? dstRect.left - destRect.left : 0;
+	int yStart = (dstRect.top < destRect.top) ? dstRect.top - destRect.top : 0;
+
+	for (int destY = yStart, yCtr = 0, scaleYCtr = 0; yCtr < dstRect.height();
+			++destY, ++yCtr, scaleYCtr += scaleY) {
+		if (destY < 0 || destY >= destArea.h)
+			continue;
+		byte *destP = (byte *)destArea.getBasePtr(0, destY);
+		const byte *srcP = (const byte *)src.getBasePtr(
+			srcRect.left, srcRect.top + scaleYCtr / SCALE_THRESHOLD);
+
+		// Loop through the pixels of the row
+		for (int destX = xStart, xCtr = 0, scaleXCtr = 0; xCtr < dstRect.width();
+				++destX, ++xCtr, scaleXCtr += scaleX) {
+			if (destX < 0 || destX >= destArea.w)
+				continue;
+
+			const byte *srcVal = srcP + scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel;
+			uint32 srcCol = getColor(srcVal, src.format.bytesPerPixel);
+
+			// Check if this is a transparent color we should skip
+			if (skipTrans && ((srcCol & alphaMask) == transColor))
+				continue;
+
+			byte *destVal = (byte *)&destP[destX * format.bytesPerPixel];
+
+			// When blitting to the same format we can just copy the color
+			if (format.bytesPerPixel == 1) {
+				*destVal = srcCol;
+				continue;
+			} else if (sameFormat && srcAlpha == -1) {
+				if (format.bytesPerPixel == 4)
+					*(uint32 *)destVal = srcCol;
+				else
+					*(uint16 *)destVal = srcCol;
+				continue;
+			}
+
+			// We need the rgb values to do blending and/or convert between formats
+			if (src.format.bytesPerPixel == 1) {
+				const RGB& rgb = palette[srcCol];
+				aSrc = 0xff;
+				rSrc = rgb.r;
+				gSrc = rgb.g;
+				bSrc = rgb.b;
+			} else
+				src.format.colorToARGB(srcCol, aSrc, rSrc, gSrc, bSrc);
+
+			if (srcAlpha == -1) {
+				// This means we don't use blending.
+				aDest = aSrc;
+				rDest = rSrc;
+				gDest = gSrc;
+				bDest = bSrc;
+			} else {
+				// TODO: move this to blendPixel to only do it when needed?
+				format.colorToARGB(getColor(destVal, format.bytesPerPixel), aDest, rDest, gDest, bDest);
+				blendPixel(aSrc, rSrc, gSrc, bSrc, aDest, rDest, gDest, bDest, srcAlpha);
+			}
+
+			uint32 pixel = format.ARGBToColor(aDest, rDest, gDest, bDest);
+			if (format.bytesPerPixel == 4)
+				*(uint32 *)destVal = pixel;
+			else
+				*(uint16 *)destVal = pixel;
+		}
+	}
+}
+
 void BITMAP::blendPixel(uint8 aSrc, uint8 rSrc, uint8 gSrc, uint8 bSrc, uint8 &aDest, uint8 &rDest, uint8 &gDest, uint8 &bDest, uint32 alpha) const {
 	switch(_G(_blender_mode)) {
 	case kSourceAlphaBlender:
diff --git a/engines/ags/lib/allegro/surface.h b/engines/ags/lib/allegro/surface.h
index 1d91048c4a..5ca105d550 100644
--- a/engines/ags/lib/allegro/surface.h
+++ b/engines/ags/lib/allegro/surface.h
@@ -106,10 +106,16 @@ public:
 	 * Draws the passed surface onto this one
 	 */
 	void draw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
-		const Common::Rect &destRect, bool horizFlip, bool vertFlip,
+		int dstX, int dstY, bool horizFlip, bool vertFlip,
 		bool skipTrans, int srcAlpha, int tintRed = -1, int tintGreen = -1,
 		int tintBlue = -1);
 
+	/**
+	 * Stretches and draws the passed surface onto this one
+	 */
+	void stretchDraw(const BITMAP *srcBitmap, const Common::Rect &srcRect,
+		const Common::Rect &destRect, bool skipTrans, int srcAlpha);
+
 private:
 	// True color blender functions
 	// In Allegro all the blender functions are of the form




More information about the Scummvm-git-logs mailing list