From 7f908ce75dd46468ef7c9e5962de859da6adbc7d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 26 May 2018 14:27:54 +0200 Subject: [PATCH] - implement render styles for the softpoly span drawers --- src/polyrenderer/drawers/screen_triangle.cpp | 610 ++++++++++++++----- src/polyrenderer/drawers/screen_triangle.h | 44 +- 2 files changed, 498 insertions(+), 156 deletions(-) diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index c8731dc3e8..a43818c801 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -1163,7 +1163,8 @@ void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleT // Draw the triangle: - auto drawfunc = (args->destBgra) ? DrawSpan32 : DrawSpan8; + int bmode = (int)args->uniforms->BlendMode(); + auto drawfunc = args->destBgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode]; float stepXW = args->gradientX.W; float v1X = args->v1->x; @@ -1248,10 +1249,11 @@ void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleT } } -#ifndef NO_SSE - -void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args) +template +void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args) { + using namespace TriScreenDrawerModes; + float v1X = args->v1->x; float v1Y = args->v1->y; float v1W = args->v1->w; @@ -1267,127 +1269,12 @@ void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs float posXV = v1V + stepXV * startX + args->gradientY.V * startY; const uint32_t *texPixels = (const uint32_t*)args->uniforms->TexturePixels(); + const uint32_t *translation = (const uint32_t*)args->uniforms->Translation(); int texWidth = args->uniforms->TextureWidth(); int texHeight = args->uniforms->TextureHeight(); - bool is_fixed_light = args->uniforms->FixedLight(); - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - uint32_t light = args->uniforms->Light(); - float shade = 2.0f - (light + 12.0f) / 128.0f; - float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f); - light += light >> 7; // 255 -> 256 - - uint32_t *dest = (uint32_t*)args->dest; - uint32_t *destLine = dest + args->pitch * y; - - int x = x0; - int sseEnd = x0 + ((x1 - x0) & ~3); - while (x < sseEnd) - { - uint32_t fgcolor[2]; - int32_t lightshade[2]; - - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - fgcolor[0] = texPixels[texelX * texHeight + texelY]; - - fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - lightshade[0] = lightpos >> 8; - - posXW += stepXW; - posXU += stepXU; - posXV += stepXV; - - rcpW = 0x01000000 / posXW; - u = (int32_t)(posXU * rcpW); - v = (int32_t)(posXV * rcpW); - texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - fgcolor[1] = texPixels[texelX * texHeight + texelY]; - - lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - lightshade[1] = lightpos >> 8; - - posXW += stepXW; - posXU += stepXU; - posXV += stepXV; - - __m128i mfgcolor = _mm_loadl_epi64((const __m128i*)fgcolor); - mfgcolor = _mm_unpacklo_epi8(mfgcolor, _mm_setzero_si128()); - - __m128i mlightshade = _mm_loadl_epi64((const __m128i*)lightshade); - mlightshade = _mm_shuffle_epi32(mlightshade, _MM_SHUFFLE(1, 0, 1, 0)); - mlightshade = _mm_packs_epi32(mlightshade, mlightshade); - - __m128i mdestcolor = _mm_srli_epi16(_mm_mullo_epi16(mfgcolor, mlightshade), 8); - mdestcolor = _mm_packus_epi16(mdestcolor, _mm_setzero_si128()); - mdestcolor = _mm_or_si128(mdestcolor, _mm_set1_epi32(0xff000000)); - - _mm_storel_epi64((__m128i*)(destLine + x), mdestcolor); - - x += 2; - } - - while (x < x1) - { - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); - - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - uint32_t fgcolor = texPixels[texelX * texHeight + texelY]; - - uint32_t fgcolor_r = RPART(fgcolor); - uint32_t fgcolor_g = GPART(fgcolor); - uint32_t fgcolor_b = BPART(fgcolor); - uint32_t fgcolor_a = APART(fgcolor); - if (fgcolor_a > 127) - { - fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - int lightshade = lightpos >> 8; - - fgcolor_r = (fgcolor_r * lightshade) >> 8; - fgcolor_g = (fgcolor_g * lightshade) >> 8; - fgcolor_b = (fgcolor_b * lightshade) >> 8; - - destLine[x] = 0xff000000 | (fgcolor_r << 16) | (fgcolor_g << 8) | fgcolor_b; - } - - posXW += stepXW; - posXU += stepXU; - posXV += stepXV; - x++; - } -} - -#else - -void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args) -{ - float v1X = args->v1->x; - float v1Y = args->v1->y; - float v1W = args->v1->w; - float v1U = args->v1->u * v1W; - float v1V = args->v1->v * v1W; - float stepXW = args->gradientX.W; - float stepXU = args->gradientX.U; - float stepXV = args->gradientX.V; - float startX = x0 + (0.5f - v1X); - float startY = y + (0.5f - v1Y); - float posXW = v1W + stepXW * startX + args->gradientY.W * startY; - float posXU = v1U + stepXU * startX + args->gradientY.U * startY; - float posXV = v1V + stepXV * startX + args->gradientY.V * startY; - - const uint32_t *texPixels = (const uint32_t*)args->uniforms->TexturePixels(); - int texWidth = args->uniforms->TextureWidth(); - int texHeight = args->uniforms->TextureHeight(); + int fillcolor = args->uniforms->Color(); + int alpha = args->uniforms->SrcAlpha(); bool is_fixed_light = args->uniforms->FixedLight(); uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; @@ -1402,29 +1289,197 @@ void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs int x = x0; while (x < x1) { - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); + uint32_t fg; - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - uint32_t fgcolor = texPixels[texelX * texHeight + texelY]; - - uint32_t fgcolor_r = RPART(fgcolor); - uint32_t fgcolor_g = GPART(fgcolor); - uint32_t fgcolor_b = BPART(fgcolor); - uint32_t fgcolor_a = APART(fgcolor); - if (fgcolor_a > 127) + if (ModeT::SWFlags & SWSTYLEF_Fill) { + fg = fillcolor; + } + else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) + { + fg = destLine[x]; + } + else + { + float rcpW = 0x01000000 / posXW; + int32_t u = (int32_t)(posXU * rcpW); + int32_t v = (int32_t)(posXV * rcpW); + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + + if (ModeT::SWFlags & SWSTYLEF_Translated) + { + fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]]; + } + else + { + fg = texPixels[texelX * texHeight + texelY]; + } + } + + if (ModeT::SWFlags & SWSTYLEF_Skycap) + { + float rcpW = 0x01000000 / posXW; + int32_t v = (int32_t)(posXV * rcpW); + + int start_fade = 2; // How fast it should fade out + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + if (a == 256) + { + destLine[x] = fg; + } + else + { + uint32_t r = RPART(fg); + uint32_t g = GPART(fg); + uint32_t b = BPART(fg); + uint32_t fg_a = APART(fg); + uint32_t bg_red = RPART(fillcolor); + uint32_t bg_green = GPART(fillcolor); + uint32_t bg_blue = BPART(fillcolor); + r = (r * a + bg_red * inv_a + 127) >> 8; + g = (g * a + bg_green * inv_a + 127) >> 8; + b = (b * a + bg_blue * inv_a + 127) >> 8; + + destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; + } + } + else + { + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) + { + if (ModeT::Flags & STYLEF_RedIsAlpha) + fg = ((fg << 8) & 0xff000000) | (fillcolor & 0x00ffffff); + else + fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff); + } + + uint32_t fgalpha = fg >> 24; + + if (!(ModeT::Flags & STYLEF_Alpha1)) + { + fgalpha = (fgalpha * alpha) >> 8; + } + fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); int lightshade = lightpos >> 8; + uint32_t shadedfg_r = (RPART(fg) * lightshade) >> 8; + uint32_t shadedfg_g = (GPART(fg) * lightshade) >> 8; + uint32_t shadedfg_b = (BPART(fg) * lightshade) >> 8; - fgcolor_r = (fgcolor_r * lightshade) >> 8; - fgcolor_g = (fgcolor_g * lightshade) >> 8; - fgcolor_b = (fgcolor_b * lightshade) >> 8; + if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) + { + destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); + } + else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) + { + uint32_t dest = destLine[x]; - destLine[x] = 0xff000000 | (fgcolor_r << 16) | (fgcolor_g << 8) | fgcolor_b; + if (ModeT::BlendOp == STYLEOP_Add) + { + uint32_t out_r = MIN(RPART(dest) + shadedfg_r, 255); + uint32_t out_g = MIN(GPART(dest) + shadedfg_g, 255); + uint32_t out_b = MIN(BPART(dest) + shadedfg_b, 255); + destLine[x] = MAKEARGB(255, out_r, out_g, out_b); + } + else if (ModeT::BlendOp == STYLEOP_RevSub) + { + uint32_t out_r = MAX(RPART(dest) - shadedfg_r, 0); + uint32_t out_g = MAX(GPART(dest) - shadedfg_g, 0); + uint32_t out_b = MAX(BPART(dest) - shadedfg_b, 0); + destLine[x] = MAKEARGB(255, out_r, out_g, out_b); + } + else //if (ModeT::BlendOp == STYLEOP_Sub) + { + uint32_t out_r = MAX(shadedfg_r - RPART(dest), 0); + uint32_t out_g = MAX(shadedfg_g - GPART(dest), 0); + uint32_t out_b = MAX(shadedfg_b - BPART(dest), 0); + destLine[x] = MAKEARGB(255, out_r, out_g, out_b); + } + } + else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) + { + uint32_t dest = destLine[x]; + + uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256 + uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256 + uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256 + uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 + uint32_t dfactor_r = 256 - sfactor_r; + uint32_t dfactor_g = 256 - sfactor_g; + uint32_t dfactor_b = 256 - sfactor_b; + uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8; + uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8; + uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8; + + destLine[x] = MAKEARGB(255, out_r, out_g, out_b); + } + else if (fgalpha == 255) + { + destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); + } + else if (fgalpha != 0) + { + uint32_t dest = destLine[x]; + + uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 + uint32_t dfactor = 256 - sfactor; + uint32_t src_r = shadedfg_r * sfactor; + uint32_t src_g = shadedfg_g * sfactor; + uint32_t src_b = shadedfg_b * sfactor; + uint32_t dest_r = RPART(dest); + uint32_t dest_g = GPART(dest); + uint32_t dest_b = BPART(dest); + if (ModeT::BlendDest == STYLEALPHA_One) + { + dest_r <<= 8; + dest_g <<= 8; + dest_b <<= 8; + } + else + { + uint32_t dfactor = 256 - sfactor; + dest_r *= dfactor; + dest_g *= dfactor; + dest_b *= dfactor; + } + + uint32_t out_r, out_g, out_b; + if (ModeT::BlendOp == STYLEOP_Add) + { + if (ModeT::BlendDest == STYLEALPHA_One) + { + out_r = MIN((dest_r + src_r + 128) >> 8, 255); + out_g = MIN((dest_g + src_g + 128) >> 8, 255); + out_b = MIN((dest_b + src_b + 128) >> 8, 255); + } + else + { + out_r = (dest_r + src_r + 128) >> 8; + out_g = (dest_g + src_g + 128) >> 8; + out_b = (dest_b + src_b + 128) >> 8; + } + } + else if (ModeT::BlendOp == STYLEOP_RevSub) + { + out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); + out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); + out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); + } + else //if (ModeT::BlendOp == STYLEOP_Sub) + { + out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); + out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); + out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); + } + + destLine[x] = MAKEARGB(255, out_r, out_g, out_b); + } } posXW += stepXW; @@ -1434,10 +1489,11 @@ void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs } } -#endif - -void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args) +template +void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args) { + using namespace TriScreenDrawerModes; + float v1X = args->v1->x; float v1Y = args->v1->y; float v1W = args->v1->w; @@ -1455,9 +1511,17 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs auto colormaps = args->uniforms->BaseColormap(); const uint8_t *texPixels = args->uniforms->TexturePixels(); + const uint8_t *translation = args->uniforms->Translation(); int texWidth = args->uniforms->TextureWidth(); int texHeight = args->uniforms->TextureHeight(); + int fillcolor = args->uniforms->Color(); + int alpha = args->uniforms->SrcAlpha(); + + uint32_t capcolor = fillcolor; + if (ModeT::SWFlags & SWSTYLEF_Skycap) + capcolor = GPalette.BaseColors[capcolor].d; + bool is_fixed_light = args->uniforms->FixedLight(); uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; uint32_t light = args->uniforms->Light(); @@ -1471,23 +1535,197 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs int x = x0; while (x < x1) { - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); + int fg; + int fgalpha = 255; - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - uint8_t fgcolor = texPixels[texelX * texHeight + texelY]; + if (ModeT::SWFlags & SWSTYLEF_Fill) + { + fg = fillcolor; + } + else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) + { + fg = destLine[x]; + } + else + { + float rcpW = 0x01000000 / posXW; + int32_t u = (int32_t)(posXU * rcpW); + int32_t v = (int32_t)(posXV * rcpW); + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + fg = texPixels[texelX * texHeight + texelY]; - fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - int lightshade = lightpos >> 8; + if (ModeT::SWFlags & SWSTYLEF_Translated) + fg = translation[fg]; - lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00; - uint8_t shadedfg = colormaps[lightshade + fgcolor]; + fgalpha = (fg != 0) ? 255 : 0; + } - if (fgcolor != 0) - destLine[x] = shadedfg; + if (ModeT::SWFlags & SWSTYLEF_Skycap) + { + float rcpW = 0x01000000 / posXW; + int32_t v = (int32_t)(posXV * rcpW); + + int start_fade = 2; // How fast it should fade out + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + if (a == 256) + { + destLine[x] = fg; + } + else + { + uint32_t texelrgb = GPalette.BaseColors[fg].d; + + uint32_t r = RPART(texelrgb); + uint32_t g = GPART(texelrgb); + uint32_t b = BPART(texelrgb); + uint32_t fg_a = APART(texelrgb); + uint32_t bg_red = RPART(capcolor); + uint32_t bg_green = GPART(capcolor); + uint32_t bg_blue = BPART(capcolor); + r = (r * a + bg_red * inv_a + 127) >> 8; + g = (g * a + bg_green * inv_a + 127) >> 8; + b = (b * a + bg_blue * inv_a + 127) >> 8; + + destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; + } + } + else + { + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) + { + if (ModeT::Flags & STYLEF_RedIsAlpha) + fgalpha = fg; + fg = fillcolor; + } + + if (!(ModeT::Flags & STYLEF_Alpha1)) + { + fgalpha = (fgalpha * alpha) >> 8; + } + + fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + int lightshade = lightpos >> 8; + lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00; + uint8_t shadedfg = colormaps[lightshade + fg]; + + if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) + { + destLine[x] = shadedfg; + } + else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) + { + uint32_t src = GPalette.BaseColors[shadedfg]; + uint32_t dest = GPalette.BaseColors[destLine[x]]; + + if (ModeT::BlendOp == STYLEOP_Add) + { + uint32_t out_r = MIN(RPART(dest) + RPART(src), 255); + uint32_t out_g = MIN(GPART(dest) + GPART(src), 255); + uint32_t out_b = MIN(BPART(dest) + BPART(src), 255); + destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; + } + else if (ModeT::BlendOp == STYLEOP_RevSub) + { + uint32_t out_r = MAX(RPART(dest) - RPART(src), 0); + uint32_t out_g = MAX(GPART(dest) - GPART(src), 0); + uint32_t out_b = MAX(BPART(dest) - BPART(src), 0); + destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; + } + else //if (ModeT::BlendOp == STYLEOP_Sub) + { + uint32_t out_r = MAX(RPART(src) - RPART(dest), 0); + uint32_t out_g = MAX(GPART(src) - GPART(dest), 0); + uint32_t out_b = MAX(BPART(src) - BPART(dest), 0); + destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; + } + } + else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) + { + uint32_t src = GPalette.BaseColors[shadedfg]; + uint32_t dest = GPalette.BaseColors[destLine[x]]; + + uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256 + uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256 + uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256 + uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 + uint32_t dfactor_r = 256 - sfactor_r; + uint32_t dfactor_g = 256 - sfactor_g; + uint32_t dfactor_b = 256 - sfactor_b; + uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8; + uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8; + uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8; + + destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; + } + else if (fgalpha == 255) + { + destLine[x] = shadedfg; + } + else if (fgalpha != 0) + { + uint32_t src = GPalette.BaseColors[shadedfg]; + uint32_t dest = GPalette.BaseColors[destLine[x]]; + + uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 + uint32_t dfactor = 256 - sfactor; + uint32_t src_r = RPART(src) * sfactor; + uint32_t src_g = GPART(src) * sfactor; + uint32_t src_b = BPART(src) * sfactor; + uint32_t dest_r = RPART(dest); + uint32_t dest_g = GPART(dest); + uint32_t dest_b = BPART(dest); + if (ModeT::BlendDest == STYLEALPHA_One) + { + dest_r <<= 8; + dest_g <<= 8; + dest_b <<= 8; + } + else + { + uint32_t dfactor = 256 - sfactor; + dest_r *= dfactor; + dest_g *= dfactor; + dest_b *= dfactor; + } + + uint32_t out_r, out_g, out_b; + if (ModeT::BlendOp == STYLEOP_Add) + { + if (ModeT::BlendDest == STYLEALPHA_One) + { + out_r = MIN((dest_r + src_r + 128) >> 8, 255); + out_g = MIN((dest_g + src_g + 128) >> 8, 255); + out_b = MIN((dest_b + src_b + 128) >> 8, 255); + } + else + { + out_r = (dest_r + src_r + 128) >> 8; + out_g = (dest_g + src_g + 128) >> 8; + out_b = (dest_b + src_b + 128) >> 8; + } + } + else if (ModeT::BlendOp == STYLEOP_RevSub) + { + out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); + out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); + out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); + } + else //if (ModeT::BlendOp == STYLEOP_Sub) + { + out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); + out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); + out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); + } + + destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; + } + } posXW += stepXW; posXU += stepXU; @@ -1496,6 +1734,70 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs } } +void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) = +{ + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8, + &DrawSpan8 +}; + +void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *) = +{ + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32, + &DrawSpan32 +}; + void(*ScreenTriangle::TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *) = { &TriScreenDrawer8::Execute, // TextureOpaque diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index df635a29e6..c8a23c707b 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -139,9 +139,9 @@ class ScreenTriangle public: static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); - static void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args); - static void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args); + static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args); + static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args); static void(*TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *); static void(*TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *); static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); @@ -152,6 +152,46 @@ public: namespace TriScreenDrawerModes { + enum SWStyleFlags + { + SWSTYLEF_Translated = 1, + SWSTYLEF_Skycap = 2, + SWSTYLEF_FogBoundary = 4, + SWSTYLEF_Fill = 8, + SWSTYLEF_SrcColorOneMinusSrcColor = 16 + }; + + struct StyleOpaque { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = 0; }; + struct StyleSkycap { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Skycap; }; + struct StyleFogBoundary { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_FogBoundary; }; + struct StyleSrcColor { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_SrcColorOneMinusSrcColor; }; + struct StyleFill { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; + + struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; }; + struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; + struct StyleStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = 0; }; + struct StyleTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; + struct StyleAdd { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; }; + struct StyleShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; }; + struct StyleTranslucentStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = 0; }; + struct StyleShadow { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; + struct StyleSubtract { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; }; + struct StyleAddStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = 0; }; + struct StyleAddShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; }; + + struct StyleOpaqueTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; }; + struct StyleSrcColorTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated|SWSTYLEF_SrcColorOneMinusSrcColor; }; + struct StyleNormalTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; }; + struct StyleStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; + struct StyleTranslucentTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; }; + struct StyleAddTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; }; + struct StyleShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; + struct StyleTranslucentStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; + struct StyleShadowTranslated { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; }; + struct StyleSubtractTranslated { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; }; + struct StyleAddStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; + struct StyleAddShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; + enum class BlendModes { Opaque, Masked, AddClamp, SubClamp, RevSubClamp, AddSrcColorOneMinusSrcColor, Shaded, AddClampShaded }; struct OpaqueBlend { static const int Mode = (int)BlendModes::Opaque; }; struct MaskedBlend { static const int Mode = (int)BlendModes::Masked; };