[Scummvm-git-logs] scummvm master -> 5f3e0cc9b4e37f49cfe4187b50cde55a5e23990f
bluegr
noreply at scummvm.org
Sun Jun 22 11:09:48 UTC 2025
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
aebd8c7346 GRAPHICS: Add a ManagedSurface function for filling surfaces with blending
5f3e0cc9b4 WINTERMUTE: Make use of ManagedSurface::blendFillRect
Commit: aebd8c73463c5a81f4c4cfad86f19eb21abcbac8
https://github.com/scummvm/scummvm/commit/aebd8c73463c5a81f4c4cfad86f19eb21abcbac8
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-06-22T14:09:44+03:00
Commit Message:
GRAPHICS: Add a ManagedSurface function for filling surfaces with blending
Changed paths:
graphics/blit.h
graphics/blit/blit-alpha.cpp
graphics/blit/blit-alpha.h
graphics/blit/blit-generic.cpp
graphics/managed_surface.cpp
graphics/managed_surface.h
diff --git a/graphics/blit.h b/graphics/blit.h
index 49fd1f65dc6..126e790804b 100644
--- a/graphics/blit.h
+++ b/graphics/blit.h
@@ -290,10 +290,17 @@ private:
static void blitGeneric(Args &args, const TSpriteBlendMode &blendMode, const AlphaType &alphaType);
template<class T>
static void blitT(Args &args, const TSpriteBlendMode &blendMode, const AlphaType &alphaType);
-#undef LOGIC_FUNCS_EXT
typedef void(*BlitFunc)(Args &, const TSpriteBlendMode &, const AlphaType &);
static BlitFunc blitFunc;
+
+ static void fillGeneric(Args &args, const TSpriteBlendMode &blendMode);
+ template<class T>
+ static void fillT(Args &args, const TSpriteBlendMode &blendMode);
+
+ typedef void(*FillFunc)(Args &, const TSpriteBlendMode &);
+ static FillFunc fillFunc;
+
friend class ::BlendBlitUnfilteredTestSuite;
friend class BlendBlitImpl_Default;
friend class BlendBlitImpl_NEON;
@@ -373,6 +380,21 @@ public:
const TSpriteBlendMode blendMode,
const AlphaType alphaType);
+ /**
+ * Optimized version of doFill to be used with alpha blended fills
+ * NOTE: Can only be used with BlendBlit::getSupportedPixelFormat format
+ * @param dst a pointer to the destination buffer (can be offseted by pixels)
+ * @param dstPitch destination pitch
+ * @param width width of the input surface
+ * @param height height of the input surface
+ * @param colorMod the color to multiply by. (0xffffffff does no multiplication and has 0 overhead usually)
+ * @param blendMode the blending mode to be used
+ */
+ static void fill(byte *dst, const uint dstPitch,
+ const uint width, const uint height,
+ const uint32 colorMod,
+ const TSpriteBlendMode blendMode);
+
}; // End of class BlendBlit
/** @} */
diff --git a/graphics/blit/blit-alpha.cpp b/graphics/blit/blit-alpha.cpp
index b37edd2e712..e399b9da553 100644
--- a/graphics/blit/blit-alpha.cpp
+++ b/graphics/blit/blit-alpha.cpp
@@ -203,8 +203,9 @@ BlendBlit::Args::Args(byte *dst, const byte *src,
outo = dst + posY * _dstPitch + posX * 4;
}
-// Initialize this to nullptr at the start
+// Initialize these to nullptr at the start
BlendBlit::BlitFunc BlendBlit::blitFunc = nullptr;
+BlendBlit::FillFunc BlendBlit::fillFunc = nullptr;
// Only blits to and from 32bpp images
// So this function is just here to jump to whatever function is in
@@ -240,4 +241,25 @@ void BlendBlit::blit(byte *dst, const byte *src,
blitFunc(args, blendMode, alphaType);
}
+// Only fills 32bpp images
+// So this function is just here to jump to whatever function is in
+// BlendBlit::fillFunc. This way, we can detect at runtime whether or not
+// the cpu has certain SIMD feature enabled or not.
+void BlendBlit::fill(byte *dst, const uint dstPitch,
+ const uint width, const uint height,
+ const uint32 colorMod,
+ const TSpriteBlendMode blendMode) {
+ if (width == 0 || height == 0) return;
+
+ // If no function has been selected yet, detect and select
+ if (!fillFunc) {
+ // Get the correct blit function
+ // TODO: Add SIMD variants
+ fillFunc = fillGeneric;
+ }
+
+ Args args(dst, nullptr, dstPitch, 0, 0, 0, width, height, 0, 0, 0, 0, colorMod, 0);
+ fillFunc(args, blendMode);
+}
+
} // End of namespace Graphics
diff --git a/graphics/blit/blit-alpha.h b/graphics/blit/blit-alpha.h
index 2ebe959c82d..1aa4cb52075 100644
--- a/graphics/blit/blit-alpha.h
+++ b/graphics/blit/blit-alpha.h
@@ -85,6 +85,41 @@ public:
}
}
+
+ inline void fill(byte *out) const {
+ uint32 ina = this->ca;
+
+ /* if (ina == 255) {
+ if (rgbmod) {
+ out[BlendBlit::kAIndex] = 255;
+ out[BlendBlit::kBIndex] = this->cb;
+ out[BlendBlit::kGIndex] = this->cg;
+ out[BlendBlit::kRIndex] = this->cr;
+ } else {
+ out[BlendBlit::kAIndex] = 255;
+ out[BlendBlit::kBIndex] = 255;
+ out[BlendBlit::kGIndex] = 255;
+ out[BlendBlit::kRIndex] = 255;
+ }
+ } else if (ina != 0) */ {
+ if (rgbmod) {
+ const uint outb = (out[BlendBlit::kBIndex] * (255 - ina) >> 8);
+ const uint outg = (out[BlendBlit::kGIndex] * (255 - ina) >> 8);
+ const uint outr = (out[BlendBlit::kRIndex] * (255 - ina) >> 8);
+
+ out[BlendBlit::kAIndex] = 255;
+ out[BlendBlit::kBIndex] = outb + (255 * ina * this->cb >> 16);
+ out[BlendBlit::kGIndex] = outg + (255 * ina * this->cg >> 16);
+ out[BlendBlit::kRIndex] = outr + (255 * ina * this->cr >> 16);
+ } else {
+ out[BlendBlit::kAIndex] = 255;
+ out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * (255 - ina) + 255 * ina) >> 8;
+ out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * (255 - ina) + 255 * ina) >> 8;
+ out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * (255 - ina) + 255 * ina) >> 8;
+ }
+ }
+
+ }
};
template<bool rgbmod, bool alphamod>
@@ -123,6 +158,28 @@ public:
}
}
}
+
+ inline void fill(byte *out) const {
+ uint32 ina = this->ca;
+
+ if (ina == 255) {
+ if (rgbmod) {
+ out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * this->cb) >> 8;
+ out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * this->cg) >> 8;
+ out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * this->cr) >> 8;
+ }
+ } else if (ina != 0) {
+ if (rgbmod) {
+ out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((this->cb * ina) >> 8) >> 8;
+ out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((this->cg * ina) >> 8) >> 8;
+ out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((this->cr * ina) >> 8) >> 8;
+ } else {
+ out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * ina) >> 8;
+ out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * ina) >> 8;
+ out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * ina) >> 8;
+ }
+ }
+ }
};
template<bool rgbmod, bool alphamod>
@@ -186,6 +243,32 @@ public:
}
}
}
+
+ inline void fill(byte *out) const {
+ uint32 ina = this->ca;
+
+ if (ina == 255) {
+ if (rgbmod) {
+ out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + this->cb;
+ out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + this->cg;
+ out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + this->cr;
+ } else {
+ out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + 255;
+ out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + 255;
+ out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + 255;
+ }
+ } else if (ina != 0) {
+ if (rgbmod) {
+ out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((this->cb * ina) >> 8);
+ out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((this->cg * ina) >> 8);
+ out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((this->cr * ina) >> 8);
+ } else {
+ out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ina;
+ out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ina;
+ out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ina;
+ }
+ }
+ }
};
template<bool rgbmod, bool alphamod>
@@ -219,6 +302,20 @@ public:
}
}
}
+
+ inline void fill(byte *out) const {
+ out[BlendBlit::kAIndex] = 255;
+
+ if (rgbmod) {
+ out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((this->cb * out[BlendBlit::kBIndex]) >> 8), 0);
+ out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((this->cg * out[BlendBlit::kGIndex]) >> 8), 0);
+ out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((this->cr * out[BlendBlit::kRIndex]) >> 8), 0);
+ } else {
+ out[BlendBlit::kBIndex] = 0;
+ out[BlendBlit::kGIndex] = 0;
+ out[BlendBlit::kRIndex] = 0;
+ }
+ }
};
}; // End of class BlendBlitImpl_Base
@@ -344,4 +441,61 @@ void BlendBlit::blitT(Args &args, const TSpriteBlendMode &blendMode, const Alpha
}
}
+template<class T>
+void BlendBlit::fillT(Args &args, const TSpriteBlendMode &blendMode) {
+ bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
+ bool alphamod = ((args.color & kAModMask) != kAModMask);
+
+ if (blendMode == BLEND_ADDITIVE) {
+ if (rgbmod) {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template AdditiveBlend, true, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template AdditiveBlend, true, false>(args);
+ }
+ } else {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template AdditiveBlend, false, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template AdditiveBlend, false, false>(args);
+ }
+ }
+ } else if (blendMode == BLEND_SUBTRACTIVE) {
+ if (rgbmod) {
+ T::template fillInnerLoop<T::template SubtractiveBlend, true, false>(args);
+ } else {
+ T::template fillInnerLoop<T::template SubtractiveBlend, false, false>(args);
+ }
+ } else if (blendMode == BLEND_MULTIPLY) {
+ if (rgbmod) {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template MultiplyBlend, true, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template MultiplyBlend, true, false>(args);
+ }
+ } else {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template MultiplyBlend, false, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template MultiplyBlend, false, false>(args);
+ }
+ }
+ } else {
+ assert(blendMode == BLEND_NORMAL);
+ if (rgbmod) {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template AlphaBlend, true, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template AlphaBlend, true, false>(args);
+ }
+ } else {
+ if (alphamod) {
+ T::template fillInnerLoop<T::template AlphaBlend, false, true>(args);
+ } else {
+ T::template fillInnerLoop<T::template AlphaBlend, false, false>(args);
+ }
+ }
+ }
+}
+
} // End of namespace Graphics
diff --git a/graphics/blit/blit-generic.cpp b/graphics/blit/blit-generic.cpp
index bbdbc062f28..4fae045cd53 100644
--- a/graphics/blit/blit-generic.cpp
+++ b/graphics/blit/blit-generic.cpp
@@ -68,10 +68,32 @@ static inline void blitInnerLoop(BlendBlit::Args &args) {
}
}
+template<template <bool RGBMOD, bool ALPHAMOD> class PixelFunc, bool rgbmod, bool alphamod>
+static inline void fillInnerLoop(BlendBlit::Args &args) {
+ byte *out;
+
+ const PixelFunc<rgbmod, alphamod> pixelFunc(args.color);
+
+ for (uint32 i = 0; i < args.height; i++) {
+ out = args.outo;
+
+ for (uint32 j = 0; j < args.width; j++) {
+ pixelFunc.fill(out);
+
+ out += 4;
+ }
+ args.outo += args.dstPitch;
+ }
+}
+
}; // end of class BlendBlitImpl_Default
void BlendBlit::blitGeneric(Args &args, const TSpriteBlendMode &blendMode, const AlphaType &alphaType) {
blitT<BlendBlitImpl_Default>(args, blendMode, alphaType);
}
+void BlendBlit::fillGeneric(Args &args, const TSpriteBlendMode &blendMode) {
+ fillT<BlendBlitImpl_Default>(args, blendMode);
+}
+
} // End of namespace Graphics
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index 3a90fd66063..5582661ff71 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -1100,6 +1100,37 @@ Common::Rect ManagedSurface::blendBlitTo(Surface &target,
else return Common::Rect(0, 0, dstArea.width(), dstArea.height());
}
+void ManagedSurface::blendFillRect(Common::Rect r,
+ const uint colorMod, const TSpriteBlendMode blend) {
+ if (!isBlendBlitPixelFormatSupported(format, format)) {
+ warning("ManagedSurface::blendFillRect only accepts RGBA32!");
+ return;
+ }
+
+ // Alpha is zero
+ if ((colorMod & MS_ARGB(255, 0, 0, 0)) == 0) return;
+
+ // Use faster memory fills where possible
+ if (blend == BLEND_NORMAL &&
+ (colorMod & MS_ARGB(255, 0, 0, 0)) == MS_ARGB(255, 0, 0, 0)) {
+ fillRect(r, colorMod);
+ return;
+ }
+
+ r.clip(w, h);
+
+ if (!r.isValidRect())
+ return;
+
+ BlendBlit::fill(
+ (byte *)getBasePtr(0, 0), pitch,
+ r.width(), r.height(),
+ colorMod, blend);
+
+ // Mark the affected area
+ addDirtyRect(r);
+}
+
void ManagedSurface::markAllDirty() {
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
}
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
index 23831d07e83..d899e3fc2e1 100644
--- a/graphics/managed_surface.h
+++ b/graphics/managed_surface.h
@@ -767,6 +767,15 @@ public:
const TSpriteBlendMode blend = BLEND_NORMAL,
const AlphaType alphaType = ALPHA_FULL);
+ /**
+ * Fill a rect with a given color and blending mode.
+ *
+ * @param r The rectangle to fill.
+ * @param color The color to fill the rect with.
+ * @param blend The blending mode to use.
+ */
+ void blendFillRect(const Common::Rect r, const uint colorMod, const TSpriteBlendMode blend);
+
/**
* Clear the entire surface.
*/
Commit: 5f3e0cc9b4e37f49cfe4187b50cde55a5e23990f
https://github.com/scummvm/scummvm/commit/5f3e0cc9b4e37f49cfe4187b50cde55a5e23990f
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-06-22T14:09:44+03:00
Commit Message:
WINTERMUTE: Make use of ManagedSurface::blendFillRect
Changed paths:
engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
engines/wintermute/base/gfx/osystem/render_ticket.cpp
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index c4068a3b5cc..a9f67bd1198 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -242,17 +242,11 @@ void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a) {
modTargetRect(&fillRect);
- uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b);
-
- Graphics::Surface surf;
- surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format);
- Common::Rect sizeRect(fillRect);
- sizeRect.translate(-fillRect.top, -fillRect.left);
- surf.fillRect(fillRect, col);
+ Common::Rect sizeRect(fillRect.width(), fillRect.height());
Graphics::TransformStruct temp = Graphics::TransformStruct();
- temp._alphaDisable = false;
- drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp);
- surf.free();
+ temp._rgbaMod = MS_ARGB(a, r, g, b);
+ temp._alphaDisable = (a == 0xff);
+ drawSurface(nullptr, nullptr, &sizeRect, &fillRect, temp);
}
Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const {
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index ad633f5770f..a0fed8a9269 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -93,6 +93,11 @@ bool RenderTicket::operator==(const RenderTicket &t) const {
// Replacement for SDL2's SDL_RenderCopy
void RenderTicket::drawToSurface(Graphics::ManagedSurface *_targetSurface) const {
+ if (!getSurface()) {
+ _targetSurface->blendFillRect(_dstRect, _transform._rgbaMod, Graphics::BLEND_NORMAL);
+ return;
+ }
+
Common::Rect clipRect;
clipRect.setWidth(getSurface()->w);
clipRect.setHeight(getSurface()->h);
@@ -125,6 +130,11 @@ void RenderTicket::drawToSurface(Graphics::ManagedSurface *_targetSurface) const
}
void RenderTicket::drawToSurface(Graphics::ManagedSurface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const {
+ if (!getSurface()) {
+ _targetSurface->blendFillRect(*dstRect, _transform._rgbaMod, _transform._blendMode);
+ return;
+ }
+
bool doDelete = false;
if (!clipRect) {
doDelete = true;
More information about the Scummvm-git-logs
mailing list