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.hxx1460
1 files changed, 684 insertions, 776 deletions
diff --git a/src/emu/rendersw.hxx b/src/emu/rendersw.hxx
index b1a032258d1..d4fde37566e 100644
--- a/src/emu/rendersw.hxx
+++ b/src/emu/rendersw.hxx
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- rendersw.inc
+ rendersw.hxx
Software-only rasterization system.
@@ -14,8 +14,9 @@
#include "video/rgbutil.h"
#include "render.h"
+#include <array>
-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 +30,34 @@ 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 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); }
+ template <int... Values>
+ static auto make_cosine_table(std::integer_sequence<int, Values...>)
+ {
+ return std::array<u32, sizeof...(Values)>{ u32((1.0 / cos(atan(double(Values) / double(sizeof...(Values) - 1)))) * 0x10000000 + 0.5)... };
+ }
+ 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 rgb_t apply_intensity(int intensity, rgb_t color) { return color.scale8(intensity); }
+ static 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 +73,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 +136,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 +148,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 +159,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 +175,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 +187,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 +210,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 +259,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 +273,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 +343,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 +412,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,10 +430,10 @@ 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];
+ // internal cosine table generated at compile time
+ static auto const s_cosine_table = make_cosine_table(std::make_integer_sequence<int, 2049>());
// compute the start/end coordinates
int x1 = int(prim.bounds.x0 * 65536.0f);
@@ -353,11 +446,6 @@ private:
if (PRIMFLAG_GET_ANTIALIAS(prim.flags))
{
- // build up the cosine table if we haven't yet
- if (s_cosine_table[0] == 0)
- for (int entry = 0; entry <= 2048; entry++)
- s_cosine_table[entry] = int(double(1.0 / cos(atan(double(entry) / 2048.0))) * 0x10000000 + 0.5);
-
int beam = prim.width * 65536.0f;
if (beam < 0x00010000)
beam = 0x00010000;
@@ -386,9 +474,9 @@ private:
draw_aa_pixel(dstdata, pitch, x1, dy, apply_intensity(0xff & (~y1 >> 8), col));
dy++;
dx -= 0x10000 - (0xffff & y1); // take off amount plotted
- u8 a1 = (dx >> 8) & 0xff; // calc remainder pixel
- dx >>= 16; // adjust to pixel (solid) count
- while (dx--) // plot rest of pixels
+ u8 a1 = (dx >> 8) & 0xff; // calc remainder pixel
+ dx >>= 16; // adjust to pixel (solid) count
+ while (dx--) // plot rest of pixels
{
if (dy >= 0 && dy < height)
draw_aa_pixel(dstdata, pitch, x1, dy, col);
@@ -422,9 +510,9 @@ private:
draw_aa_pixel(dstdata, pitch, dx, y1, apply_intensity(0xff & (~x1 >> 8), col));
dx++;
dy -= 0x10000 - (0xffff & x1); // take off amount plotted
- u8 a1 = (dy >> 8) & 0xff; // remainder pixel
- dy >>= 16; // adjust to pixel (solid) count
- while (dy--) // plot rest of pixels
+ u8 a1 = (dy >> 8) & 0xff; // remainder pixel
+ dy >>= 16; // adjust to pixel (solid) count
+ while (dy--) // plot rest of pixels
{
if (dx >= 0 && dx < width)
draw_aa_pixel(dstdata, pitch, dx, y1, col);
@@ -489,7 +577,6 @@ private:
}
-
//**************************************************************************
// RECT RASTERIZERS
//**************************************************************************
@@ -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);
@@ -595,111 +663,97 @@ private:
//**************************************************************************
- // 16-BIT PALETTE RASTERIZERS
+ // 16-BIT RASTERIZERS
//**************************************************************************
//-------------------------------------------------
- // draw_quad_palette16_none - perform
- // rasterization of a 16bpp palettized texture
+ // draw_quad_convert_none - perform
+ // rasterization of a texture after conversion
//-------------------------------------------------
- static void draw_quad_palette16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, quad_setup_data &setup)
+ template <typename T>
+ static void draw_quad_convert_none(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup, T &&gettexel)
{
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
- // 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_palette16(prim.texture, curu, curv);
+ u32 const pix = gettexel(prim, curu, curv);
*dest++ = source32_to_dest(pix);
- curu += dudx;
- curv += dvdx;
+ 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_palette16(prim.texture, curu, curv);
- u32 r = (source32_r(pix) * sr) >> 8;
- u32 g = (source32_g(pix) * sg) >> 8;
- u32 b = (source32_b(pix) * sb) >> 8;
+ u32 const pix = gettexel(prim, 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
-
- // 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_palette16(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
+ u32 const pix = gettexel(prim, 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -707,282 +761,62 @@ private:
//-------------------------------------------------
- // draw_quad_palette16_add - perform
- // rasterization of a 16bpp palettized texture
+ // draw_quad_convert_rop - perform rasterization
+ // by using RGB operation after conversion
//-------------------------------------------------
- static void draw_quad_palette16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, quad_setup_data &setup)
+ template <typename T, typename U, typename V>
+ static void draw_quad_convert_rop(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup, T &&gettexel, U &&notint, V &&tinted)
{
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
// 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))
- {
- // loop over rows
- for (s32 y = setup.starty; y < setup.endy; y++)
- {
- _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 < endx; x++)
- {
- u32 pix = get_texel_palette16(prim.texture, curu, curv);
- if ((pix & 0xffffff) != 0)
- {
- u32 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);
- *dest = dest_assemble_rgb(r, g, b);
- }
- dest++;
- curu += dudx;
- curv += dvdx;
- }
- }
- }
-
- // 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);
-
- // 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; }
-
- // loop over rows
- for (s32 y = setup.starty; y < setup.endy; y++)
- {
- _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 < endx; x++)
- {
- u32 pix = get_texel_palette16(prim.texture, curu, curv);
- if ((pix & 0xffffff) != 0)
- {
- u32 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);
- *dest++ = dest_assemble_rgb(r, g, b);
- curu += dudx;
- curv += dvdx;
- }
- }
- }
- }
- }
-
-
-
- //**************************************************************************
- // 16-BIT YUY RASTERIZERS
- //**************************************************************************
-
- //-------------------------------------------------
- // draw_quad_yuy16_none - perform
- // rasterization of a 16bpp YUY image
- //-------------------------------------------------
-
- static void draw_quad_yuy16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, quad_setup_data &setup)
- {
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
- // 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;
- 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 < endx; x++)
- {
- u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- *dest++ = source32_to_dest(pix);
- curu += dudx;
- curv += 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);
-
- // 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; }
+ // 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- u32 r = (source32_r(pix) * sr) >> 8;
- u32 g = (source32_g(pix) * sg) >> 8;
- u32 b = (source32_b(pix) * sb) >> 8;
-
- *dest++ = dest_assemble_rgb(r, g, b);
- curu += dudx;
- curv += dvdx;
- }
- }
- }
-
- // 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));
-
- // 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; }
-
- // loop over rows
- for (s32 y = setup.starty; y < setup.endy; y++)
- {
- _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 < endx; x++)
- {
- u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
-
- *dest++ = dest_assemble_rgb(r, g, b);
- curu += dudx;
- curv += dvdx;
- }
- }
- }
- }
-
-
- //-------------------------------------------------
- // draw_quad_yuy16_add - perform
- // rasterization by using RGB add after YUY
- // conversion
- //-------------------------------------------------
-
- static void draw_quad_yuy16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, quad_setup_data &setup)
- {
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
- // simply can't do this without reading from the dest
- if (_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))
- {
- // loop over rows
- for (s32 y = setup.starty; y < setup.endy; y++)
- {
- _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 < endx; x++)
- {
- u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- u32 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);
- *dest++ = dest_assemble_rgb(r, g, b);
- curu += dudx;
- curv += dvdx;
+ u32 const pix = gettexel(prim, curu, curv);
+ notint(*dest, pix);
+ dest++;
+ 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 * 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
- 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);
- *dest++ = dest_assemble_rgb(r, g, b);
- curu += dudx;
- curv += dvdx;
+ u32 const pix = gettexel(prim, curu, curv);
+ tinted(*dest, pix, sr, sg, sb);
+ dest++;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -998,12 +832,10 @@ private:
// a 32bpp RGB texture
//-------------------------------------------------
- static void draw_quad_rgb32(const render_primitive &prim, _PixelType *dstdata, u32 pitch, 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;
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
+ 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))
@@ -1011,151 +843,145 @@ 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- u32 r = palbase[(pix >> 16) & 0xff] >> _SrcShiftR;
- u32 g = palbase[(pix >> 8) & 0xff] >> _SrcShiftG;
- 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 += dudx;
- curv += dvdx;
+ 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;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- u32 r = (source32_r(pix) * sr) >> 8;
- u32 g = (source32_g(pix) * sg) >> 8;
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- u32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + _SrcShiftR);
- u32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + _SrcShiftG);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
}
-
- // 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
- u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_rgb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8;
- u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8;
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -1168,127 +994,127 @@ private:
// rasterization by using RGB add
//-------------------------------------------------
- static void draw_quad_rgb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, 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;
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
// 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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 += dudx;
- curv += dvdx;
+ 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;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -1301,113 +1127,114 @@ private:
// rasterization using RGB multiply
//-------------------------------------------------
- static void draw_quad_rgb32_multiply(const render_primitive &prim, _PixelType *dstdata, u32 pitch, 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;
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
// 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (source32_r(pix) * dest_r(dpix)) >> (8 - _SrcShiftR);
- u32 g = (source32_g(pix) * dest_g(dpix)) >> (8 - _SrcShiftG);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8;
- u32 g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8;
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
}
-
- // 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - _SrcShiftR);
- u32 g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - _SrcShiftG);
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16;
- u32 g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16;
- 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 += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -1424,140 +1251,135 @@ private:
// rasterization using standard alpha blending
//-------------------------------------------------
- static void draw_quad_argb32_alpha(const render_primitive &prim, _PixelType *dstdata, u32 pitch, 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;
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
+ 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 invta = 0x100 - ta;
- u32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
- u32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
- 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);
}
dest++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 invta = 0x100 - ta;
- u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * ta + dest_r(dpix) * invta) >> 8;
- u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * ta + dest_g(dpix) * invta) >> 8;
- 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);
}
dest++;
- curu += dudx;
- curv += dvdx;
+ 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;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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)
{
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 invsta = (0x10000 - ta) << 8;
- u32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
- u32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
- 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);
}
dest++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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)
{
- u32 dpix = _NoDestRead ? 0 : *dest;
- u32 invsta = (0x10000 - ta) << 8;
- u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24;
- u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24;
- 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);
}
dest++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -1570,147 +1392,142 @@ private:
// rasterization by using RGB add
//-------------------------------------------------
- static void draw_quad_argb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, 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;
- s32 dudx = setup.dudx;
- s32 dvdx = setup.dvdx;
- s32 endx = setup.endx;
-
// 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 < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- 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++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- u32 ta = pix >> 24;
+ u32 const pix = get_texel_argb32<Wrap>(prim.texture, curu, curv);
+ u32 const ta = pix >> 24;
if (ta != 0)
{
- 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++;
- curu += dudx;
- curv += dvdx;
+ 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;
- // no lookup case
- if (palbase == nullptr)
+ if (!palbase)
{
+ // no lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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)
{
- 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++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
-
- // lookup case
else
{
+ // lookup case
+
// loop over cols
- for (s32 x = setup.startx; x < endx; x++)
+ for (s32 x = setup.startx; x < setup.endx; x++)
{
- u32 pix = get_texel_argb32(prim.texture, curu, curv);
- 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)
{
- 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++;
- curu += dudx;
- curv += dvdx;
+ curu += setup.dudx;
+ curv += setup.dvdx;
}
}
}
@@ -1728,16 +1545,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;
@@ -1769,54 +1586,145 @@ 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;
}
+ auto const gettexel_palette16 =
+ [] (render_primitive const &prim, s32 u, s32 v) -> u32
+ {
+ return get_texel_palette16(prim.texture, u, v);
+ };
+ auto const gettexel_yuy16 =
+ [] (render_primitive const &prim, s32 u, s32 v) -> u32
+ {
+ return ycc_to_rgb(get_texel_yuy16(prim.texture, u, v));
+ };
+ auto const rop_mul_notint =
+ [] (PixelType &dest, u32 pix)
+ {
+ if ((pix & 0x00ff'ffff) != 0x00ff'ffff)
+ {
+ u32 const dpix = NoDestRead ? 0x00ff'ffff : 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);
+ }
+ };
+ auto const rop_mul_tinted =
+ [] (PixelType &dest, u32 pix, u32 sr, u32 sg, u32 sb)
+ {
+ if ((pix & 0x00ff'ffff) != 0x00ff'ffff)
+ {
+ u32 const dpix = NoDestRead ? 0x00ff'ffff : 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);
+ }
+ };
+ auto const rop_add_notint =
+ [] (PixelType &dest, u32 pix)
+ {
+ if ((pix & 0x00ff'ffff) != 0)
+ {
+ 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);
+ dest = dest_assemble_rgb(r, g, b);
+ }
+ };
+ auto const rop_add_tinted =
+ [] (PixelType &dest, u32 pix, u32 sr, u32 sg, u32 sb)
+ {
+ if ((pix & 0x00ff'ffff) != 0)
+ {
+ 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);
+ dest = dest_assemble_rgb(r, g, b);
+ }
+ };
+
// render based on the texture coordinates
switch (prim.flags & (PRIMFLAG_TEXFORMAT_MASK | PRIMFLAG_BLENDMODE_MASK))
{
case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
- draw_quad_palette16_none(prim, dstdata, pitch, setup);
+ assert(prim.texture.palette);
+ draw_quad_convert_none(prim, dstdata, pitch, setup, gettexel_palette16);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
+ assert(prim.texture.palette);
+ draw_quad_convert_rop(prim, dstdata, pitch, setup, gettexel_palette16, rop_mul_notint, rop_mul_tinted);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
- draw_quad_palette16_add(prim, dstdata, pitch, setup);
+ assert(prim.texture.palette);
+ draw_quad_convert_rop(prim, dstdata, pitch, setup, gettexel_palette16, rop_add_notint, rop_add_tinted);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
- draw_quad_yuy16_none(prim, dstdata, pitch, setup);
+ draw_quad_convert_none(prim, dstdata, pitch, setup, gettexel_yuy16);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
+ draw_quad_convert_rop(prim, dstdata, pitch, setup, gettexel_yuy16, rop_mul_notint, rop_mul_tinted);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
- draw_quad_yuy16_add(prim, dstdata, pitch, setup);
+ draw_quad_convert_rop(prim, dstdata, pitch, setup, gettexel_yuy16, rop_add_notint, rop_add_tinted);
break;
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:
@@ -1836,21 +1744,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: