diff options
Diffstat (limited to 'src/emu/rendersw.hxx')
-rw-r--r-- | src/emu/rendersw.hxx | 1460 |
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 &¬int, 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: |