summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/rendersw.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/rendersw.hxx')
-rw-r--r--src/emu/rendersw.hxx1034
1 files changed, 544 insertions, 490 deletions
diff --git a/src/emu/rendersw.hxx b/src/emu/rendersw.hxx
index 37cdbc5b736..5561928e7df 100644
--- a/src/emu/rendersw.hxx
+++ b/src/emu/rendersw.hxx
@@ -15,7 +15,7 @@
#include "render.h"
-template<typename _PixelType, int _SrcShiftR, int _SrcShiftG, int _SrcShiftB, int _DstShiftR, int _DstShiftG, int _DstShiftB, bool _NoDestRead = false, bool _BilinearFilter = false>
+template <typename PixelType, int SrcShiftR, int SrcShiftG, int SrcShiftB, int DstShiftR, int DstShiftG, int DstShiftB, bool NoDestRead = false, bool BilinearFilter = false>
class software_renderer
{
private:
@@ -29,29 +29,29 @@ private:
};
// internal helpers
- static inline bool is_opaque(float alpha) { return (alpha >= (_NoDestRead ? 0.5f : 1.0f)); }
- static inline bool is_transparent(float alpha) { return (alpha < (_NoDestRead ? 0.5f : 0.0001f)); }
+ static constexpr bool is_opaque(float alpha) { return (alpha >= (NoDestRead ? 0.5f : 1.0f)); }
+ static constexpr bool is_transparent(float alpha) { return (alpha < (NoDestRead ? 0.5f : 0.0001f)); }
static inline rgb_t apply_intensity(int intensity, rgb_t color) { return color.scale8(intensity); }
static inline float round_nearest(float f) { return floor(f + 0.5f); }
// destination pixels are written based on the values of the template parameters
- static inline _PixelType dest_assemble_rgb(u32 r, u32 g, u32 b) { return (r << _DstShiftR) | (g << _DstShiftG) | (b << _DstShiftB); }
- static inline _PixelType dest_rgb_to_pixel(u32 r, u32 g, u32 b) { return dest_assemble_rgb(r >> _SrcShiftR, g >> _SrcShiftG, b >> _SrcShiftB); }
+ static constexpr PixelType dest_assemble_rgb(u32 r, u32 g, u32 b) { return (r << DstShiftR) | (g << DstShiftG) | (b << DstShiftB); }
+ static constexpr PixelType dest_rgb_to_pixel(u32 r, u32 g, u32 b) { return dest_assemble_rgb(r >> SrcShiftR, g >> SrcShiftG, b >> SrcShiftB); }
// source 32-bit pixels are in MAME standardized format
- static inline u32 source32_r(u32 pixel) { return (pixel >> (16 + _SrcShiftR)) & (0xff >> _SrcShiftR); }
- static inline u32 source32_g(u32 pixel) { return (pixel >> ( 8 + _SrcShiftG)) & (0xff >> _SrcShiftG); }
- static inline u32 source32_b(u32 pixel) { return (pixel >> ( 0 + _SrcShiftB)) & (0xff >> _SrcShiftB); }
+ static constexpr u32 source32_r(u32 pixel) { return (pixel >> (16 + SrcShiftR)) & (0xff >> SrcShiftR); }
+ static constexpr u32 source32_g(u32 pixel) { return (pixel >> ( 8 + SrcShiftG)) & (0xff >> SrcShiftG); }
+ static constexpr u32 source32_b(u32 pixel) { return (pixel >> ( 0 + SrcShiftB)) & (0xff >> SrcShiftB); }
// destination pixel masks are based on the template parameters as well
- static inline u32 dest_r(_PixelType pixel) { return (pixel >> _DstShiftR) & (0xff >> _SrcShiftR); }
- static inline u32 dest_g(_PixelType pixel) { return (pixel >> _DstShiftG) & (0xff >> _SrcShiftG); }
- static inline u32 dest_b(_PixelType pixel) { return (pixel >> _DstShiftB) & (0xff >> _SrcShiftB); }
+ static constexpr u32 dest_r(PixelType pixel) { return (pixel >> DstShiftR) & (0xff >> SrcShiftR); }
+ static constexpr u32 dest_g(PixelType pixel) { return (pixel >> DstShiftG) & (0xff >> SrcShiftG); }
+ static constexpr u32 dest_b(PixelType pixel) { return (pixel >> DstShiftB) & (0xff >> SrcShiftB); }
// generic conversion with special optimization for destinations in the standard format
- static inline _PixelType source32_to_dest(u32 pixel)
+ static constexpr PixelType source32_to_dest(u32 pixel)
{
- if (_SrcShiftR == 0 && _SrcShiftG == 0 && _SrcShiftB == 0 && _DstShiftR == 16 && _DstShiftG == 8 && _DstShiftB == 0)
+ if (SrcShiftR == 0 && SrcShiftG == 0 && SrcShiftB == 0 && DstShiftR == 16 && DstShiftG == 8 && DstShiftB == 0)
return pixel;
else
return dest_assemble_rgb(source32_r(pixel), source32_g(pixel), source32_b(pixel));
@@ -67,12 +67,12 @@ private:
// The document also contains the constants below as floats.
//-------------------------------------------------
- static inline u32 clamp16_shift8(u32 x)
+ static constexpr u32 clamp16_shift8(u32 x)
{
- return ((s32(x) < 0) ? 0 : (x > 65535 ? 255: x >> 8));
+ return (s32(x) < 0) ? 0 : (x > 65535) ? 255 : (x >> 8);
}
- static inline u32 ycc_to_rgb(u32 ycc)
+ static constexpr u32 ycc_to_rgb(u32 ycc)
{
// original equations:
//
@@ -130,8 +130,8 @@ private:
static inline u32 get_texel_palette16(const render_texinfo &texture, s32 curu, s32 curv)
{
- const rgb_t *palbase = texture.palette;
- if (_BilinearFilter)
+ rgb_t const *const palbase = texture.palette;
+ if constexpr (BilinearFilter)
{
s32 u0 = curu >> 16;
s32 u1 = 1;
@@ -142,7 +142,7 @@ private:
if (v0 < 0) v0 = v1 = 0;
else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
- const u16 *texbase = reinterpret_cast<const u16 *>(texture.base);
+ u16 const *texbase = reinterpret_cast<u16 const *>(texture.base);
texbase += v0 * texture.rowpixels + u0;
u32 pix00 = palbase[texbase[0]];
@@ -153,7 +153,10 @@ private:
}
else
{
- const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
+ s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1);
+ s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1);
+
+ u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + v * texture.rowpixels + u;
return palbase[texbase[0]];
}
}
@@ -166,8 +169,8 @@ private:
static inline u32 get_texel_palette16a(const render_texinfo &texture, s32 curu, s32 curv)
{
- const rgb_t *palbase = texture.palette;
- if (_BilinearFilter)
+ rgb_t const *const palbase = texture.palette;
+ if constexpr (BilinearFilter)
{
s32 u0 = curu >> 16;
s32 u1 = 1;
@@ -178,14 +181,17 @@ private:
if (v0 < 0) v0 = v1 = 0;
else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
- const u16 *texbase = reinterpret_cast<const u16 *>(texture.base);
+ u16 const *texbase = reinterpret_cast<u16 const *>(texture.base);
texbase += v0 * texture.rowpixels + u0;
return rgbaint_t::bilinear_filter(palbase[texbase[0]], palbase[texbase[u1]], palbase[texbase[v1]], palbase[texbase[u1 + v1]], curu >> 8, curv >> 8);
}
else
{
- const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
+ s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1);
+ s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1);
+
+ u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + v * texture.rowpixels + u;
return palbase[texbase[0]];
}
}
@@ -198,7 +204,7 @@ private:
static inline u32 get_texel_yuy16(const render_texinfo &texture, s32 curu, s32 curv)
{
- if (_BilinearFilter)
+ if constexpr (BilinearFilter)
{
s32 u0 = curu >> 16;
s32 u1 = 1;
@@ -247,8 +253,11 @@ private:
}
else
{
- const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 17) * 2;
- return (texbase[(curu >> 16) & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
+ s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1);
+ s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1);
+
+ const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + v * texture.rowpixels + (u >> 1) * 2;
+ return (texbase[u & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
}
}
@@ -258,28 +267,67 @@ private:
// RGB source
//-------------------------------------------------
+ template <bool Wrap>
static inline u32 get_texel_rgb32(const render_texinfo &texture, s32 curu, s32 curv)
{
- if (_BilinearFilter)
+ if constexpr (BilinearFilter)
{
- s32 u0 = curu >> 16;
- s32 u1 = 1;
- if (u0 < 0) u0 = u1 = 0;
- else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
- s32 v0 = curv >> 16;
- s32 v1 = texture.rowpixels;
- if (v0 < 0) v0 = v1 = 0;
- else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
-
- const u32 *texbase = reinterpret_cast<const u32 *>(texture.base);
- texbase += v0 * texture.rowpixels + u0;
+ s32 u0, u1, v0, v1;
+ if constexpr (Wrap)
+ {
+ u0 = (curu >> 16) % texture.width;
+ if (0 > u0)
+ u0 += texture.width;
+ u1 = (u0 + 1) % texture.width;
+
+ v0 = (curv >> 16) % texture.height;
+ if (0 > v0)
+ v0 += texture.height;
+ v1 = (v0 + 1) % texture.height;
+ }
+ else
+ {
+ u0 = curu >> 16;
+ if (u0 < 0)
+ u0 = u1 = 0;
+ else if (texture.width <= (u0 + 1))
+ u0 = u1 = texture.width - 1;
+ else
+ u1 = u0 + 1;
- return rgbaint_t::bilinear_filter(texbase[0], texbase[u1], texbase[v1], texbase[u1 + v1], curu >> 8, curv >> 8);
+ v0 = curv >> 16;
+ if (v0 < 0)
+ v0 = v1 = 0;
+ else if (texture.height <= (v0 + 1))
+ v0 = v1 = texture.height - 1;
+ else
+ v1 = v0 + 1;
+ }
+ u32 const *const texbase = reinterpret_cast<u32 const *>(texture.base);
+ u32 const *const row0base = texbase + (v0 * texture.rowpixels);
+ u32 const *const row1base = texbase + (v1 * texture.rowpixels);
+ return rgbaint_t::bilinear_filter(row0base[u0], row0base[u1], row1base[u0], row1base[u1], curu >> 8, curv >> 8);
}
else
{
- const u32 *texbase = reinterpret_cast<const u32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
- return texbase[0];
+ s32 u, v;
+ if constexpr (Wrap)
+ {
+ u = (curu >> 16) % texture.width;
+ if (0 > u)
+ u += texture.width;
+
+ v = (curv >> 16) % texture.height;
+ if (0 > v)
+ v += texture.height;
+ }
+ else
+ {
+ u = std::clamp<s32>(curu >> 16, 0, texture.width - 1);
+ v = std::clamp<s32>(curv >> 16, 0, texture.height - 1);
+ }
+ u32 const *const rowbase = reinterpret_cast<u32 const *>(texture.base) + (v * texture.rowpixels);
+ return rowbase[u];
}
}
@@ -289,28 +337,67 @@ private:
// ARGB source
//-------------------------------------------------
- static inline u32 get_texel_argb32(const render_texinfo &texture, s32 curu, s32 curv)
+ template <bool Wrap>
+ static inline u32 get_texel_argb32(render_texinfo const &texture, s32 curu, s32 curv)
{
- if (_BilinearFilter)
+ if constexpr (BilinearFilter)
{
- s32 u0 = curu >> 16;
- s32 u1 = 1;
- if (u0 < 0) u0 = u1 = 0;
- else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
- s32 v0 = curv >> 16;
- s32 v1 = texture.rowpixels;
- if (v0 < 0) v0 = v1 = 0;
- else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
-
- const u32 *texbase = reinterpret_cast<const u32 *>(texture.base);
- texbase += v0 * texture.rowpixels + u0;
+ s32 u0, u1, v0, v1;
+ if constexpr (Wrap)
+ {
+ u0 = (curu >> 16) % texture.width;
+ if (0 > u0)
+ u0 += texture.width;
+ u1 = (u0 + 1) % texture.width;
+
+ v0 = (curv >> 16) % texture.height;
+ if (0 > v0)
+ v0 += texture.height;
+ v1 = (v0 + 1) % texture.height;
+ }
+ else
+ {
+ u0 = curu >> 16;
+ if (u0 < 0)
+ u0 = u1 = 0;
+ else if (texture.width <= (u0 + 1))
+ u0 = u1 = texture.width - 1;
+ else
+ u1 = u0 + 1;
- return rgbaint_t::bilinear_filter(texbase[0], texbase[u1], texbase[v1], texbase[u1 + v1], curu >> 8, curv >> 8);
+ v0 = curv >> 16;
+ if (v0 < 0)
+ v0 = v1 = 0;
+ else if (texture.height <= (v0 + 1))
+ v0 = v1 = texture.height - 1;
+ else
+ v1 = v0 + 1;
+ }
+ u32 const *const texbase = reinterpret_cast<u32 const *>(texture.base);
+ u32 const *const row0base = texbase + (v0 * texture.rowpixels);
+ u32 const *const row1base = texbase + (v1 * texture.rowpixels);
+ return rgbaint_t::bilinear_filter(row0base[u0], row0base[u1], row1base[u0], row1base[u1], curu >> 8, curv >> 8);
}
else
{
- const u32 *texbase = reinterpret_cast<const u32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
- return texbase[0];
+ s32 u, v;
+ if constexpr (Wrap)
+ {
+ u = (curu >> 16) % texture.width;
+ if (0 > u)
+ u += texture.width;
+
+ v = (curv >> 16) % texture.height;
+ if (0 > v)
+ v += texture.height;
+ }
+ else
+ {
+ u = std::clamp<s32>(curu >> 16, 0, texture.width - 1);
+ v = std::clamp<s32>(curv >> 16, 0, texture.height - 1);
+ }
+ u32 const *const rowbase = reinterpret_cast<u32 const *>(texture.base) + (v * texture.rowpixels);
+ return rowbase[u];
}
}
@@ -319,16 +406,16 @@ private:
// draw_aa_pixel - draw an antialiased pixel
//-------------------------------------------------
- static inline void draw_aa_pixel(_PixelType *dstdata, u32 pitch, int x, int y, u32 col)
+ static inline void draw_aa_pixel(PixelType *dstdata, u32 pitch, int x, int y, u32 col)
{
- _PixelType *dest = dstdata + y * pitch + x;
- u32 dpix = _NoDestRead ? 0 : *dest;
+ PixelType *dest = dstdata + y * pitch + x;
+ u32 dpix = NoDestRead ? 0 : *dest;
u32 dr = source32_r(col) + dest_r(dpix);
u32 dg = source32_g(col) + dest_g(dpix);
u32 db = source32_b(col) + dest_b(dpix);
- dr = (dr | -(dr >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- dg = (dg | -(dg >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- db = (db | -(db >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ dr = (dr | -(dr >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ dg = (dg | -(dg >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ db = (db | -(db >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(dr, dg, db);
}
@@ -337,7 +424,7 @@ private:
// draw_line - draw a line or point
//-------------------------------------------------
- static void draw_line(const render_primitive &prim, _PixelType *dstdata, s32 width, s32 height, u32 pitch)
+ static void draw_line(render_primitive const &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch)
{
// internal tables
static u32 s_cosine_table[2049];
@@ -498,77 +585,58 @@ private:
// draw_rect - draw a solid rectangle
//-------------------------------------------------
- static void draw_rect(const render_primitive &prim, _PixelType *dstdata, s32 width, s32 height, u32 pitch)
+ static void draw_rect(render_primitive const &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch)
{
- render_bounds fpos = prim.bounds;
+ render_bounds const fpos = prim.bounds;
assert(fpos.x0 <= fpos.x1);
assert(fpos.y0 <= fpos.y1);
- // clamp to integers
- s32 startx = round_nearest(fpos.x0);
- s32 starty = round_nearest(fpos.y0);
- s32 endx = round_nearest(fpos.x1);
- s32 endy = round_nearest(fpos.y1);
-
- // ensure we fit
- if (startx < 0) startx = 0;
- if (startx >= width) startx = width;
- if (endx < 0) endx = 0;
- if (endx >= width) endx = width;
- if (starty < 0) starty = 0;
- if (starty >= height) starty = height;
- if (endy < 0) endy = 0;
- if (endy >= height) endy = height;
+ // clamp to integers and ensure we fit
+ s32 const startx = std::clamp<s32>(round_nearest(fpos.x0), 0, width);
+ s32 const starty = std::clamp<s32>(round_nearest(fpos.y0), 0, height);
+ s32 const endx = std::clamp<s32>(round_nearest(fpos.x1), 0, width);
+ s32 const endy = std::clamp<s32>(round_nearest(fpos.y1), 0, height);
// bail if nothing left
- if (fpos.x0 > fpos.x1 || fpos.y0 > fpos.y1)
+ if ((startx > endx) || (starty > endy))
return;
// only support alpha and "none" blendmodes
assert(PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE ||
PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_ALPHA);
- // fast case: no alpha
- if (PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE || is_opaque(prim.color.a))
+ if ((PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE) || is_opaque(prim.color.a))
{
- u32 r = u32(256.0f * prim.color.r);
- u32 g = u32(256.0f * prim.color.g);
- u32 b = u32(256.0f * prim.color.b);
- u32 pix;
+ // fast case: no alpha
// clamp R,G,B to 0-256 range
- if (r > 0xff) { if (s32(r) < 0) r = 0; else r = 0xff; }
- if (g > 0xff) { if (s32(g) < 0) g = 0; else g = 0xff; }
- if (b > 0xff) { if (s32(b) < 0) b = 0; else b = 0xff; }
- pix = dest_rgb_to_pixel(r, g, b);
+ u32 const r = u32(std::clamp(256.0f * prim.color.r, 0.0f, 255.0f));
+ u32 const g = u32(std::clamp(256.0f * prim.color.g, 0.0f, 255.0f));
+ u32 const b = u32(std::clamp(256.0f * prim.color.b, 0.0f, 255.0f));
+ u32 const pix = dest_rgb_to_pixel(r, g, b);
// loop over rows
for (s32 y = starty; y < endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + startx;
+ PixelType *dest = dstdata + y * pitch + startx;
// loop over cols
for (s32 x = startx; x < endx; x++)
*dest++ = pix;
}
}
-
- // alpha and/or coloring case
else if (!is_transparent(prim.color.a))
{
- u32 rmask = dest_rgb_to_pixel(0xff,0x00,0x00);
- u32 gmask = dest_rgb_to_pixel(0x00,0xff,0x00);
- u32 bmask = dest_rgb_to_pixel(0x00,0x00,0xff);
- u32 r = u32(256.0f * prim.color.r * prim.color.a);
- u32 g = u32(256.0f * prim.color.g * prim.color.a);
- u32 b = u32(256.0f * prim.color.b * prim.color.a);
- u32 inva = u32(256.0f * (1.0f - prim.color.a));
+ // alpha and/or coloring case
+ u32 const rmask = dest_rgb_to_pixel(0xff,0x00,0x00);
+ u32 const gmask = dest_rgb_to_pixel(0x00,0xff,0x00);
+ u32 const bmask = dest_rgb_to_pixel(0x00,0x00,0xff);
// clamp R,G,B and inverse A to 0-256 range
- if (r > 0xff) { if (s32(r) < 0) r = 0; else r = 0xff; }
- if (g > 0xff) { if (s32(g) < 0) g = 0; else g = 0xff; }
- if (b > 0xff) { if (s32(b) < 0) b = 0; else b = 0xff; }
- if (inva > 0x100) { if (s32(inva) < 0) inva = 0; else inva = 0x100; }
+ u32 r = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 255.0f));
+ u32 g = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 255.0f));
+ u32 b = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 255.0f));
+ u32 const inva = u32(std::clamp(256.0f * (1.0f - prim.color.a), 0.0f, 256.0f));
// pre-shift the RGBA pieces
r = dest_rgb_to_pixel(r, 0, 0) << 8;
@@ -578,12 +646,12 @@ private:
// loop over rows
for (s32 y = starty; y < endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + startx;
+ PixelType *dest = dstdata + y * pitch + startx;
// loop over cols
for (s32 x = startx; x < endx; x++)
{
- u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 dpix = NoDestRead ? 0 : *dest;
u32 dr = (r + ((dpix & rmask) * inva)) & (rmask << 8);
u32 dg = (g + ((dpix & gmask) * inva)) & (gmask << 8);
u32 db = (b + ((dpix & bmask) * inva)) & (bmask << 8);
@@ -603,58 +671,55 @@ private:
// rasterization of a 16bpp palettized texture
//-------------------------------------------------
- static void draw_quad_palette16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data &setup)
+ static void draw_quad_palette16_none(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
// ensure all parameters are valid
assert(prim.texture.palette != nullptr);
- // fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_palette16(prim.texture, curu, curv);
+ u32 const pix = get_texel_palette16(prim.texture, curu, curv);
*dest++ = source32_to_dest(pix);
curu += setup.dudx;
curv += setup.dvdx;
}
}
}
-
- // coloring-only case
else if (is_opaque(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
+ // coloring-only case
// clamp R,G,B to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_palette16(prim.texture, curu, curv);
- const u32 r = (source32_r(pix) * sr) >> 8;
- const u32 g = (source32_g(pix) * sg) >> 8;
- const u32 b = (source32_b(pix) * sb) >> 8;
+ u32 const pix = get_texel_palette16(prim.texture, curu, curv);
+ u32 const r = (source32_r(pix) * sr) >> 8;
+ u32 const g = (source32_g(pix) * sg) >> 8;
+ u32 const b = (source32_b(pix) * sb) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -662,36 +727,31 @@ private:
}
}
}
-
- // alpha and/or coloring case
else if (!is_transparent(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r * prim.color.a);
- u32 sg = u32(256.0f * prim.color.g * prim.color.a);
- u32 sb = u32(256.0f * prim.color.b * prim.color.a);
- u32 invsa = u32(256.0f * (1.0f - prim.color.a));
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (invsa > 0x100) { if (s32(invsa) < 0) invsa = 0; else invsa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f));
+ u32 const invsa = u32(std::clamp(256.0f * (1.0f - prim.color.a), 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_palette16(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
+ u32 const pix = get_texel_palette16(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
+ u32 const g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
+ u32 const b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -707,18 +767,19 @@ private:
// rasterization of a 16bpp palettized texture
//-------------------------------------------------
- static void draw_quad_palette16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ static void draw_quad_palette16_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
// ensure all parameters are valid
assert(prim.texture.palette != nullptr);
- // fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
@@ -728,13 +789,13 @@ private:
const u32 pix = get_texel_palette16(prim.texture, curu, curv);
if ((pix & 0xffffff) != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = source32_r(pix) + dest_r(dpix);
u32 g = source32_g(pix) + dest_g(dpix);
u32 b = source32_b(pix) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(r, g, b);
}
dest++;
@@ -743,39 +804,35 @@ private:
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r * prim.color.a);
- u32 sg = u32(256.0f * prim.color.g * prim.color.a);
- u32 sb = u32(256.0f * prim.color.b * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_palette16(prim.texture, curu, curv);
+ u32 const pix = get_texel_palette16(prim.texture, curu, curv);
if ((pix & 0xffffff) != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = ((source32_r(pix) * sr) >> 8) + dest_r(dpix);
u32 g = ((source32_g(pix) * sg) >> 8) + dest_g(dpix);
u32 b = ((source32_b(pix) * sb) >> 8) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
@@ -796,55 +853,52 @@ private:
// rasterization of a 16bpp YUY image
//-------------------------------------------------
- static void draw_quad_yuy16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ static void draw_quad_yuy16_none(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- // fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
+ u32 const pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
*dest++ = source32_to_dest(pix);
curu += setup.dudx;
curv += setup.dvdx;
}
}
}
-
- // coloring-only case
else if (is_opaque(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
+ // coloring-only case
// clamp R,G,B to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- const u32 r = (source32_r(pix) * sr) >> 8;
- const u32 g = (source32_g(pix) * sg) >> 8;
- const u32 b = (source32_b(pix) * sb) >> 8;
+ u32 const pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
+ u32 const r = (source32_r(pix) * sr) >> 8;
+ u32 const g = (source32_g(pix) * sg) >> 8;
+ u32 const b = (source32_b(pix) * sb) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -852,36 +906,31 @@ private:
}
}
}
-
- // alpha and/or coloring case
else if (!is_transparent(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r * prim.color.a);
- u32 sg = u32(256.0f * prim.color.g * prim.color.a);
- u32 sb = u32(256.0f * prim.color.b * prim.color.a);
- u32 invsa = u32(256.0f * (1.0f - prim.color.a));
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (invsa > 0x100) { if (s32(invsa) < 0) invsa = 0; else invsa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f));
+ u32 const invsa = u32(std::clamp(256.0f * (1.0f - prim.color.a), 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
+ u32 const pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
+ u32 const g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
+ u32 const b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -898,58 +947,54 @@ private:
// conversion
//-------------------------------------------------
- static void draw_quad_yuy16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ static void draw_quad_yuy16_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
// simply can't do this without reading from the dest
- if (_NoDestRead)
+ if constexpr (NoDestRead)
return;
- // fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = source32_r(pix) + dest_r(dpix);
u32 g = source32_g(pix) + dest_g(dpix);
u32 b = source32_b(pix) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
- u32 sa = u32(256.0f * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
+ u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
@@ -957,13 +1002,13 @@ private:
for (s32 x = setup.startx; x < setup.endx; x++)
{
const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ const u32 dpix = NoDestRead ? 0 : *dest;
u32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix);
u32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix);
u32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
@@ -982,9 +1027,10 @@ private:
// a 32bpp RGB texture
//-------------------------------------------------
- static void draw_quad_rgb32(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ template <bool Wrap>
+ static void draw_quad_rgb32(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- const rgb_t *palbase = prim.texture.palette;
+ rgb_t const *const palbase = prim.texture.palette;
// fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
@@ -992,33 +1038,34 @@ private:
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
*dest++ = source32_to_dest(pix);
curu += setup.dudx;
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- const u32 r = palbase[(pix >> 16) & 0xff] >> _SrcShiftR;
- const u32 g = palbase[(pix >> 8) & 0xff] >> _SrcShiftG;
- const u32 b = palbase[(pix >> 0) & 0xff] >> _SrcShiftB;
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
+ u32 const r = palbase[(pix >> 16) & 0xff] >> SrcShiftR;
+ u32 const g = palbase[(pix >> 8) & 0xff] >> SrcShiftG;
+ u32 const b = palbase[(pix >> 0) & 0xff] >> SrcShiftB;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1027,53 +1074,50 @@ private:
}
}
}
-
- // coloring-only case
else if (is_opaque(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
+ // coloring-only case
// clamp R,G,B to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- const u32 r = (source32_r(pix) * sr) >> 8;
- const u32 g = (source32_g(pix) * sg) >> 8;
- const u32 b = (source32_b(pix) * sb) >> 8;
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
+ u32 const r = (source32_r(pix) * sr) >> 8;
+ u32 const g = (source32_g(pix) * sg) >> 8;
+ u32 const b = (source32_b(pix) * sb) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- const u32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + _SrcShiftR);
- const u32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + _SrcShiftG);
- const u32 b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + _SrcShiftB);
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
+ u32 const r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + SrcShiftR);
+ u32 const g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + SrcShiftG);
+ u32 const b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1082,57 +1126,53 @@ private:
}
}
}
-
- // alpha and/or coloring case
else if (!is_transparent(prim.color.a))
{
- u32 sr = u32(256.0f * prim.color.r * prim.color.a);
- u32 sg = u32(256.0f * prim.color.g * prim.color.a);
- u32 sb = u32(256.0f * prim.color.b * prim.color.a);
- u32 invsa = u32(256.0f * (1.0f - prim.color.a));
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (invsa > 0x100) { if (s32(invsa) < 0) invsa = 0; else invsa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f));
+ u32 const invsa = u32(std::clamp(256.0f * (1.0f - prim.color.a), 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
+ u32 const g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
+ u32 const b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8;
- const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8;
- const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8;
+ u32 const pix = get_texel_rgb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8;
+ u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8;
+ u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1149,58 +1189,61 @@ private:
// rasterization by using RGB add
//-------------------------------------------------
- static void draw_quad_rgb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ template <bool Wrap>
+ static void draw_quad_rgb32_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- const rgb_t *palbase = prim.texture.palette;
-
// simply can't do this without reading from the dest
- if (_NoDestRead)
+ if (NoDestRead)
return;
- // fast case: no coloring, no alpha
+ rgb_t const *const palbase = prim.texture.palette;
+
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = source32_r(pix) + dest_r(dpix);
u32 g = source32_g(pix) + dest_g(dpix);
u32 b = source32_b(pix) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (palbase[(pix >> 16) & 0xff] >> _SrcShiftR) + dest_r(dpix);
- u32 g = (palbase[(pix >> 8) & 0xff] >> _SrcShiftG) + dest_g(dpix);
- u32 b = (palbase[(pix >> 0) & 0xff] >> _SrcShiftB) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 r = (palbase[(pix >> 16) & 0xff] >> SrcShiftR) + dest_r(dpix);
+ u32 g = (palbase[(pix >> 8) & 0xff] >> SrcShiftG) + dest_g(dpix);
+ u32 b = (palbase[(pix >> 0) & 0xff] >> SrcShiftB) + dest_b(dpix);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
@@ -1208,62 +1251,58 @@ private:
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
- u32 sa = u32(256.0f * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
+ u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix);
u32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix);
u32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_r(dpix);
- u32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_g(dpix);
- u32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_r(dpix);
+ u32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_g(dpix);
+ u32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_b(dpix);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
curv += setup.dvdx;
@@ -1279,35 +1318,38 @@ private:
// rasterization using RGB multiply
//-------------------------------------------------
- static void draw_quad_rgb32_multiply(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ template <bool Wrap>
+ static void draw_quad_rgb32_multiply(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- const rgb_t *palbase = prim.texture.palette;
-
// simply can't do this without reading from the dest
- if (_NoDestRead)
+ if (NoDestRead)
return;
- // fast case: no coloring, no alpha
+ rgb_t const *const palbase = prim.texture.palette;
+
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (source32_r(pix) * dest_r(dpix)) >> (8 - _SrcShiftR);
- const u32 g = (source32_g(pix) * dest_g(dpix)) >> (8 - _SrcShiftG);
- const u32 b = (source32_b(pix) * dest_b(dpix)) >> (8 - _SrcShiftB);
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (source32_r(pix) * dest_r(dpix)) >> (8 - SrcShiftR);
+ u32 const g = (source32_g(pix) * dest_g(dpix)) >> (8 - SrcShiftG);
+ u32 const b = (source32_b(pix) * dest_b(dpix)) >> (8 - SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1316,14 +1358,16 @@ private:
}
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8;
- const u32 g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8;
- const u32 b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8;
+ u32 const g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8;
+ u32 const b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1332,37 +1376,34 @@ private:
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r * prim.color.a);
- u32 sg = u32(256.0f * prim.color.g * prim.color.a);
- u32 sb = u32(256.0f * prim.color.b * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - _SrcShiftR);
- const u32 g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - _SrcShiftG);
- const u32 b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - _SrcShiftB);
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - SrcShiftR);
+ u32 const g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - SrcShiftG);
+ u32 const b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - SrcShiftB);
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1371,14 +1412,16 @@ private:
}
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16;
- const u32 g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16;
- const u32 b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16;
+ u32 const g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16;
+ u32 const b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16;
*dest++ = dest_assemble_rgb(r, g, b);
curu += setup.dudx;
@@ -1399,35 +1442,38 @@ private:
// rasterization using standard alpha blending
//-------------------------------------------------
- static void draw_quad_argb32_alpha(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ template <bool Wrap>
+ static void draw_quad_argb32_alpha(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- const rgb_t *palbase = prim.texture.palette;
+ rgb_t const *const palbase = prim.texture.palette;
- // fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
+ // fast case: no coloring, no alpha
+
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 invta = 0x100 - ta;
- const u32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
- const u32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
- const u32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const invta = 0x100 - ta;
+ u32 const r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
+ u32 const g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
+ u32 const b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
*dest = dest_assemble_rgb(r, g, b);
}
@@ -1436,22 +1482,22 @@ private:
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 invta = 0x100 - ta;
- const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * ta + dest_r(dpix) * invta) >> 8;
- const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * ta + dest_g(dpix) * invta) >> 8;
- const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * ta + dest_b(dpix) * invta) >> 8;
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const invta = 0x100 - ta;
+ u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * ta + dest_r(dpix) * invta) >> 8;
+ u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * ta + dest_g(dpix) * invta) >> 8;
+ u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * ta + dest_b(dpix) * invta) >> 8;
*dest = dest_assemble_rgb(r, g, b);
}
@@ -1462,43 +1508,39 @@ private:
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
- u32 sa = u32(256.0f * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
+ u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = (pix >> 24) * sa;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = (pix >> 24) * sa;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 invsta = (0x10000 - ta) << 8;
- const u32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
- const u32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
- const u32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const invsta = (0x10000 - ta) << 8;
+ u32 const r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
+ u32 const g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
+ u32 const b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
*dest = dest_assemble_rgb(r, g, b);
}
@@ -1507,23 +1549,22 @@ private:
curv += setup.dvdx;
}
}
-
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = (pix >> 24) * sa;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = (pix >> 24) * sa;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- const u32 invsta = (0x10000 - ta) << 8;
- const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24;
- const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24;
- const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24;
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 const invsta = (0x10000 - ta) << 8;
+ u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24;
+ u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24;
+ u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24;
*dest = dest_assemble_rgb(r, g, b);
}
@@ -1542,41 +1583,43 @@ private:
// rasterization by using RGB add
//-------------------------------------------------
- static void draw_quad_argb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup)
+ template <bool Wrap>
+ static void draw_quad_argb32_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup)
{
- const rgb_t *palbase = prim.texture.palette;
-
// simply can't do this without reading from the dest
- if (_NoDestRead)
+ if (NoDestRead)
return;
+ rgb_t const *const palbase = prim.texture.palette;
+
// fast case: no coloring, no alpha
if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
{
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = ((source32_r(pix) * ta) >> 8) + dest_r(dpix);
u32 g = ((source32_g(pix) * ta) >> 8) + dest_g(dpix);
u32 b = ((source32_b(pix) * ta) >> 8) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(r, g, b);
}
dest++;
@@ -1584,24 +1627,24 @@ private:
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + _SrcShiftR)) + dest_r(dpix);
- u32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + _SrcShiftG)) + dest_g(dpix);
- u32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + _SrcShiftB)) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + SrcShiftR)) + dest_r(dpix);
+ u32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + SrcShiftG)) + dest_g(dpix);
+ u32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + SrcShiftB)) + dest_b(dpix);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(r, g, b);
}
dest++;
@@ -1611,45 +1654,41 @@ private:
}
}
}
-
- // alpha and/or coloring case
else
{
- u32 sr = u32(256.0f * prim.color.r);
- u32 sg = u32(256.0f * prim.color.g);
- u32 sb = u32(256.0f * prim.color.b);
- u32 sa = u32(256.0f * prim.color.a);
+ // alpha and/or coloring case
// clamp R,G,B and inverse A to 0-256 range
- if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; }
- if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; }
- if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; }
- if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; }
+ u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f));
+ u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f));
+ u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f));
+ u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f));
// loop over rows
for (s32 y = setup.starty; y < setup.endy; y++)
{
- _PixelType *dest = dstdata + y * pitch + setup.startx;
+ PixelType *dest = dstdata + y * pitch + setup.startx;
s32 curu = setup.startu + (y - setup.starty) * setup.dudy;
s32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = (pix >> 24) * sa;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = (pix >> 24) * sa;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
+ u32 const dpix = NoDestRead ? 0 : *dest;
u32 r = ((source32_r(pix) * sr * ta) >> 24) + dest_r(dpix);
u32 g = ((source32_g(pix) * sg * ta) >> 24) + dest_g(dpix);
u32 b = ((source32_b(pix) * sb * ta) >> 24) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(r, g, b);
}
dest++;
@@ -1657,24 +1696,24 @@ private:
curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
for (s32 x = setup.startx; x < setup.endx; x++)
{
- const u32 pix = get_texel_argb32(prim.texture, curu, curv);
- const u32 ta = (pix >> 24) * sa;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = (pix >> 24) * sa;
if (ta != 0)
{
- const u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_r(dpix);
- u32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_g(dpix);
- u32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_b(dpix);
- r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
- g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
- b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
+ u32 const dpix = NoDestRead ? 0 : *dest;
+ u32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_r(dpix);
+ u32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_g(dpix);
+ u32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_b(dpix);
+ r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR);
+ g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG);
+ b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB);
*dest = dest_assemble_rgb(r, g, b);
}
dest++;
@@ -1697,16 +1736,16 @@ private:
// drawing routine
//-------------------------------------------------
- static void setup_and_draw_textured_quad(const render_primitive &prim, _PixelType *dstdata, s32 width, s32 height, u32 pitch)
+ static void setup_and_draw_textured_quad(render_primitive const &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch)
{
assert(prim.bounds.x0 <= prim.bounds.x1);
assert(prim.bounds.y0 <= prim.bounds.y1);
// determine U/V deltas
- float fdudx = (prim.texcoords.tr.u - prim.texcoords.tl.u) / (prim.bounds.x1 - prim.bounds.x0);
- float fdvdx = (prim.texcoords.tr.v - prim.texcoords.tl.v) / (prim.bounds.x1 - prim.bounds.x0);
- float fdudy = (prim.texcoords.bl.u - prim.texcoords.tl.u) / (prim.bounds.y1 - prim.bounds.y0);
- float fdvdy = (prim.texcoords.bl.v - prim.texcoords.tl.v) / (prim.bounds.y1 - prim.bounds.y0);
+ float const fdudx = (prim.texcoords.tr.u - prim.texcoords.tl.u) / (prim.bounds.x1 - prim.bounds.x0);
+ float const fdvdx = (prim.texcoords.tr.v - prim.texcoords.tl.v) / (prim.bounds.x1 - prim.bounds.x0);
+ float const fdudy = (prim.texcoords.bl.u - prim.texcoords.tl.u) / (prim.bounds.y1 - prim.bounds.y0);
+ float const fdvdy = (prim.texcoords.bl.v - prim.texcoords.tl.v) / (prim.bounds.y1 - prim.bounds.y0);
// clamp to integers
quad_setup_data setup;
@@ -1738,7 +1777,7 @@ private:
setup.startv += (setup.dvdx + setup.dvdy) / 2;
// if we're bilinear filtering, we need to offset u/v by half a texel
- if (_BilinearFilter)
+ if constexpr (BilinearFilter)
{
setup.startu -= 0x8000;
setup.startv -= 0x8000;
@@ -1768,24 +1807,39 @@ private:
case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
- draw_quad_rgb32(prim, dstdata, pitch, setup);
+ if (PRIMFLAG_GET_TEXWRAP(prim.flags))
+ draw_quad_rgb32<true>(prim, dstdata, pitch, setup);
+ else
+ draw_quad_rgb32<false>(prim, dstdata, pitch, setup);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
- draw_quad_rgb32_multiply(prim, dstdata, pitch, setup);
+ if (PRIMFLAG_GET_TEXWRAP(prim.flags))
+ draw_quad_rgb32_multiply<true>(prim, dstdata, pitch, setup);
+ else
+ draw_quad_rgb32_multiply<false>(prim, dstdata, pitch, setup);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
- draw_quad_rgb32_add(prim, dstdata, pitch, setup);
+ if (PRIMFLAG_GET_TEXWRAP(prim.flags))
+ draw_quad_rgb32_add<true>(prim, dstdata, pitch, setup);
+ else
+ draw_quad_rgb32_add<false>(prim, dstdata, pitch, setup);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
- draw_quad_argb32_alpha(prim, dstdata, pitch, setup);
+ if (PRIMFLAG_GET_TEXWRAP(prim.flags))
+ draw_quad_argb32_alpha<true>(prim, dstdata, pitch, setup);
+ else
+ draw_quad_argb32_alpha<false>(prim, dstdata, pitch, setup);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
- draw_quad_argb32_add(prim, dstdata, pitch, setup);
+ if (PRIMFLAG_GET_TEXWRAP(prim.flags))
+ draw_quad_argb32_add<true>(prim, dstdata, pitch, setup);
+ else
+ draw_quad_argb32_add<false>(prim, dstdata, pitch, setup);
break;
default:
@@ -1805,21 +1859,21 @@ private:
//-------------------------------------------------
public:
- static void draw_primitives(const render_primitive_list &primlist, void *dstdata, u32 width, u32 height, u32 pitch)
+ static void draw_primitives(render_primitive_list const &primlist, void *dstdata, u32 width, u32 height, u32 pitch)
{
// loop over the list and render each element
- for (const render_primitive *prim = primlist.first(); prim != nullptr; prim = prim->next())
+ for (render_primitive const *prim = primlist.first(); prim != nullptr; prim = prim->next())
switch (prim->type)
{
case render_primitive::LINE:
- draw_line(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
+ draw_line(*prim, reinterpret_cast<PixelType *>(dstdata), width, height, pitch);
break;
case render_primitive::QUAD:
if (!prim->texture.base)
- draw_rect(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
+ draw_rect(*prim, reinterpret_cast<PixelType *>(dstdata), width, height, pitch);
else
- setup_and_draw_textured_quad(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
+ setup_and_draw_textured_quad(*prim, reinterpret_cast<PixelType *>(dstdata), width, height, pitch);
break;
default: