From d026c7736fac7026f72894ce2b7d7d44e6b21b9b Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 21 Nov 2021 02:16:51 +1100 Subject: emu/rendersw.hxx: Support texture wrap/clamp properly for (A)RGB formats. Also got rid of names starting with an underscore followed by an uppercase letter, as they are reserved. Yes, get_texel_rgb32 and get_texel_argb32 are identical - thew were already identical before. --- src/emu/rendersw.hxx | 799 ++++++++++++++++++++++++++++----------------------- 1 file changed, 443 insertions(+), 356 deletions(-) diff --git a/src/emu/rendersw.hxx b/src/emu/rendersw.hxx index db6b41f9bba..840f7fa5d8a 100644 --- a/src/emu/rendersw.hxx +++ b/src/emu/rendersw.hxx @@ -15,7 +15,7 @@ #include "render.h" -template +template class software_renderer { private: @@ -29,29 +29,29 @@ private: }; // internal helpers - 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 constexpr bool is_opaque(float alpha) { return (alpha >= (NoDestRead ? 0.5f : 1.0f)); } + static constexpr bool is_transparent(float alpha) { return (alpha < (NoDestRead ? 0.5f : 0.0001f)); } static inline rgb_t apply_intensity(int intensity, rgb_t color) { return color.scale8(intensity); } static inline float round_nearest(float f) { return floor(f + 0.5f); } // destination pixels are written based on the values of the template parameters - static 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); } + 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 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); } + 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 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); } + 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 constexpr _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)); @@ -69,7 +69,7 @@ private: 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 constexpr u32 ycc_to_rgb(u32 ycc) @@ -131,7 +131,7 @@ private: static inline u32 get_texel_palette16(const render_texinfo &texture, s32 curu, s32 curv) { const rgb_t *palbase = texture.palette; - if constexpr (_BilinearFilter) + if constexpr (BilinearFilter) { s32 u0 = curu >> 16; s32 u1 = 1; @@ -167,7 +167,7 @@ private: static inline u32 get_texel_palette16a(const render_texinfo &texture, s32 curu, s32 curv) { const rgb_t *palbase = texture.palette; - if constexpr (_BilinearFilter) + if constexpr (BilinearFilter) { s32 u0 = curu >> 16; s32 u1 = 1; @@ -198,7 +198,7 @@ private: static inline u32 get_texel_yuy16(const render_texinfo &texture, s32 curu, s32 curv) { - if constexpr (_BilinearFilter) + if constexpr (BilinearFilter) { s32 u0 = curu >> 16; s32 u1 = 1; @@ -258,28 +258,67 @@ private: // RGB source //------------------------------------------------- + template static inline u32 get_texel_rgb32(const render_texinfo &texture, s32 curu, s32 curv) { - if constexpr (_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(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(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(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(curu >> 16, 0, texture.width - 1); + v = std::clamp(curv >> 16, 0, texture.height - 1); + } + u32 const *const rowbase = reinterpret_cast(texture.base) + (v * texture.rowpixels); + return rowbase[u]; } } @@ -289,28 +328,67 @@ private: // ARGB source //------------------------------------------------- - static inline u32 get_texel_argb32(const render_texinfo &texture, s32 curu, s32 curv) + template + static inline u32 get_texel_argb32(render_texinfo const &texture, s32 curu, s32 curv) { - if constexpr (_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(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(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(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(curu >> 16, 0, texture.width - 1); + v = std::clamp(curv >> 16, 0, texture.height - 1); + } + u32 const *const rowbase = reinterpret_cast(texture.base) + (v * texture.rowpixels); + return rowbase[u]; } } @@ -319,16 +397,16 @@ private: // draw_aa_pixel - draw an antialiased pixel //------------------------------------------------- - static inline void draw_aa_pixel(_PixelType *dstdata, u32 pitch, int x, int y, u32 col) + static inline void draw_aa_pixel(PixelType *dstdata, u32 pitch, int x, int y, u32 col) { - _PixelType *dest = dstdata + y * pitch + x; - u32 dpix = _NoDestRead ? 0 : *dest; + PixelType *dest = dstdata + y * pitch + x; + u32 dpix = NoDestRead ? 0 : *dest; u32 dr = source32_r(col) + dest_r(dpix); u32 dg = source32_g(col) + dest_g(dpix); u32 db = source32_b(col) + dest_b(dpix); - dr = (dr | -(dr >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - dg = (dg | -(dg >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - db = (db | -(db >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + dr = (dr | -(dr >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + dg = (dg | -(dg >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + db = (db | -(db >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest = dest_assemble_rgb(dr, dg, db); } @@ -337,7 +415,7 @@ private: // draw_line - draw a line or point //------------------------------------------------- - static void draw_line(const render_primitive &prim, _PixelType *dstdata, s32 width, s32 height, u32 pitch) + static void draw_line(const render_primitive &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch) { // internal tables static u32 s_cosine_table[2049]; @@ -498,7 +576,7 @@ 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(const render_primitive &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch) { render_bounds fpos = prim.bounds; assert(fpos.x0 <= fpos.x1); @@ -545,7 +623,7 @@ 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++) @@ -578,12 +656,12 @@ private: // loop over rows for (s32 y = starty; y < endy; y++) { - _PixelType *dest = dstdata + y * pitch + startx; + PixelType *dest = dstdata + y * pitch + startx; // loop over cols for (s32 x = startx; x < endx; x++) { - u32 dpix = _NoDestRead ? 0 : *dest; + u32 dpix = NoDestRead ? 0 : *dest; u32 dr = (r + ((dpix & rmask) * inva)) & (rmask << 8); u32 dg = (g + ((dpix & gmask) * inva)) & (gmask << 8); u32 db = (b + ((dpix & bmask) * inva)) & (bmask << 8); @@ -603,7 +681,7 @@ private: // rasterization of a 16bpp palettized texture //------------------------------------------------- - static void draw_quad_palette16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data &setup) + static void draw_quad_palette16_none(const render_primitive &prim, PixelType *dstdata, u32 pitch, const quad_setup_data &setup) { // ensure all parameters are valid assert(prim.texture.palette != nullptr); @@ -614,7 +692,7 @@ 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; @@ -644,7 +722,7 @@ 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; @@ -680,7 +758,7 @@ 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; @@ -688,7 +766,7 @@ private: for (s32 x = setup.startx; x < setup.endx; x++) { const u32 pix = get_texel_palette16(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; + const u32 dpix = NoDestRead ? 0 : *dest; const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8; const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8; const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8; @@ -707,7 +785,7 @@ private: // rasterization of a 16bpp palettized texture //------------------------------------------------- - static void draw_quad_palette16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + static void draw_quad_palette16_add(const render_primitive &prim, PixelType *dstdata, u32 pitch, const quad_setup_data&setup) { // ensure all parameters are valid assert(prim.texture.palette != nullptr); @@ -718,7 +796,7 @@ 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; @@ -728,13 +806,13 @@ private: const u32 pix = get_texel_palette16(prim.texture, curu, curv); if ((pix & 0xffffff) != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; + const 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); + 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++; @@ -759,7 +837,7 @@ 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; @@ -769,13 +847,13 @@ private: const u32 pix = get_texel_palette16(prim.texture, curu, curv); if ((pix & 0xffffff) != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; + const 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); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; @@ -796,7 +874,7 @@ private: // rasterization of a 16bpp YUY image //------------------------------------------------- - static void draw_quad_yuy16_none(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + static void draw_quad_yuy16_none(const render_primitive &prim, PixelType *dstdata, u32 pitch, const quad_setup_data&setup) { // fast case: no coloring, no alpha if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) @@ -804,7 +882,7 @@ 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; @@ -834,7 +912,7 @@ 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; @@ -870,7 +948,7 @@ 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; @@ -878,7 +956,7 @@ private: for (s32 x = setup.startx; x < setup.endx; x++) { const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv)); - const u32 dpix = _NoDestRead ? 0 : *dest; + const u32 dpix = NoDestRead ? 0 : *dest; const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8; const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8; const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8; @@ -898,10 +976,10 @@ private: // conversion //------------------------------------------------- - static void draw_quad_yuy16_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + static void draw_quad_yuy16_add(const render_primitive &prim, PixelType *dstdata, u32 pitch, const quad_setup_data&setup) { // simply can't do this without reading from the dest - if constexpr (_NoDestRead) + if constexpr (NoDestRead) return; // fast case: no coloring, no alpha @@ -910,7 +988,7 @@ 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; @@ -918,13 +996,13 @@ private: for (s32 x = setup.startx; x < setup.endx; x++) { const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv)); - const u32 dpix = _NoDestRead ? 0 : *dest; + const u32 dpix = NoDestRead ? 0 : *dest; u32 r = source32_r(pix) + dest_r(dpix); u32 g = source32_g(pix) + dest_g(dpix); u32 b = source32_b(pix) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; @@ -949,7 +1027,7 @@ 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; @@ -957,13 +1035,13 @@ private: for (s32 x = setup.startx; x < setup.endx; x++) { const u32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv)); - const u32 dpix = _NoDestRead ? 0 : *dest; + const u32 dpix = NoDestRead ? 0 : *dest; u32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix); u32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix); u32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; @@ -982,9 +1060,10 @@ private: // a 32bpp RGB texture //------------------------------------------------- - static void draw_quad_rgb32(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + template + static void draw_quad_rgb32(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup) { - const rgb_t *palbase = prim.texture.palette; + rgb_t const *const palbase = prim.texture.palette; // fast case: no coloring, no alpha if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) @@ -992,33 +1071,34 @@ private: // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); *dest++ = source32_to_dest(pix); curu += setup.dudx; curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); - const u32 r = palbase[(pix >> 16) & 0xff] >> _SrcShiftR; - const u32 g = palbase[(pix >> 8) & 0xff] >> _SrcShiftG; - const u32 b = palbase[(pix >> 0) & 0xff] >> _SrcShiftB; + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const r = palbase[(pix >> 16) & 0xff] >> SrcShiftR; + u32 const g = palbase[(pix >> 8) & 0xff] >> SrcShiftG; + u32 const b = palbase[(pix >> 0) & 0xff] >> SrcShiftB; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1027,53 +1107,50 @@ private: } } } - - // coloring-only case else if (is_opaque(prim.color.a)) { - u32 sr = u32(256.0f * prim.color.r); - u32 sg = u32(256.0f * prim.color.g); - u32 sb = u32(256.0f * prim.color.b); + // coloring-only case // clamp R,G,B to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } + u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f)); + u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f)); + u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); - const u32 r = (source32_r(pix) * sr) >> 8; - const u32 g = (source32_g(pix) * sg) >> 8; - const u32 b = (source32_b(pix) * sb) >> 8; + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const r = (source32_r(pix) * sr) >> 8; + u32 const g = (source32_g(pix) * sg) >> 8; + u32 const b = (source32_b(pix) * sb) >> 8; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); - const u32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + _SrcShiftR); - const u32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + _SrcShiftG); - const u32 b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + _SrcShiftB); + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + SrcShiftR); + u32 const g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + SrcShiftG); + u32 const b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1082,57 +1159,53 @@ private: } } } - - // alpha and/or coloring case else if (!is_transparent(prim.color.a)) { - u32 sr = u32(256.0f * prim.color.r * prim.color.a); - u32 sg = u32(256.0f * prim.color.g * prim.color.a); - u32 sb = u32(256.0f * prim.color.b * prim.color.a); - u32 invsa = u32(256.0f * (1.0f - prim.color.a)); + // alpha and/or coloring case // clamp R,G,B and inverse A to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } - if (invsa > 0x100) { if (s32(invsa) < 0) invsa = 0; else invsa = 0x100; } + u32 sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f)); + u32 sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f)); + u32 sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f)); + u32 invsa = u32(std::clamp(256.0f * (1.0f - prim.color.a), 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8; - const u32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8; - const u32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8; + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8; + u32 const g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8; + u32 const b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_rgb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8; - const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8; - const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8; + u32 const pix = get_texel_rgb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8; + u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8; + u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1149,58 +1222,61 @@ private: // rasterization by using RGB add //------------------------------------------------- - static void draw_quad_rgb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + template + static void draw_quad_rgb32_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup) { - const rgb_t *palbase = prim.texture.palette; - // simply can't do this without reading from the dest - if (_NoDestRead) + if (NoDestRead) return; - // fast case: no coloring, no alpha + rgb_t const *const palbase = prim.texture.palette; + if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) { + // fast case: no coloring, no alpha + // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; u32 r = source32_r(pix) + dest_r(dpix); u32 g = source32_g(pix) + dest_g(dpix); u32 b = source32_b(pix) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - u32 r = (palbase[(pix >> 16) & 0xff] >> _SrcShiftR) + dest_r(dpix); - u32 g = (palbase[(pix >> 8) & 0xff] >> _SrcShiftG) + dest_g(dpix); - u32 b = (palbase[(pix >> 0) & 0xff] >> _SrcShiftB) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 r = (palbase[(pix >> 16) & 0xff] >> SrcShiftR) + dest_r(dpix); + u32 g = (palbase[(pix >> 8) & 0xff] >> SrcShiftG) + dest_g(dpix); + u32 b = (palbase[(pix >> 0) & 0xff] >> SrcShiftB) + dest_b(dpix); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; @@ -1208,62 +1284,58 @@ private: } } } - - // alpha and/or coloring case else { - u32 sr = u32(256.0f * prim.color.r); - u32 sg = u32(256.0f * prim.color.g); - u32 sb = u32(256.0f * prim.color.b); - u32 sa = u32(256.0f * prim.color.a); + // alpha and/or coloring case // clamp R,G,B and inverse A to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } - if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; } + u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f)); + u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f)); + u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f)); + u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; u32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix); u32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix); u32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - u32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_r(dpix); - u32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_g(dpix); - u32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_r(dpix); + u32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_g(dpix); + u32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + SrcShiftR)) + dest_b(dpix); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; curv += setup.dvdx; @@ -1279,35 +1351,38 @@ private: // rasterization using RGB multiply //------------------------------------------------- - static void draw_quad_rgb32_multiply(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + template + static void draw_quad_rgb32_multiply(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup) { - const rgb_t *palbase = prim.texture.palette; - // simply can't do this without reading from the dest - if (_NoDestRead) + if (NoDestRead) return; - // fast case: no coloring, no alpha + rgb_t const *const palbase = prim.texture.palette; + if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) { + // fast case: no coloring, no alpha + // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = (source32_r(pix) * dest_r(dpix)) >> (8 - _SrcShiftR); - const u32 g = (source32_g(pix) * dest_g(dpix)) >> (8 - _SrcShiftG); - const u32 b = (source32_b(pix) * dest_b(dpix)) >> (8 - _SrcShiftB); + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = (source32_r(pix) * dest_r(dpix)) >> (8 - SrcShiftR); + u32 const g = (source32_g(pix) * dest_g(dpix)) >> (8 - SrcShiftG); + u32 const b = (source32_b(pix) * dest_b(dpix)) >> (8 - SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1316,14 +1391,16 @@ private: } else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8; - const u32 g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8; - const u32 b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8; + u32 const g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8; + u32 const b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1332,37 +1409,34 @@ private: } } } - - // alpha and/or coloring case else { - u32 sr = u32(256.0f * prim.color.r * prim.color.a); - u32 sg = u32(256.0f * prim.color.g * prim.color.a); - u32 sb = u32(256.0f * prim.color.b * prim.color.a); + // alpha and/or coloring case // clamp R,G,B to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } + u32 const sr = u32(std::clamp(256.0f * prim.color.r * prim.color.a, 0.0f, 256.0f)); + u32 const sg = u32(std::clamp(256.0f * prim.color.g * prim.color.a, 0.0f, 256.0f)); + u32 const sb = u32(std::clamp(256.0f * prim.color.b * prim.color.a, 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - _SrcShiftR); - const u32 g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - _SrcShiftG); - const u32 b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - _SrcShiftB); + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - SrcShiftR); + u32 const g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - SrcShiftG); + u32 const b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - SrcShiftB); *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1371,14 +1445,16 @@ private: } else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16; - const u32 g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16; - const u32 b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16; + u32 const g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16; + u32 const b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16; *dest++ = dest_assemble_rgb(r, g, b); curu += setup.dudx; @@ -1399,35 +1475,38 @@ private: // rasterization using standard alpha blending //------------------------------------------------- - static void draw_quad_argb32_alpha(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + template + static void draw_quad_argb32_alpha(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup) { - const rgb_t *palbase = prim.texture.palette; + rgb_t const *const palbase = prim.texture.palette; - // fast case: no coloring, no alpha if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) { + // fast case: no coloring, no alpha + // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = pix >> 24; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = pix >> 24; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 invta = 0x100 - ta; - const u32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8; - const u32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8; - const u32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8; + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const invta = 0x100 - ta; + u32 const r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8; + u32 const g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8; + u32 const b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8; *dest = dest_assemble_rgb(r, g, b); } @@ -1436,22 +1515,22 @@ private: curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = pix >> 24; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = pix >> 24; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 invta = 0x100 - ta; - const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * ta + dest_r(dpix) * invta) >> 8; - const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * ta + dest_g(dpix) * invta) >> 8; - const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * ta + dest_b(dpix) * invta) >> 8; + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const invta = 0x100 - ta; + u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * ta + dest_r(dpix) * invta) >> 8; + u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * ta + dest_g(dpix) * invta) >> 8; + u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * ta + dest_b(dpix) * invta) >> 8; *dest = dest_assemble_rgb(r, g, b); } @@ -1462,43 +1541,39 @@ private: } } } - - // alpha and/or coloring case else { - u32 sr = u32(256.0f * prim.color.r); - u32 sg = u32(256.0f * prim.color.g); - u32 sb = u32(256.0f * prim.color.b); - u32 sa = u32(256.0f * prim.color.a); + // alpha and/or coloring case // clamp R,G,B and inverse A to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } - if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; } + u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f)); + u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f)); + u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f)); + u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = (pix >> 24) * sa; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = (pix >> 24) * sa; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 invsta = (0x10000 - ta) << 8; - const u32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24; - const u32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24; - const u32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24; + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const invsta = (0x10000 - ta) << 8; + u32 const r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24; + u32 const g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24; + u32 const b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24; *dest = dest_assemble_rgb(r, g, b); } @@ -1507,23 +1582,22 @@ private: curv += setup.dvdx; } } - - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = (pix >> 24) * sa; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = (pix >> 24) * sa; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - const u32 invsta = (0x10000 - ta) << 8; - const u32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24; - const u32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24; - const u32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24; + u32 const dpix = NoDestRead ? 0 : *dest; + u32 const invsta = (0x10000 - ta) << 8; + u32 const r = ((palbase[(pix >> 16) & 0xff] >> SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24; + u32 const g = ((palbase[(pix >> 8) & 0xff] >> SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24; + u32 const b = ((palbase[(pix >> 0) & 0xff] >> SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24; *dest = dest_assemble_rgb(r, g, b); } @@ -1542,41 +1616,43 @@ private: // rasterization by using RGB add //------------------------------------------------- - static void draw_quad_argb32_add(const render_primitive &prim, _PixelType *dstdata, u32 pitch, const quad_setup_data&setup) + template + static void draw_quad_argb32_add(render_primitive const &prim, PixelType *dstdata, u32 pitch, quad_setup_data const &setup) { - const rgb_t *palbase = prim.texture.palette; - // simply can't do this without reading from the dest - if (_NoDestRead) + if (NoDestRead) return; + rgb_t const *const palbase = prim.texture.palette; + // fast case: no coloring, no alpha if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a)) { // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = pix >> 24; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = pix >> 24; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; + u32 const dpix = NoDestRead ? 0 : *dest; u32 r = ((source32_r(pix) * ta) >> 8) + dest_r(dpix); u32 g = ((source32_g(pix) * ta) >> 8) + dest_g(dpix); u32 b = ((source32_b(pix) * ta) >> 8) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest = dest_assemble_rgb(r, g, b); } dest++; @@ -1584,24 +1660,24 @@ private: curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = pix >> 24; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = pix >> 24; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - u32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + _SrcShiftR)) + dest_r(dpix); - u32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + _SrcShiftG)) + dest_g(dpix); - u32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + _SrcShiftB)) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + SrcShiftR)) + dest_r(dpix); + u32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + SrcShiftG)) + dest_g(dpix); + u32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + SrcShiftB)) + dest_b(dpix); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest = dest_assemble_rgb(r, g, b); } dest++; @@ -1611,45 +1687,41 @@ private: } } } - - // alpha and/or coloring case else { - u32 sr = u32(256.0f * prim.color.r); - u32 sg = u32(256.0f * prim.color.g); - u32 sb = u32(256.0f * prim.color.b); - u32 sa = u32(256.0f * prim.color.a); + // alpha and/or coloring case // clamp R,G,B and inverse A to 0-256 range - if (sr > 0x100) { if (s32(sr) < 0) sr = 0; else sr = 0x100; } - if (sg > 0x100) { if (s32(sg) < 0) sg = 0; else sg = 0x100; } - if (sb > 0x100) { if (s32(sb) < 0) sb = 0; else sb = 0x100; } - if (sa > 0x100) { if (s32(sa) < 0) sa = 0; else sa = 0x100; } + u32 const sr = u32(std::clamp(256.0f * prim.color.r, 0.0f, 256.0f)); + u32 const sg = u32(std::clamp(256.0f * prim.color.g, 0.0f, 256.0f)); + u32 const sb = u32(std::clamp(256.0f * prim.color.b, 0.0f, 256.0f)); + u32 const sa = u32(std::clamp(256.0f * prim.color.a, 0.0f, 256.0f)); // loop over rows for (s32 y = setup.starty; y < setup.endy; y++) { - _PixelType *dest = dstdata + y * pitch + setup.startx; + PixelType *dest = dstdata + y * pitch + setup.startx; s32 curu = setup.startu + (y - setup.starty) * setup.dudy; s32 curv = setup.startv + (y - setup.starty) * setup.dvdy; - // no lookup case - if (palbase == nullptr) + if (!palbase) { + // no lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = (pix >> 24) * sa; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = (pix >> 24) * sa; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; + u32 const dpix = NoDestRead ? 0 : *dest; u32 r = ((source32_r(pix) * sr * ta) >> 24) + dest_r(dpix); u32 g = ((source32_g(pix) * sg * ta) >> 24) + dest_g(dpix); u32 b = ((source32_b(pix) * sb * ta) >> 24) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest = dest_assemble_rgb(r, g, b); } dest++; @@ -1657,24 +1729,24 @@ private: curv += setup.dvdx; } } - - // lookup case else { + // lookup case + // loop over cols for (s32 x = setup.startx; x < setup.endx; x++) { - const u32 pix = get_texel_argb32(prim.texture, curu, curv); - const u32 ta = (pix >> 24) * sa; + u32 const pix = get_texel_argb32(prim.texture, curu, curv); + u32 const ta = (pix >> 24) * sa; if (ta != 0) { - const u32 dpix = _NoDestRead ? 0 : *dest; - u32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_r(dpix); - u32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_g(dpix); - u32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_b(dpix); - r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR); - g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG); - b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB); + u32 const dpix = NoDestRead ? 0 : *dest; + u32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_r(dpix); + u32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_g(dpix); + u32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + SrcShiftR)) + dest_b(dpix); + r = (r | -(r >> (8 - SrcShiftR))) & (0xff >> SrcShiftR); + g = (g | -(g >> (8 - SrcShiftG))) & (0xff >> SrcShiftG); + b = (b | -(b >> (8 - SrcShiftB))) & (0xff >> SrcShiftB); *dest = dest_assemble_rgb(r, g, b); } dest++; @@ -1697,7 +1769,7 @@ 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(const render_primitive &prim, PixelType *dstdata, s32 width, s32 height, u32 pitch) { assert(prim.bounds.x0 <= prim.bounds.x1); assert(prim.bounds.y0 <= prim.bounds.y1); @@ -1738,7 +1810,7 @@ private: setup.startv += (setup.dvdx + setup.dvdy) / 2; // if we're bilinear filtering, we need to offset u/v by half a texel - if constexpr (_BilinearFilter) + if constexpr (BilinearFilter) { setup.startu -= 0x8000; setup.startv -= 0x8000; @@ -1768,24 +1840,39 @@ private: case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE): case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA): case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE): - draw_quad_rgb32(prim, dstdata, pitch, setup); + if (PRIMFLAG_GET_TEXWRAP(prim.flags)) + draw_quad_rgb32(prim, dstdata, pitch, setup); + else + draw_quad_rgb32(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(prim, dstdata, pitch, setup); + else + draw_quad_rgb32_multiply(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(prim, dstdata, pitch, setup); + else + draw_quad_rgb32_add(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(prim, dstdata, pitch, setup); + else + draw_quad_argb32_alpha(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(prim, dstdata, pitch, setup); + else + draw_quad_argb32_add(prim, dstdata, pitch, setup); break; default: @@ -1812,14 +1899,14 @@ public: switch (prim->type) { case render_primitive::LINE: - draw_line(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch); + draw_line(*prim, reinterpret_cast(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(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(dstdata), width, height, pitch); break; default: -- cgit v1.2.3