[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