diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8c0a30ea0..49152b785 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -892,6 +892,7 @@ set( FASTMATH_PCH_SOURCES r_swrenderer.cpp r_3dfloors.cpp r_bsp.cpp + r_drawer_context.cpp r_draw.cpp r_draw_rgba.cpp r_drawt.cpp diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 934d2d3e5..2b94b1e95 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -41,7 +41,7 @@ #include "r_local.h" #include "r_main.h" #include "r_plane.h" -#include "r_draw.h" +#include "r_drawer_context.h" #include "r_things.h" #include "r_3dfloors.h" #include "a_sharedglobal.h" @@ -545,7 +545,7 @@ void R_AddLine (seg_t *line) curline = line; // [RH] Color if not texturing line - dc_color = (((int)(line - segs) * 8) + 4) & 255; + DrawerContext::SetFlatColor((((int)(line - segs) * 8) + 4) & 255); pt1 = line->v1->fPos() - ViewPos; pt2 = line->v2->fPos() - ViewPos; diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 4dcdc3e6b..19195e907 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -23,6 +23,8 @@ // //----------------------------------------------------------------------------- +#define DRAWER_INTERNALS + #include #include "templates.h" @@ -40,6 +42,8 @@ #include "r_data/colormaps.h" #include "r_plane.h" #include "r_draw_rgba.h" +#include "r_drawer_context.h" +#include "d_net.h" #include "gi.h" #include "stats.h" @@ -66,6 +70,7 @@ int ylookup[MAXHEIGHT]; BYTE *dc_destorg; } int scaledviewwidth; +DCanvas *dc_canvas; // [RH] Pointers to the different column drawers. // These get changed depending on the current @@ -97,9 +102,9 @@ void (*R_DrawSpanMaskedAddClamp)(void); void (*R_FillSpan)(void); void (*R_FillColumnHoriz)(void); void (*R_DrawFogBoundary)(int x1, int x2, short *uclip, short *dclip); -void (*R_MapTiltedPlane)(int y, int x1); -void (*R_MapColoredPlane)(int y, int x1); -void (*R_DrawParticle)(vissprite_t *); +void (*R_DrawTiltedSpan)(int y, int x1, int x2); +void (*R_DrawColoredSpan)(int y, int x1, int x2); +void (*R_FillTransColumn)(int x, int y1, int y2, int color, int alpha); fixed_t (*tmvline1_add)(); void (*tmvline4_add)(); fixed_t (*tmvline1_addclamp)(); @@ -134,6 +139,24 @@ void (*rt_tlatesubclamp4cols)(int sx, int yl, int yh); void (*rt_tlaterevsubclamp4cols)(int sx, int yl, int yh); void (*rt_initcols)(BYTE *buffer); void (*rt_span_coverage)(int x, int start, int stop); +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*fuzzcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); +void (*hcolfunc_pre) (void); +void (*hcolfunc_post1) (int hx, int sx, int yl, int yh); +void (*hcolfunc_post2) (int hx, int sx, int yl, int yh); +void (*hcolfunc_post4) (int sx, int yl, int yh); + +extern "C" void R_DrawTiltedPlane_ASM(int y, int x1); +#ifdef X86_ASM +extern "C" void R_SetSpanSource_ASM(const BYTE *flat); +extern "C" void R_SetSpanSize_ASM(int xbits, int ybits); +extern "C" void R_SetSpanColormap_ASM(BYTE *colormap); +extern "C" void R_SetTiltedSpanSource_ASM(const BYTE *flat); +extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource; +#endif // // R_DrawColumn @@ -1040,13 +1063,6 @@ const BYTE* ds_source; // just for profiling int dscount; - -#ifdef X86_ASM -extern "C" void R_SetSpanSource_ASM (const BYTE *flat); -extern "C" void R_SetSpanSize_ASM (int xbits, int ybits); -extern "C" void R_SetSpanColormap_ASM (BYTE *colormap); -extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource; -#endif } //========================================================================== @@ -1076,9 +1092,8 @@ void R_SetSpanSource(const BYTE *pixels) // //========================================================================== -void R_SetSpanColormap(FDynamicColormap *colormap, int shade) +void R_SetSpanColormap() { - R_SetDSColorMapLight(colormap, 0, shade); #ifdef X86_ASM if (!r_swtruecolor && ds_colormap != ds_curcolormap) { @@ -2297,9 +2312,9 @@ void R_InitColumnDrawers () R_FillColumnHoriz = R_FillColumnHoriz_rgba; R_DrawFogBoundary = R_DrawFogBoundary_rgba; - R_MapTiltedPlane = R_MapTiltedPlane_rgba; - R_MapColoredPlane = R_MapColoredPlane_rgba; - R_DrawParticle = R_DrawParticle_rgba; + R_DrawTiltedSpan = R_DrawTiltedSpan_rgba; + R_DrawColoredSpan = R_DrawColoredSpan_rgba; + R_FillTransColumn = R_FillTransColumn_rgba; tmvline1_add = tmvline1_add_rgba; tmvline4_add = tmvline4_add_rgba; @@ -2394,9 +2409,15 @@ void R_InitColumnDrawers () R_FillColumnHoriz = R_FillColumnHorizP_C; R_DrawFogBoundary = R_DrawFogBoundary_C; - R_MapTiltedPlane = R_MapTiltedPlane_C; - R_MapColoredPlane = R_MapColoredPlane_C; - R_DrawParticle = R_DrawParticle_C; + R_DrawColoredSpan = R_DrawColoredSpan_C; + R_FillTransColumn = R_FillTransColumn_C; + +#ifdef X86_ASM + // To do: update R_DrawTiltedPlane_ASM to use x2 rather than spanend[y] + R_DrawTiltedSpan = [](int y, int x1, int x2) { R_DrawTiltedPlane_ASM(y, x1); }; +#else + R_DrawTiltedSpan = R_DrawTiltedSpan_C; +#endif tmvline1_add = tmvline1_add_C; tmvline4_add = tmvline4_add_C; @@ -2829,3 +2850,744 @@ void R_SetDSColorMapLight(FColormap *base_colormap, float light, int shade) ds_colormap = base_colormap->Maps + (GETPALOOKUP(light, shade) << COLORMAPSHIFT); } } + +///////////////////////////////////////////////////////////////////////////// + +FVector3 ds_plane_sz, ds_plane_su, ds_plane_sv; +bool ds_plane_shade; +float ds_planelightfloat; +fixed_t ds_pviewx, ds_pviewy; +int ds_planeshade; +extern "C" BYTE *tiltlighting[MAXWIDTH]; + +extern "C" { void R_CalcTiltedLighting(double lval, double lend, int width); } + +#ifdef _MSC_VER +#pragma warning(disable:4244) // warning C4244: conversion from 'SQWORD' to 'DWORD', possible loss of data +#endif + +//========================================================================== +// +// R_CalcTiltedLighting +// +// Calculates the lighting for one row of a tilted plane. If the definition +// of GETPALOOKUP changes, this needs to change, too. +// +//========================================================================== + +extern "C" { +void R_CalcTiltedLighting (double lval, double lend, int width) +{ + double lstep; + BYTE *lightfiller; + BYTE *basecolormapdata = ds_fcolormap->Maps; + int i = 0; + + if (width == 0 || lval == lend) + { // Constant lighting + lightfiller = basecolormapdata + (GETPALOOKUP(lval, ds_planeshade) << COLORMAPSHIFT); + } + else + { + lstep = (lend - lval) / width; + if (lval >= MAXLIGHTVIS) + { // lval starts "too bright". + lightfiller = basecolormapdata + (GETPALOOKUP(lval, ds_planeshade) << COLORMAPSHIFT); + for (; i <= width && lval >= MAXLIGHTVIS; ++i) + { + tiltlighting[i] = lightfiller; + lval += lstep; + } + } + if (lend >= MAXLIGHTVIS) + { // lend ends "too bright". + lightfiller = basecolormapdata + (GETPALOOKUP(lend, ds_planeshade) << COLORMAPSHIFT); + for (; width > i && lend >= MAXLIGHTVIS; --width) + { + tiltlighting[width] = lightfiller; + lend -= lstep; + } + } + if (width > 0) + { + lval = FIXED2DBL(ds_planeshade) - lval; + lend = FIXED2DBL(ds_planeshade) - lend; + lstep = (lend - lval) / width; + if (lstep < 0) + { // Going from dark to light + if (lval < 1.) + { // All bright + lightfiller = basecolormapdata; + } + else + { + if (lval >= NUMCOLORMAPS) + { // Starts beyond the dark end + BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + while (lval >= NUMCOLORMAPS && i <= width) + { + tiltlighting[i++] = clight; + lval += lstep; + } + if (i > width) + return; + } + while (i <= width && lval >= 0) + { + tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT); + lval += lstep; + } + lightfiller = basecolormapdata; + } + } + else + { // Going from light to dark + if (lval >= (NUMCOLORMAPS-1)) + { // All dark + lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + } + else + { + while (lval < 0 && i <= width) + { + tiltlighting[i++] = basecolormapdata; + lval += lstep; + } + if (i > width) + return; + while (i <= width && lval < (NUMCOLORMAPS-1)) + { + tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT); + lval += lstep; + } + lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + } + } + } + } + for (; i <= width; i++) + { + tiltlighting[i] = lightfiller; + } +} +} // extern "C" + +void R_DrawTiltedSpan_C (int y, int x1, int x2) +{ + int width = x2 - x1; + double iz, uz, vz; + BYTE *fb; + DWORD u, v; + int i; + + iz = ds_plane_sz[2] + ds_plane_sz[1]*(centery-y) + ds_plane_sz[0]*(x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + if (ds_plane_shade) + { + uz = (iz + ds_plane_sz[0]*width) * ds_planelightfloat; + vz = iz * ds_planelightfloat; + R_CalcTiltedLighting (vz, uz, width); + } + + uz = ds_plane_su[2] + ds_plane_su[1]*(centery-y) + ds_plane_su[0]*(x1-centerx); + vz = ds_plane_sv[2] + ds_plane_sv[1]*(centery-y) + ds_plane_sv[0]*(x1-centerx); + + fb = ylookup[y] + x1 + dc_destorg; + + BYTE vshift = 32 - ds_ybits; + BYTE ushift = vshift - ds_xbits; + int umask = ((1 << ds_xbits) - 1) << ds_ybits; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + + u = SQWORD(uz*z) + ds_pviewx; + v = SQWORD(vz*z) + ds_pviewy; + R_SetDSColorMapLight(tiltlighting[i], 0, 0); + fb[i++] = ds_colormap[ds_source[(v >> vshift) | ((u >> ushift) & umask)]]; + iz += ds_plane_sz[0]; + uz += ds_plane_su[0]; + vz += ds_plane_sv[0]; + } while (--width >= 0); +#else +//#define SPANSIZE 32 +//#define INVSPAN 0.03125f +//#define SPANSIZE 8 +//#define INVSPAN 0.125f +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + double startz = 1.f/iz; + double startu = uz*startz; + double startv = vz*startz; + double izstep, uzstep, vzstep; + + izstep = ds_plane_sz[0] * SPANSIZE; + uzstep = ds_plane_su[0] * SPANSIZE; + vzstep = ds_plane_sv[0] * SPANSIZE; + x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + double endz = 1.f/iz; + double endu = uz*endz; + double endv = vz*endz; + DWORD stepu = SQWORD((endu - startu) * INVSPAN); + DWORD stepv = SQWORD((endv - startv) * INVSPAN); + u = SQWORD(startu) + ds_pviewx; + v = SQWORD(startv) + ds_pviewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); + x1++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = SQWORD(startu); + v = SQWORD(startv); + fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); + } + else + { + double left = width; + iz += ds_plane_sz[0] * left; + uz += ds_plane_su[0] * left; + vz += ds_plane_sv[0] * left; + + double endz = 1.f/iz; + double endu = uz*endz; + double endv = vz*endz; + left = 1.f/left; + DWORD stepu = SQWORD((endu - startu) * left); + DWORD stepv = SQWORD((endv - startv) * left); + u = SQWORD(startu) + ds_pviewx; + v = SQWORD(startv) + ds_pviewy; + + for (; width != 0; width--) + { + fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); + x1++; + u += stepu; + v += stepv; + } + } + } +#endif +} + +void R_DrawColoredSpan_C (int y, int x1, int x2) +{ + memset (ylookup[y] + x1 + dc_destorg, ds_color, x2 - x1 + 1); +} + +///////////////////////////////////////////////////////////////////////////// + +// Draw a column with support for non-power-of-two ranges +uint32_t wallscan_drawcol1(int x, int y1, int y2, uint32_t uv_start, uint32_t uv_step, uint32_t uv_max, const BYTE *source, DWORD(*draw1column)()) +{ + int pixelsize = r_swtruecolor ? 4 : 1; + if (uv_max == 0) // power of two + { + int count = y2 - y1; + + dc_source = source; + dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; + dc_count = count; + dc_iscale = uv_step; + dc_texturefrac = uv_start; + draw1column(); + + uint64_t step64 = uv_step; + uint64_t pos64 = uv_start; + return (uint32_t)(pos64 + step64 * count); + } + else + { + uint32_t uv_pos = uv_start; + + uint32_t left = y2 - y1; + while (left > 0) + { + uint32_t available = uv_max - uv_pos; + uint32_t next_uv_wrap = available / uv_step; + if (available % uv_step != 0) + next_uv_wrap++; + uint32_t count = MIN(left, next_uv_wrap); + + dc_source = source; + dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; + dc_count = count; + dc_iscale = uv_step; + dc_texturefrac = uv_pos; + draw1column(); + + left -= count; + uv_pos += uv_step * count; + if (uv_pos >= uv_max) + uv_pos -= uv_max; + } + + return uv_pos; + } +} + +// Draw four columns with support for non-power-of-two ranges +void wallscan_drawcol4(int x, int y1, int y2, uint32_t *uv_pos, uint32_t *uv_step, uint32_t uv_max, const BYTE **source, void(*draw4columns)()) +{ + int pixelsize = r_swtruecolor ? 4 : 1; + if (uv_max == 0) // power of two, no wrap handling needed + { + int count = y2 - y1; + for (int i = 0; i < 4; i++) + { + bufplce[i] = source[i]; + vplce[i] = uv_pos[i]; + vince[i] = uv_step[i]; + + uint64_t step64 = uv_step[i]; + uint64_t pos64 = uv_pos[i]; + uv_pos[i] = (uint32_t)(pos64 + step64 * count); + } + dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; + dc_count = count; + draw4columns(); + } + else + { + dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; + for (int i = 0; i < 4; i++) + bufplce[i] = source[i]; + + uint32_t left = y2 - y1; + while (left > 0) + { + // Find which column wraps first + uint32_t count = left; + for (int i = 0; i < 4; i++) + { + uint32_t available = uv_max - uv_pos[i]; + uint32_t next_uv_wrap = available / uv_step[i]; + if (available % uv_step[i] != 0) + next_uv_wrap++; + count = MIN(next_uv_wrap, count); + } + + // Draw until that column wraps + for (int i = 0; i < 4; i++) + { + vplce[i] = uv_pos[i]; + vince[i] = uv_step[i]; + } + dc_count = count; + draw4columns(); + + // Wrap the uv position + for (int i = 0; i < 4; i++) + { + uv_pos[i] += uv_step[i] * count; + if (uv_pos[i] >= uv_max) + uv_pos[i] -= uv_max; + } + + left -= count; + } + } +} + +// Calculates a wrapped uv start position value for a column +void calc_uv_start_and_step(int y1, float swal, double yrepeat, uint32_t uv_height, int fracbits, uint32_t &uv_start_out, uint32_t &uv_step_out) +{ + double uv_stepd = swal * yrepeat; + + // Find start uv in [0-uv_height[ range. + // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. + double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / uv_height; + v = v - floor(v); + v *= uv_height; + v *= (1 << fracbits); + + uv_start_out = (uint32_t)v; + uv_step_out = xs_ToFixed(fracbits, uv_stepd); +} + +typedef DWORD(*Draw1ColumnFuncPtr)(); +typedef void(*Draw4ColumnsFuncPtr)(); + +void wallscan_any( + int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, + FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x), + void(setupwallscan(int bits, Draw1ColumnFuncPtr &draw1, Draw4ColumnsFuncPtr &draw2))) +{ + if (rw_pic->UseType == FTexture::TEX_Null) + return; + + uint32_t uv_height = rw_pic->GetHeight(); + uint32_t fracbits = 32 - rw_pic->HeightBits; + uint32_t uv_max = uv_height << fracbits; + + DWORD(*draw1column)(); + void(*draw4columns)(); + setupwallscan(fracbits, draw1column, draw4columns); + + fixed_t xoffset = rw_offset; + + bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0); + if (fixed) + { + palookupoffse[0] = dc_colormap; + palookupoffse[1] = dc_colormap; + palookupoffse[2] = dc_colormap; + palookupoffse[3] = dc_colormap; + palookuplight[0] = 0; + palookuplight[1] = 0; + palookuplight[2] = 0; + palookuplight[3] = 0; + } + + if (fixedcolormap) + R_SetColorMapLight(fixedcolormap, 0, 0); + else + R_SetColorMapLight(basecolormap, 0, 0); + + float light = rw_light; + + // Calculate where 4 column alignment begins and ends: + int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2); + int aligned_x2 = clamp(x2 / 4 * 4, x1, x2); + + // First unaligned columns: + for (int x = x1; x < aligned_x1; x++, light += rw_lightstep) + { + int y1 = uwal[x]; + int y2 = dwal[x]; + if (y2 <= y1) + continue; + + if (!fixed) + R_SetColorMapLight(basecolormap, light, wallshade); + + const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS); + + uint32_t uv_start, uv_step; + calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step); + + wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column); + } + + // The aligned columns + for (int x = aligned_x1; x < aligned_x2; x += 4) + { + // Find y1, y2, light and uv values for four columns: + int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] }; + int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] }; + + const BYTE *source[4]; + for (int i = 0; i < 4; i++) + source[i] = getcol(rw_pic, (lwal[x + i] + xoffset) >> FRACBITS); + + float lights[4]; + for (int i = 0; i < 4; i++) + { + lights[i] = light; + light += rw_lightstep; + } + + uint32_t uv_pos[4], uv_step[4]; + for (int i = 0; i < 4; i++) + calc_uv_start_and_step(y1[i], swal[x + i], yrepeat, uv_height, fracbits, uv_pos[i], uv_step[i]); + + // Figure out where we vertically can start and stop drawing 4 columns in one go + int middle_y1 = y1[0]; + int middle_y2 = y2[0]; + for (int i = 1; i < 4; i++) + { + middle_y1 = MAX(y1[i], middle_y1); + middle_y2 = MIN(y2[i], middle_y2); + } + + // If we got an empty column in our set we cannot draw 4 columns in one go: + bool empty_column_in_set = false; + for (int i = 0; i < 4; i++) + { + if (y2[i] <= y1[i]) + empty_column_in_set = true; + } + + if (empty_column_in_set || middle_y2 <= middle_y1) + { + for (int i = 0; i < 4; i++) + { + if (y2[i] <= y1[i]) + continue; + + if (!fixed) + R_SetColorMapLight(basecolormap, lights[i], wallshade); + wallscan_drawcol1(x + i, y1[i], y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column); + } + continue; + } + + // Draw the first rows where not all 4 columns are active + for (int i = 0; i < 4; i++) + { + if (!fixed) + R_SetColorMapLight(basecolormap, lights[i], wallshade); + + if (y1[i] < middle_y1) + uv_pos[i] = wallscan_drawcol1(x + i, y1[i], middle_y1, uv_pos[i], uv_step[i], uv_max, source[i], draw1column); + } + + // Draw the area where all 4 columns are active + if (!fixed) + { + for (int i = 0; i < 4; i++) + { + if (r_swtruecolor) + { + palookupoffse[i] = basecolormap->Maps; + palookuplight[i] = LIGHTSCALE(lights[i], wallshade); + } + else + { + palookupoffse[i] = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT); + palookuplight[i] = 0; + } + } + } + wallscan_drawcol4(x, middle_y1, middle_y2, uv_pos, uv_step, uv_max, source, draw4columns); + + // Draw the last rows where not all 4 columns are active + for (int i = 0; i < 4; i++) + { + if (!fixed) + R_SetColorMapLight(basecolormap, lights[i], wallshade); + + if (middle_y2 < y2[i]) + uv_pos[i] = wallscan_drawcol1(x + i, middle_y2, y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column); + } + } + + // The last unaligned columns: + for (int x = aligned_x2; x < x2; x++, light += rw_lightstep) + { + int y1 = uwal[x]; + int y2 = dwal[x]; + if (y2 <= y1) + continue; + + if (!fixed) + R_SetColorMapLight(basecolormap, light, wallshade); + + const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS); + + uint32_t uv_start, uv_step; + calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step); + + wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column); + } + + NetUpdate(); +} + +void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x)) +{ + wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) + { + setupvline(bits); + line1 = dovline1; + line4 = dovline4; + }); +} + +void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x)) +{ + if (!rw_pic->bMasked) // Textures that aren't masked can use the faster wallscan. + { + wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol); + } + else + { + wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) + { + setupmvline(bits); + line1 = domvline1; + line4 = domvline4; + }); + } +} + +void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x)) +{ + static fixed_t(*tmvline1)(); + static void(*tmvline4)(); + if (!R_GetTransMaskDrawers(&tmvline1, &tmvline4)) + { + // The current translucency is unsupported, so draw with regular maskwallscan instead. + maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol); + } + else + { + wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) + { + setuptmvline(bits); + line1 = reinterpret_cast(tmvline1); + line4 = tmvline4; + }); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void R_FillTransColumn_C(int x, int y1, int y2, int color, int alpha) +{ + fixed_t fglevel, bglevel; + DWORD *fg2rgb; + DWORD *bg2rgb; + int spacing; + BYTE *dest; + DWORD fg; + + fglevel = ((alpha + 1) << 8) & ~0x3ff; + bglevel = FRACUNIT - fglevel; + fg2rgb = Col2RGB8[fglevel >> 10]; + bg2rgb = Col2RGB8[bglevel >> 10]; + fg = fg2rgb[color]; + + spacing = dc_pitch; + + int ycount = y2 - y1 + 1; + dest = ylookup[y1] + x + dc_destorg; + for (int y = 0; y < ycount; y++) + { + DWORD bg = bg2rgb[*dest]; + bg = (fg + bg) | 0x1f07c1f; + *dest = RGB32k.All[bg & (bg >> 15)]; + dest += spacing; + } +} + +///////////////////////////////////////////////////////////////////////////// + +// +// R_DrawMaskedColumn +// Used for sprites and masked mid textures. +// Masked means: partly transparent, i.e. stored +// in posts/runs of opaque pixels. +// +short* dc_mfloorclip; +short* dc_mceilingclip; + +double dc_spryscale; +double dc_sprtopscreen; + +bool dc_sprflipvert; + +void R_DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *span) +{ + int pixelsize = r_swtruecolor ? 4 : 1; + const fixed_t centeryfrac = FLOAT2FIXED(CenterY); + const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); + while (span->Length != 0) + { + const int length = span->Length; + const int top = span->TopOffset; + + fixed_t texturefrac = dc_texturefrac; + fixed_t iscale = dc_iscale; + + // calculate unclipped screen coordinates for post + int yl = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * top); + int yh = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * (top + length)) - 1; + + if (dc_sprflipvert) + { + swapvalues(yl, yh); + } + + if (yh >= dc_mfloorclip[x]) + { + yh = dc_mfloorclip[x] - 1; + } + if (yl < dc_mceilingclip[x]) + { + yl = dc_mceilingclip[x]; + } + + if (yl <= yh) + { + if (dc_sprflipvert) + { + texturefrac = (yl*iscale) - (top << FRACBITS) + - FixedMul(centeryfrac, iscale) - texturemid; + const fixed_t maxfrac = length << FRACBITS; + while (texturefrac >= maxfrac) + { + if (++yl > yh) + goto nextpost; + texturefrac += iscale; + } + fixed_t endfrac = texturefrac + (yh - yl)*iscale; + while (endfrac < 0) + { + if (--yh < yl) + goto nextpost; + endfrac -= iscale; + } + } + else + { + texturefrac = texturemid - (top << FRACBITS) + + (yl*iscale) - FixedMul(centeryfrac - FRACUNIT, iscale); + while (texturefrac < 0) + { + if (++yl > yh) + goto nextpost; + texturefrac += iscale; + } + fixed_t endfrac = texturefrac + (yh - yl)*iscale; + const fixed_t maxfrac = length << FRACBITS; + if (yh < dc_mfloorclip[x] - 1 && endfrac < maxfrac - iscale) + { + yh++; + } + else while (endfrac >= maxfrac) + { + if (--yh < yl) + goto nextpost; + endfrac -= iscale; + } + } + + dc_yl = yl; + dc_yh = yh; + dc_x = x; + dc_texturefrac = texturefrac; + dc_iscale = iscale; + dc_source = column + top; + dc_count = yh - yl + 1; + dc_dest = (ylookup[yl] + x) * pixelsize + dc_destorg; + colfunc(); + } + nextpost: + span++; + } +} diff --git a/src/r_draw.h b/src/r_draw.h index a31183405..c22c958d0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -25,6 +25,11 @@ #include "r_defs.h" +// Prevents files outside the DrawerContext class getting good ideas about +// accessing the private globals. Any drawer actions should be facilitated +// via the DrawerContext class! +#ifdef DRAWER_INTERNALS + // Spectre/Invisibility. #define FUZZTABLE 50 extern "C" int fuzzoffset[FUZZTABLE + 1]; // [RH] +1 for the assembly routine @@ -71,6 +76,7 @@ extern "C" fixed_t dc_destalpha; // first pixel in a column extern "C" const BYTE* dc_source; +extern DCanvas *dc_canvas; extern "C" BYTE *dc_dest, *dc_destorg; extern "C" int dc_count; @@ -86,6 +92,23 @@ extern "C" unsigned int dc_tspans[4][MAXHEIGHT]; extern "C" unsigned int *dc_ctspan[4]; extern "C" unsigned int horizspans[4]; +// +// Function pointers to switch refresh/drawing functions. +// Used to select shadow mode etc. +// +extern void (*colfunc) (void); +extern void (*basecolfunc) (void); +extern void (*fuzzcolfunc) (void); +extern void (*transcolfunc) (void); +// No shadow effects on floors. +extern void (*spanfunc) (void); + +// [RH] Function pointers for the horizontal column drawers. +extern void (*hcolfunc_pre) (void); +extern void (*hcolfunc_post1) (int hx, int sx, int yl, int yh); +extern void (*hcolfunc_post2) (int hx, int sx, int yl, int yh); +extern void (*hcolfunc_post4) (int sx, int yl, int yh); + // [RH] Pointers to the different column and span drawers... // The span blitting interface. @@ -116,7 +139,7 @@ extern void (*R_DrawTranslatedColumn)(void); // Span drawing for rows, floor/ceiling. No Spectre effect needed. extern void (*R_DrawSpan)(void); void R_SetupSpanBits(FTexture *tex); -void R_SetSpanColormap(FDynamicColormap *colormap, int shade); +void R_SetSpanColormap(); void R_SetSpanSource(const BYTE *pixels); // Span drawing for masked textures. @@ -281,6 +304,15 @@ void R_FillColumnP_C (void); void R_FillColumnHorizP_C (void); void R_FillSpan_C (void); +// vars for R_DrawMaskedColumn +extern short* dc_mfloorclip; +extern short* dc_mceilingclip; +extern double dc_spryscale; +extern double dc_sprtopscreen; +extern bool dc_sprflipvert; + +void R_DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans); + #ifdef X86_ASM #define R_SetupDrawSlab R_SetupDrawSlabA #define R_DrawSlab R_DrawSlabA @@ -325,12 +357,7 @@ void R_InitShadeMaps(); void R_InitFuzzTable (int fuzzoff); // [RH] Consolidate column drawer selection -enum ESPSResult -{ - DontDraw, // not useful to draw this - DoDraw0, // draw this as if r_columnmethod is 0 - DoDraw1, // draw this as if r_columnmethod is 1 -}; +enum ESPSResult; ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color); inline ESPSResult R_SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color) { @@ -353,18 +380,6 @@ extern void(*tmvline4_revsubclamp)(); // transmaskwallscan calls this to find out what column drawers to use bool R_GetTransMaskDrawers (fixed_t (**tmvline1)(), void (**tmvline4)()); -// Retrieve column data for wallscan. Should probably be removed -// to just use the texture's GetColumn() method. It just exists -// for double-layer skies. -const BYTE *R_GetColumn (FTexture *tex, int col); -void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); - -// maskwallscan is exactly like wallscan but does not draw anything where the texture is color 0. -void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); - -// transmaskwallscan is like maskwallscan, but it can also blend to the background -void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); - // Sets dc_colormap and dc_light to their appropriate values depending on the output format (pal vs true color) void R_SetColorMapLight(FColormap *base_colormap, float light, int shade); @@ -373,4 +388,40 @@ void R_SetDSColorMapLight(FColormap *base_colormap, float light, int shade); void R_SetTranslationMap(lighttable_t *translation); +// Retrieve column data for wallscan. Should probably be removed +// to just use the texture's GetColumn() method. It just exists +// for double-layer skies. +const BYTE *R_GetColumn (FTexture *tex, int col); +void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); + +// maskwallscan is exactly like wallscan but does not draw anything where the texture is color 0. +void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); + +// transmaskwallscan is like maskwallscan, but it can also blend to the background +void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); + +extern void(*R_DrawColoredSpan)(int y, int x1, int x2); +extern void(*R_DrawTiltedSpan)(int y, int x1, int x2); + +void R_DrawTiltedSpan_C(int y, int x1, int x2); +void R_DrawTiltedSpan_rgba(int y, int x1, int x2); +void R_DrawColoredSpan_C(int y, int x1, int x2); +void R_DrawColoredSpan_rgba(int y, int x1, int x2); + +extern FVector3 ds_plane_sz, ds_plane_su, ds_plane_sv; +extern bool ds_plane_shade; +extern float ds_planelightfloat; +extern fixed_t ds_pviewx, ds_pviewy; +extern int ds_planeshade; + +extern "C" BYTE *tiltlighting[MAXWIDTH]; +extern "C" { void R_CalcTiltedLighting(double lval, double lend, int width); } + +struct vissprite_t; +extern void(*R_FillTransColumn)(int x, int y1, int y2, int color, int alpha); +void R_FillTransColumn_C(int x, int y1, int y2, int color, int alpha); +void R_FillTransColumn_rgba(int x, int y1, int y2, int color, int alpha); + +#endif + #endif diff --git a/src/r_draw_rgba.cpp b/src/r_draw_rgba.cpp index 2062609b4..420b63dff 100644 --- a/src/r_draw_rgba.cpp +++ b/src/r_draw_rgba.cpp @@ -21,6 +21,8 @@ // //----------------------------------------------------------------------------- +#define DRAWER_INTERNALS + #include #include "templates.h" @@ -3492,6 +3494,158 @@ public: } }; +class DrawTiltedSpanRGBACommand : public DrawerCommand +{ + int _y; + int _x1; + int _x2; + BYTE *dc_destorg; + fixed_t dc_light; + ShadeConstants dc_shade_constants; + const BYTE *ds_source; + +public: + DrawTiltedSpanRGBACommand(int y, int x1, int x2) + { + _y = y; + _x1 = x1; + _x2 = x2; + + dc_destorg = ::dc_destorg; + ds_source = ::ds_source; + } + + void Execute(DrawerThread *thread) override + { + if (thread->line_skipped_by_thread(_y)) + return; + + int y = _y; + int x1 = _x1; + int x2 = _x2; + + // Slopes are broken currently in master. + // Until R_DrawTiltedPlane is fixed we are just going to fill with a solid color. + + uint32_t *source = (uint32_t*)ds_source; + uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg; + + int count = x2 - x1 + 1; + while (count > 0) + { + *(dest++) = source[0]; + count--; + } + } +}; + +class DrawColoredSpanRGBACommand : public DrawerCommand +{ + int _y; + int _x1; + int _x2; + BYTE *dc_destorg; + fixed_t ds_light; + int ds_color; + +public: + DrawColoredSpanRGBACommand(int y, int x1, int x2) + { + _y = y; + _x1 = x1; + _x2 = x2; + + dc_destorg = ::dc_destorg; + ds_light = ::ds_light; + ds_color = ::ds_color; + } + + void Execute(DrawerThread *thread) override + { + if (thread->line_skipped_by_thread(_y)) + return; + + int y = _y; + int x1 = _x1; + int x2 = _x2; + + uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg; + int count = (x2 - x1 + 1); + uint32_t light = calc_light_multiplier(ds_light); + uint32_t color = shade_pal_index_simple(ds_color, light); + for (int i = 0; i < count; i++) + dest[i] = color; + } +}; + +class FillTransColumnRGBACommand : public DrawerCommand +{ + int _x; + int _y1; + int _y2; + int _color; + int _a; + BYTE *dc_destorg; + int dc_pitch; + fixed_t ds_light; + int ds_color; + +public: + FillTransColumnRGBACommand(int x, int y1, int y2, int color, int a) + { + _x = x; + _y1 = y1; + _y2 = y2; + _color = color; + _a = a; + + dc_destorg = ::dc_destorg; + dc_pitch = ::dc_pitch; + } + + void Execute(DrawerThread *thread) override + { + int x = _x; + int y1 = _y1; + int y2 = _y2; + int color = _color; + int a = _a; + + int ycount = thread->count_for_thread(y1, y2 - y1 + 1); + if (ycount <= 0) + return; + + uint32_t fg = GPalette.BaseColors[color].d; + uint32_t fg_red = (fg >> 16) & 0xff; + uint32_t fg_green = (fg >> 8) & 0xff; + uint32_t fg_blue = fg & 0xff; + + uint32_t alpha = a + 1; + uint32_t inv_alpha = 256 - alpha; + + fg_red *= alpha; + fg_green *= alpha; + fg_blue *= alpha; + + int spacing = dc_pitch * thread->num_cores; + uint32_t *dest = thread->dest_for_thread(y1, dc_pitch, ylookup[y1] + x + (uint32_t*)dc_destorg); + + for (int y = 0; y < ycount; y++) + { + uint32_t bg_red = (*dest >> 16) & 0xff; + uint32_t bg_green = (*dest >> 8) & 0xff; + uint32_t bg_blue = (*dest) & 0xff; + + uint32_t red = (fg_red + bg_red * inv_alpha) / 256; + uint32_t green = (fg_green + bg_green * inv_alpha) / 256; + uint32_t blue = (fg_blue + bg_blue * inv_alpha) / 256; + + *dest = 0xff000000 | (red << 16) | (green << 8) | blue; + dest += spacing; + } + } +}; + ApplySpecialColormapRGBACommand::ApplySpecialColormapRGBACommand(FSpecialColormap *colormap, DFrameBuffer *screen) { buffer = screen->GetBuffer(); @@ -3968,3 +4122,18 @@ void R_DrawFogBoundary_rgba(int x1, int x2, short *uclip, short *dclip) R_DrawFogBoundarySection_rgba(t2, b2, x1); } } + +void R_DrawTiltedSpan_rgba(int y, int x1, int x2) +{ + DrawerCommandQueue::QueueCommand(y, x1, x2); +} + +void R_DrawColoredSpan_rgba(int y, int x1, int x2) +{ + DrawerCommandQueue::QueueCommand(y, x1, x2); +} + +void R_FillTransColumn_rgba(int x, int y1, int y2, int color, int a) +{ + DrawerCommandQueue::QueueCommand(x, y1, y2, color, a); +} diff --git a/src/r_draw_rgba.h b/src/r_draw_rgba.h index 47ea75260..a91b54d74 100644 --- a/src/r_draw_rgba.h +++ b/src/r_draw_rgba.h @@ -23,6 +23,11 @@ #ifndef __R_DRAW_RGBA__ #define __R_DRAW_RGBA__ +// Prevents files outside the DrawerContext class getting good ideas about +// accessing the private globals. Any drawer actions should be facilitated +// via the DrawerContext class! +#ifdef DRAWER_INTERNALS + #include "r_draw.h" #include "v_palette.h" #include @@ -487,3 +492,5 @@ FORCEINLINE uint32_t alpha_blend(uint32_t fg, uint32_t bg) } #endif + +#endif diff --git a/src/r_drawer_context.cpp b/src/r_drawer_context.cpp new file mode 100644 index 000000000..3533a3e4f --- /dev/null +++ b/src/r_drawer_context.cpp @@ -0,0 +1,464 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id:$ +// +// Copyright (C) 1993-1996 by id Software, Inc. +// +// This source is available for distribution and/or modification +// only under the terms of the DOOM Source Code License as +// published by id Software. All rights reserved. +// +// The source is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License +// for more details. +// +// $Log:$ +// +// DESCRIPTION: +// The actual span/column drawing functions. +// Here find the main potential for optimization, +// e.g. inline assembly, different algorithms. +// +//----------------------------------------------------------------------------- + +#define DRAWER_INTERNALS + +#include + +#include "templates.h" +#include "doomdef.h" +#include "i_system.h" +#include "w_wad.h" +#include "r_local.h" +#include "v_video.h" +#include "doomstat.h" +#include "st_stuff.h" +#include "g_game.h" +#include "g_level.h" +#include "r_data/r_translate.h" +#include "v_palette.h" +#include "r_data/colormaps.h" +#include "r_plane.h" +#include "r_draw_rgba.h" +#include "d_net.h" +#include "r_drawer_context.h" + +#include "gi.h" +#include "stats.h" +#include "x86.h" + +#ifdef X86_ASM +extern "C" void R_SetSpanSource_ASM (const BYTE *flat); +extern "C" void R_SetSpanSize_ASM (int xbits, int ybits); +extern "C" void R_SetSpanColormap_ASM (BYTE *colormap); +extern "C" void R_SetTiltedSpanSource_ASM(const BYTE *flat); +extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource; +#endif + +DCanvas *DrawerContext::Canvas() +{ + return dc_canvas; +} + +uint8_t DrawerContext::FlatColor() +{ + return dc_color; +} + +FColormap *DrawerContext::LightColormap() +{ + return dc_fcolormap; +} + +fixed_t DrawerContext::TextureFrac() +{ + return dc_texturefrac; +} + +fixed_t DrawerContext::TextureStep() +{ + return dc_iscale; +} + +double DrawerContext::TextureMid() +{ + return dc_texturemid; +} + +int DrawerContext::SpanXBits() +{ + return ds_xbits; +} + +int DrawerContext::SpanYBits() +{ + return ds_ybits; +} + +lighttable_t *DrawerContext::SpanLitColormap() +{ + return ds_colormap; +} + +bool DrawerContext::IsFuzzColumn() +{ + return colfunc == fuzzcolfunc; +} + +bool DrawerContext::IsFillColumn() +{ + return colfunc == R_FillColumn; +} + +bool DrawerContext::IsBaseColumn() +{ + return colfunc == basecolfunc; +} + +void DrawerContext::SetDest(int x, int y) +{ + int pixelsize = r_swtruecolor ? 4 : 1; + dc_dest = dc_destorg + (ylookup[y] + x) * pixelsize; +} + +void DrawerContext::SetFlatColor(uint8_t color_index) +{ + dc_color = color_index; +} + +void DrawerContext::SetLight(FColormap *base_colormap, float light, int shade) +{ + R_SetColorMapLight(base_colormap, light, shade); +} + +void DrawerContext::SetX(int x) +{ + dc_x = x; +} + +void DrawerContext::SetY1(int y) +{ + dc_yl = y; +} + +void DrawerContext::SetY2(int y) +{ + dc_yh = y; +} + +void DrawerContext::SetSource(const BYTE *source) +{ + dc_source = source; +} + +void DrawerContext::SetTextureFrac(fixed_t pos) +{ + dc_texturefrac = pos; +} + +void DrawerContext::SetTextureStep(fixed_t step) +{ + dc_iscale = step; +} + +void DrawerContext::SetTextureMid(double value) +{ + dc_texturemid = value; +} + +void DrawerContext::SetDrawCount(int count) +{ + dc_count = count; +} + +void DrawerContext::SetSpanY(int y) +{ + ds_y = y; +} + +void DrawerContext::SetSpanX1(int x) +{ + ds_x1 = x; +} + +void DrawerContext::SetSpanX2(int x) +{ + ds_x2 = x; +} + +void DrawerContext::SetSpanXStep(dsfixed_t step) +{ + ds_xstep = step; +} + +void DrawerContext::SetSpanYStep(dsfixed_t step) +{ + ds_ystep = step; +} + +void DrawerContext::SetSpanXBits(int bits) +{ + ds_xbits = bits; +} + +void DrawerContext::SetSpanYBits(int bits) +{ + ds_ybits = bits; +} + +void DrawerContext::SetSpanXFrac(dsfixed_t frac) +{ + ds_xfrac = frac; +} + +void DrawerContext::SetSpanYFrac(dsfixed_t frac) +{ + ds_yfrac = frac; +} + +void DrawerContext::SetSpanLight(FColormap *base_colormap, float light, int shade) +{ + R_SetDSColorMapLight(base_colormap ? base_colormap : &identitycolormap, light, shade); + R_SetSpanColormap(); +} + +ESPSResult DrawerContext::SetPatchStyle(FRenderStyle style, fixed_t alpha, int translation, DWORD color) +{ + return R_SetPatchStyle(style, alpha, translation, color); +} + +ESPSResult DrawerContext::SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color) +{ + return R_SetPatchStyle(style, FLOAT2FIXED(alpha), translation, color); +} + +void DrawerContext::FinishSetPatchStyle() +{ + R_FinishSetPatchStyle(); +} + +void DrawerContext::SetCanvas(DCanvas *canvas) +{ + dc_canvas = canvas; + dc_destorg = canvas->GetBuffer(); + + if (r_swtruecolor != canvas->IsBgra()) + { + r_swtruecolor = canvas->IsBgra(); + R_InitColumnDrawers(); + } +} + +void DrawerContext::SetTranslationMap(lighttable_t *translation) +{ + R_SetTranslationMap(translation ? translation : identitymap); +} + +void DrawerContext::SetSpanSource(FTexture *tex) +{ + R_SetupSpanBits(tex); + if (r_swtruecolor) + ds_source = (const BYTE*)tex->GetPixelsBgra(); + else + ds_source = tex->GetPixels(); + +#ifdef X86_ASM + if (!r_swtruecolor && ds_source != ds_cursource) + { + R_SetSpanSource_ASM (ds_source); + } + if (!r_swtruecolor) + { + if (ds_source != ds_curtiltedsource) + R_SetTiltedSpanSource_ASM(ds_source); + } +#endif +} + +void DrawerContext::SetTiltedSpanState(FVector3 plane_sz, FVector3 plane_su, FVector3 plane_sv, bool plane_shade, float planelightfloat, fixed_t pviewx, fixed_t pviewy) +{ + ds_plane_sz = plane_sz; + ds_plane_su = plane_su; + ds_plane_sv = plane_sv; + ds_plane_shade = plane_shade; + ds_planelightfloat = planelightfloat; + ds_pviewx = pviewx; + ds_pviewy = pviewy; + + if (!plane_shade) + { + for (int i = 0; i < viewwidth; ++i) + { + tiltlighting[i] = DrawerContext::SpanLitColormap(); + } + } +} + +void DrawerContext::SetSlabLight(const BYTE *colormap) +{ + R_SetupDrawSlab(colormap); +} + +void DrawerContext::DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *source, int dest_x, int dest_y) +{ + int pixelsize = r_swtruecolor ? 4 : 1; + R_DrawSlab(dx, v, dy, vi, source, (ylookup[dest_y] + dest_x) * pixelsize + dc_destorg); +} + +void DrawerContext::SetSpanStyle(fixed_t alpha, bool additive, bool masked) +{ + if (spanfunc != R_FillSpan) + { + if (masked) + { + if (alpha < OPAQUE || additive) + { + if (!additive) + { + spanfunc = R_DrawSpanMaskedTranslucent; + dc_srcblend = Col2RGB8[alpha >> 10]; + dc_destblend = Col2RGB8[(OPAQUE - alpha) >> 10]; + dc_srcalpha = alpha; + dc_destalpha = OPAQUE - alpha; + } + else + { + spanfunc = R_DrawSpanMaskedAddClamp; + dc_srcblend = Col2RGB8_LessPrecision[alpha >> 10]; + dc_destblend = Col2RGB8_LessPrecision[FRACUNIT >> 10]; + dc_srcalpha = alpha; + dc_destalpha = OPAQUE - alpha; + } + } + else + { + spanfunc = R_DrawSpanMasked; + } + } + else + { + if (alpha < OPAQUE || additive) + { + if (!additive) + { + spanfunc = R_DrawSpanTranslucent; + dc_srcblend = Col2RGB8[alpha >> 10]; + dc_destblend = Col2RGB8[(OPAQUE - alpha) >> 10]; + dc_srcalpha = alpha; + dc_destalpha = OPAQUE - alpha; + } + else + { + spanfunc = R_DrawSpanAddClamp; + dc_srcblend = Col2RGB8_LessPrecision[alpha >> 10]; + dc_destblend = Col2RGB8_LessPrecision[FRACUNIT >> 10]; + dc_srcalpha = alpha; + dc_destalpha = OPAQUE - alpha; + } + } + else + { + spanfunc = R_DrawSpan; + } + } + } +} + +void DrawerContext::RtInitCols(BYTE *buffer) +{ + rt_initcols(buffer); +} + +void DrawerContext::RtSpanCoverage(int x, int start, int stop) +{ + rt_span_coverage(x, start, stop); +} + +void DrawerContext::SetMaskedColumnState(short *mfloorclip, short *mceilingclip, double spryscale, double sprtopscreen, bool sprflipvert) +{ + dc_mfloorclip = mfloorclip; + dc_mceilingclip = mceilingclip; + dc_spryscale = spryscale; + dc_sprtopscreen = sprtopscreen; + dc_sprflipvert = sprflipvert; +} + +void DrawerContext::DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans) +{ + R_DrawMaskedColumn(x, column, spans); +} + +void DrawerContext::DrawMaskedColumnHoriz(int x, const BYTE *column, const FTexture::Span *spans) +{ + dc_x = x; + R_DrawMaskedColumnHoriz(column, spans); +} + +void DrawerContext::DrawFogBoundary(int x1, int x2, short *uclip, short *dclip) +{ + R_DrawFogBoundary(x1, x2, uclip, dclip); +} + +void DrawerContext::DrawRt4cols(int sx) +{ + rt_draw4cols(sx); +} + +void DrawerContext::DrawColumn() +{ + colfunc(); +} + +void DrawerContext::DrawSpan() +{ + spanfunc(); +} + +void DrawerContext::DrawHColumnPre() +{ + hcolfunc_pre(); +} + +void DrawerContext::DrawSimplePolySpan() +{ + R_DrawSpan(); +} + +void DrawerContext::SetBaseStyle() +{ + colfunc = basecolfunc; + hcolfunc_post1 = rt_map1col; + hcolfunc_post4 = rt_map4cols; +} + +void DrawerContext::DrawWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)) +{ + wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn); +} + +void DrawerContext::DrawMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)) +{ + maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn); +} + +void DrawerContext::DrawTransMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)) +{ + transmaskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn); +} + +void DrawerContext::DrawColoredSpan(int y, int x1, int x2) +{ + R_DrawColoredSpan(y, x1, x2); +} + +void DrawerContext::DrawTiltedSpan(int y, int x1, int x2) +{ + R_DrawTiltedSpan(y, x1, x2); +} + +void DrawerContext::FillTransColumn(int x, int y1, int y2, int color, int alpha) +{ + R_FillTransColumn(x, y1, y2, color, alpha); +} diff --git a/src/r_drawer_context.h b/src/r_drawer_context.h new file mode 100644 index 000000000..64e0bf6a0 --- /dev/null +++ b/src/r_drawer_context.h @@ -0,0 +1,123 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id:$ +// +// Copyright (C) 1993-1996 by id Software, Inc. +// +// This source is available for distribution and/or modification +// only under the terms of the DOOM Source Code License as +// published by id Software. All rights reserved. +// +// The source is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License +// for more details. +// +// DESCRIPTION: +// System specific interface stuff. +// +//----------------------------------------------------------------------------- + + +#ifndef __R_DRAWER_CONTEXT__ +#define __R_DRAWER_CONTEXT__ + +#include "r_defs.h" + +// [RH] Consolidate column drawer selection +enum ESPSResult +{ + DontDraw, // not useful to draw this + DoDraw0, // draw this as if r_columnmethod is 0 + DoDraw1, // draw this as if r_columnmethod is 1 +}; + +struct TiltedPlaneData; + +// Immediate graphics context for column/span based software rendering. +class DrawerContext +{ +public: + static DCanvas *Canvas(); // dc_destorg + + static uint8_t FlatColor(); // dc_color + static FColormap *LightColormap(); // dc_fcolormap + static fixed_t TextureFrac(); // dc_texturefrac + static fixed_t TextureStep(); // dc_iscale + static double TextureMid(); // dc_texturemid + + static int SpanXBits(); // ds_xbits + static int SpanYBits(); // ds_ybits + static lighttable_t *SpanLitColormap(); // ds_colormap + + static bool IsFuzzColumn(); // colfunc == fuzzcolfunc + static bool IsFillColumn(); // colfunc == R_FillColumn + static bool IsBaseColumn(); // colfunc == basecolfunc + + static void SetCanvas(DCanvas *canvas); // dc_destorg + + static void SetFlatColor(uint8_t color_index); // dc_color + static void SetLight(FColormap *base_colormap, float light, int shade); + static void SetTranslationMap(lighttable_t *translation); + static void SetX(int x); // dc_x + static void SetY1(int y); // dc_yl + static void SetY2(int y); // dc_yh + static void SetSource(const BYTE *source); // dc_source + static void SetTextureFrac(fixed_t pos); // dc_texturefrac + static void SetTextureStep(fixed_t step); // dc_iscale + static void SetTextureMid(double value); // dc_texturemid + static void SetDest(int x, int y); // dc_dest + static void SetDrawCount(int count); // dc_count + + static void SetSpanY(int y); // ds_y + static void SetSpanX1(int x); // ds_x1 + static void SetSpanX2(int x); // ds_x2 + static void SetSpanXStep(dsfixed_t step); // ds_xstep + static void SetSpanYStep(dsfixed_t step); // ds_ystep + static void SetSpanXBits(int bits); // ds_xbits + static void SetSpanYBits(int bits); // ds_ybits + static void SetSpanXFrac(dsfixed_t frac); // ds_xfrac + static void SetSpanYFrac(dsfixed_t frac); // ds_yfrac + static void SetSpanLight(FColormap *base_colormap, float light, int shade); + static void SetSpanSource(FTexture *texture); + static void SetSpanStyle(fixed_t alpha, bool additive, bool masked); + + static void SetSlabLight(const BYTE *colormap); + + static ESPSResult SetPatchStyle(FRenderStyle style, fixed_t alpha, int translation, DWORD color); + static ESPSResult SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color); + // Call this after finished drawing the current thing, in case its style was STYLE_Shade + static void SetBaseStyle(); + static void FinishSetPatchStyle(); + + static void SetMaskedColumnState(short *mfloorclip, short *mceilingclip, double spryscale, double sprtopscreen, bool sprflipvert); + static void SetTiltedSpanState(FVector3 plane_sz, FVector3 plane_su, FVector3 plane_sv, bool plane_shade, float planelightfloat, fixed_t pviewx, fixed_t pviewy); + + static void RtInitCols(BYTE *buffer); + static void RtSpanCoverage(int x, int start, int stop); + + static void DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans); + static void DrawMaskedColumnHoriz(int x, const BYTE *column, const FTexture::Span *spans); + + static void DrawRt4cols(int sx); + static void DrawColumn(); + static void DrawHColumnPre(); + static void DrawSpan(); + static void DrawSimplePolySpan(); + + static void DrawWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr); + static void DrawMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr); + static void DrawTransMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr); + + static void DrawColoredSpan(int y, int x1, int x2); + static void DrawTiltedSpan(int y, int x1, int x2); + + static void DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *source, int dest_x, int dest_y); + + static void FillTransColumn(int x, int y1, int y2, int color, int alpha); + + static void DrawFogBoundary(int x1, int x2, short *uclip, short *dclip); +}; + +#endif diff --git a/src/r_drawt.cpp b/src/r_drawt.cpp index 837093044..a74dc0133 100644 --- a/src/r_drawt.cpp +++ b/src/r_drawt.cpp @@ -38,6 +38,8 @@ ** Let's hope so. :-) */ +#define DRAWER_INTERNALS + #include "templates.h" #include "doomtype.h" #include "doomdef.h" @@ -1128,26 +1130,26 @@ void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span) const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length) - 1); + dc_yl = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * top); + dc_yh = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * (top + length) - 1); - if (sprflipvert) + if (dc_sprflipvert) { swapvalues (dc_yl, dc_yh); } - if (dc_yh >= mfloorclip[dc_x]) + if (dc_yh >= dc_mfloorclip[dc_x]) { - dc_yh = mfloorclip[dc_x] - 1; + dc_yh = dc_mfloorclip[dc_x] - 1; } - if (dc_yl < mceilingclip[dc_x]) + if (dc_yl < dc_mceilingclip[dc_x]) { - dc_yl = mceilingclip[dc_x]; + dc_yl = dc_mceilingclip[dc_x]; } if (dc_yl <= dc_yh) { - if (sprflipvert) + if (dc_sprflipvert) { dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - fixed_t(CenterY * dc_iscale) - texturemid; @@ -1178,7 +1180,7 @@ void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span) } fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) + if (dc_yh < dc_mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) { dc_yh++; } @@ -1198,7 +1200,7 @@ nextpost: span++; } - if (sprflipvert) + if (dc_sprflipvert) { unsigned int *front = horizspan[dc_x&3]; unsigned int *back = dc_ctspan[dc_x&3] - 2; diff --git a/src/r_drawt_rgba.cpp b/src/r_drawt_rgba.cpp index d2d715c8d..4b6605b4a 100644 --- a/src/r_drawt_rgba.cpp +++ b/src/r_drawt_rgba.cpp @@ -34,6 +34,8 @@ ** Please see r_drawt.cpp for a description of the globals used. */ +#define DRAWER_INTERNALS + #include "templates.h" #include "doomtype.h" #include "doomdef.h" diff --git a/src/r_main.cpp b/src/r_main.cpp index 247a98125..a30aa232b 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -23,6 +23,8 @@ // //----------------------------------------------------------------------------- +#define DRAWER_INTERNALS + // HEADER FILES ------------------------------------------------------------ #include @@ -150,17 +152,6 @@ angle_t xtoviewangle[MAXWIDTH+1]; bool foggy; // [RH] ignore extralight and fullbright? int r_actualextralight; -void (*colfunc) (void); -void (*basecolfunc) (void); -void (*fuzzcolfunc) (void); -void (*transcolfunc) (void); -void (*spanfunc) (void); - -void (*hcolfunc_pre) (void); -void (*hcolfunc_post1) (int hx, int sx, int yl, int yh); -void (*hcolfunc_post2) (int hx, int sx, int yl, int yh); -void (*hcolfunc_post4) (int sx, int yl, int yh); - cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -820,6 +811,7 @@ void R_SetupBuffer () ASM_PatchPitch (); #endif } + dc_canvas = RenderTarget; dc_destorg = lineptr; for (int i = 0; i < RenderTarget->GetHeight(); i++) { diff --git a/src/r_main.h b/src/r_main.h index fa8fe0bb1..91eb5b183 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -110,22 +110,6 @@ extern FColormap* fixedcolormap; extern FSpecialColormap*realfixedcolormap; -// -// Function pointers to switch refresh/drawing functions. -// Used to select shadow mode etc. -// -extern void (*colfunc) (void); -extern void (*basecolfunc) (void); -extern void (*fuzzcolfunc) (void); -extern void (*transcolfunc) (void); -// No shadow effects on floors. -extern void (*spanfunc) (void); - -// [RH] Function pointers for the horizontal column drawers. -extern void (*hcolfunc_pre) (void); -extern void (*hcolfunc_post1) (int hx, int sx, int yl, int yh); -extern void (*hcolfunc_post2) (int hx, int sx, int yl, int yh); -extern void (*hcolfunc_post4) (int sx, int yl, int yh); void R_InitTextureMapping (); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 807066f77..c4d7cd59c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -58,7 +58,7 @@ #include "r_3dfloors.h" #include "v_palette.h" #include "r_data/colormaps.h" -#include "r_draw_rgba.h" +#include "r_drawer_context.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -138,8 +138,6 @@ FVector3 plane_sz, plane_su, plane_sv; float planelightfloat; bool plane_shade; fixed_t pviewx, pviewy; - -void R_DrawTiltedPlane_ASM (int y, int x1); } float yslope[MAXHEIGHT]; @@ -147,13 +145,6 @@ static fixed_t xscale, yscale; static double xstepscale, ystepscale; static double basexfrac, baseyfrac; -#ifdef X86_ASM -extern "C" void R_SetSpanSource_ASM (const BYTE *flat); -extern "C" void R_SetSpanSize_ASM (int xbits, int ybits); -extern "C" void R_SetSpanColormap_ASM (BYTE *colormap); -extern "C" void R_SetTiltedSpanSource_ASM (const BYTE *flat); -extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource; -#endif void R_DrawSinglePlane (visplane_t *, fixed_t alpha, bool additive, bool masked); //========================================================================== @@ -220,304 +211,22 @@ void R_MapPlane (int y, int x1) distance = planeheight * yslope[y]; - ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale); - ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale); - ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx; - ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy; + DrawerContext::SetSpanXStep(xs_ToFixed(32 - DrawerContext::SpanXBits(), distance * xstepscale)); + DrawerContext::SetSpanYStep(xs_ToFixed(32 - DrawerContext::SpanYBits(), distance * ystepscale)); + DrawerContext::SetSpanXFrac(xs_ToFixed(32 - DrawerContext::SpanXBits(), distance * basexfrac) + pviewx); + DrawerContext::SetSpanYFrac(xs_ToFixed(32 - DrawerContext::SpanYBits(), distance * baseyfrac) + pviewy); if (plane_shade) { // Determine lighting based on the span's distance from the viewer. - R_SetDSColorMapLight(basecolormap, GlobVis * fabs(CenterY - y), planeshade); + DrawerContext::SetSpanLight(basecolormap, GlobVis * fabs(CenterY - y), planeshade); } -#ifdef X86_ASM - if (!r_swtruecolor && ds_colormap != ds_curcolormap) - R_SetSpanColormap_ASM (ds_colormap); -#endif + DrawerContext::SetSpanY(y); + DrawerContext::SetSpanX1(x1); + DrawerContext::SetSpanX2(x2); - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - - spanfunc (); -} - -//========================================================================== -// -// R_CalcTiltedLighting -// -// Calculates the lighting for one row of a tilted plane. If the definition -// of GETPALOOKUP changes, this needs to change, too. -// -//========================================================================== - -extern "C" { -void R_CalcTiltedLighting (double lval, double lend, int width) -{ - double lstep; - BYTE *lightfiller; - BYTE *basecolormapdata = basecolormap->Maps; - int i = 0; - - if (width == 0 || lval == lend) - { // Constant lighting - lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT); - } - else - { - lstep = (lend - lval) / width; - if (lval >= MAXLIGHTVIS) - { // lval starts "too bright". - lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT); - for (; i <= width && lval >= MAXLIGHTVIS; ++i) - { - tiltlighting[i] = lightfiller; - lval += lstep; - } - } - if (lend >= MAXLIGHTVIS) - { // lend ends "too bright". - lightfiller = basecolormapdata + (GETPALOOKUP(lend, planeshade) << COLORMAPSHIFT); - for (; width > i && lend >= MAXLIGHTVIS; --width) - { - tiltlighting[width] = lightfiller; - lend -= lstep; - } - } - if (width > 0) - { - lval = FIXED2DBL(planeshade) - lval; - lend = FIXED2DBL(planeshade) - lend; - lstep = (lend - lval) / width; - if (lstep < 0) - { // Going from dark to light - if (lval < 1.) - { // All bright - lightfiller = basecolormapdata; - } - else - { - if (lval >= NUMCOLORMAPS) - { // Starts beyond the dark end - BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); - while (lval >= NUMCOLORMAPS && i <= width) - { - tiltlighting[i++] = clight; - lval += lstep; - } - if (i > width) - return; - } - while (i <= width && lval >= 0) - { - tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT); - lval += lstep; - } - lightfiller = basecolormapdata; - } - } - else - { // Going from light to dark - if (lval >= (NUMCOLORMAPS-1)) - { // All dark - lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); - } - else - { - while (lval < 0 && i <= width) - { - tiltlighting[i++] = basecolormapdata; - lval += lstep; - } - if (i > width) - return; - while (i <= width && lval < (NUMCOLORMAPS-1)) - { - tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT); - lval += lstep; - } - lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); - } - } - } - } - for (; i <= width; i++) - { - tiltlighting[i] = lightfiller; - } -} -} // extern "C" - -//========================================================================== -// -// R_MapTiltedPlane -// -//========================================================================== - -void R_MapTiltedPlane_C (int y, int x1) -{ - int x2 = spanend[y]; - int width = x2 - x1; - double iz, uz, vz; - BYTE *fb; - DWORD u, v; - int i; - - iz = plane_sz[2] + plane_sz[1]*(centery-y) + plane_sz[0]*(x1-centerx); - - // Lighting is simple. It's just linear interpolation from start to end - if (plane_shade) - { - uz = (iz + plane_sz[0]*width) * planelightfloat; - vz = iz * planelightfloat; - R_CalcTiltedLighting (vz, uz, width); - } - - uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx); - vz = plane_sv[2] + plane_sv[1]*(centery-y) + plane_sv[0]*(x1-centerx); - - fb = ylookup[y] + x1 + dc_destorg; - - BYTE vshift = 32 - ds_ybits; - BYTE ushift = vshift - ds_xbits; - int umask = ((1 << ds_xbits) - 1) << ds_ybits; - -#if 0 // The "perfect" reference version of this routine. Pretty slow. - // Use it only to see how things are supposed to look. - i = 0; - do - { - double z = 1.f/iz; - - u = SQWORD(uz*z) + pviewx; - v = SQWORD(vz*z) + pviewy; - R_SetDSColorMapLight(tiltlighting[i], 0, 0); - fb[i++] = ds_colormap[ds_source[(v >> vshift) | ((u >> ushift) & umask)]]; - iz += plane_sz[0]; - uz += plane_su[0]; - vz += plane_sv[0]; - } while (--width >= 0); -#else -//#define SPANSIZE 32 -//#define INVSPAN 0.03125f -//#define SPANSIZE 8 -//#define INVSPAN 0.125f -#define SPANSIZE 16 -#define INVSPAN 0.0625f - - double startz = 1.f/iz; - double startu = uz*startz; - double startv = vz*startz; - double izstep, uzstep, vzstep; - - izstep = plane_sz[0] * SPANSIZE; - uzstep = plane_su[0] * SPANSIZE; - vzstep = plane_sv[0] * SPANSIZE; - x1 = 0; - width++; - - while (width >= SPANSIZE) - { - iz += izstep; - uz += uzstep; - vz += vzstep; - - double endz = 1.f/iz; - double endu = uz*endz; - double endv = vz*endz; - DWORD stepu = SQWORD((endu - startu) * INVSPAN); - DWORD stepv = SQWORD((endv - startv) * INVSPAN); - u = SQWORD(startu) + pviewx; - v = SQWORD(startv) + pviewy; - - for (i = SPANSIZE-1; i >= 0; i--) - { - fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); - x1++; - u += stepu; - v += stepv; - } - startu = endu; - startv = endv; - width -= SPANSIZE; - } - if (width > 0) - { - if (width == 1) - { - u = SQWORD(startu); - v = SQWORD(startv); - fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); - } - else - { - double left = width; - iz += plane_sz[0] * left; - uz += plane_su[0] * left; - vz += plane_sv[0] * left; - - double endz = 1.f/iz; - double endu = uz*endz; - double endv = vz*endz; - left = 1.f/left; - DWORD stepu = SQWORD((endu - startu) * left); - DWORD stepv = SQWORD((endv - startv) * left); - u = SQWORD(startu) + pviewx; - v = SQWORD(startv) + pviewy; - - for (; width != 0; width--) - { - fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]); - x1++; - u += stepu; - v += stepv; - } - } - } -#endif -} - -void R_MapTiltedPlane_rgba (int y, int x1) -{ - int x2 = spanend[y]; - - // Slopes are broken currently in master. - // Until R_DrawTiltedPlane is fixed we are just going to fill with a solid color. - - uint32_t *source = (uint32_t*)ds_source; - int source_width = 1 << ds_xbits; - int source_height = 1 << ds_ybits; - - uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg; - - int count = x2 - x1 + 1; - while (count > 0) - { - *(dest++) = source[0]; - count--; - } -} - -//========================================================================== -// -// R_MapColoredPlane -// -//========================================================================== - -void R_MapColoredPlane_C (int y, int x1) -{ - memset (ylookup[y] + x1 + dc_destorg, ds_color, spanend[y] - x1 + 1); -} - -void R_MapColoredPlane_rgba(int y, int x1) -{ - uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg; - int count = (spanend[y] - x1 + 1); - uint32_t light = calc_light_multiplier(ds_light); - uint32_t color = shade_pal_index_simple(ds_color, light); - for (int i = 0; i < count; i++) - dest[i] = color; + DrawerContext::DrawSpan(); } //========================================================================== @@ -1014,7 +723,7 @@ static void R_DrawSky (visplane_t *pl) rw_offset = 0; frontyScale = rw_pic->Scale.Y; - dc_texturemid = skymid * frontyScale; + DrawerContext::SetTextureMid(skymid * frontyScale); if (1 << frontskytex->HeightBits == frontskytex->GetHeight()) { // The texture tiles nicely @@ -1023,8 +732,8 @@ static void R_DrawSky (visplane_t *pl) lastskycol[x] = 0xffffffff; lastskycol_bgra[x] = 0xffffffff; } - wallscan (pl->left, pl->right, (short *)pl->top, (short *)pl->bottom, swall, lwall, - frontyScale, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); + DrawerContext::DrawWall (pl->left, pl->right, (short *)pl->top, (short *)pl->bottom, swall, lwall, + frontyScale, rw_pic, rw_offset, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); } else { // The texture does not tile nicely @@ -1047,7 +756,7 @@ static void R_DrawSkyStriped (visplane_t *pl) if (topfrac < 0) topfrac += frontskytex->GetHeight(); yl = 0; yh = short((frontskytex->GetHeight() - topfrac) * frontyScale); - dc_texturemid = topfrac - iscale * (1 - CenterY); + DrawerContext::SetTextureMid(topfrac - iscale * (1 - CenterY)); while (yl < viewheight) { @@ -1061,11 +770,11 @@ static void R_DrawSkyStriped (visplane_t *pl) lastskycol[x] = 0xffffffff; lastskycol_bgra[x] = 0xffffffff; } - wallscan (pl->left, pl->right, top, bot, swall, lwall, rw_pic->Scale.Y, - backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); + DrawerContext::DrawWall(pl->left, pl->right, top, bot, swall, lwall, rw_pic->Scale.Y, + rw_pic, rw_offset, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); yl = yh; yh += drawheight; - dc_texturemid = iscale * (centery-yl-1); + DrawerContext::SetTextureMid(iscale * (centery-yl-1)); } } @@ -1086,7 +795,7 @@ int R_DrawPlanes () int i; int vpcount = 0; - ds_color = 3; + DrawerContext::SetFlatColor(3); for (i = 0; i < MAXVISPLANES; i++) { @@ -1111,7 +820,7 @@ void R_DrawHeightPlanes(double height) visplane_t *pl; int i; - ds_color = 3; + DrawerContext::SetFlatColor(3); DVector3 oViewPos = ViewPos; DAngle oViewAngle = ViewAngle; @@ -1151,8 +860,8 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske if (r_drawflat) { // [RH] no texture mapping - ds_color += 4; - R_MapVisPlane (pl, R_MapColoredPlane); + DrawerContext::SetFlatColor(DrawerContext::FlatColor() + 4); + R_MapVisPlane (pl, [](int y, int x1) { DrawerContext::DrawColoredSpan(y, x1, spanend[y]); }); } else if (pl->picnum == skyflatnum) { // sky flat @@ -1175,13 +884,9 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske { // Don't waste time on a masked texture if it isn't really masked. masked = false; } - R_SetupSpanBits(tex); double xscale = pl->xform.xScale * tex->Scale.X; double yscale = pl->xform.yScale * tex->Scale.Y; - if (r_swtruecolor) - ds_source = (const BYTE*)tex->GetPixelsBgra(); - else - ds_source = tex->GetPixels(); + DrawerContext::SetSpanSource(tex); basecolormap = pl->colormap; planeshade = LIGHT2SHADE(pl->lightlevel); @@ -1544,13 +1249,13 @@ void R_DrawSkyPlane (visplane_t *pl) bool fakefixed = false; if (fixedcolormap) { - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); } else { fakefixed = true; fixedcolormap = &NormalLight; - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); } R_DrawSky (pl); @@ -1567,13 +1272,6 @@ void R_DrawSkyPlane (visplane_t *pl) void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked) { -#ifdef X86_ASM - if (!r_swtruecolor && ds_source != ds_cursource) - { - R_SetSpanSource_ASM (ds_source); - } -#endif - if (alpha <= 0) { return; @@ -1583,8 +1281,8 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac; double x; - xscale = xs_ToFixed(32 - ds_xbits, _xscale); - yscale = xs_ToFixed(32 - ds_ybits, _yscale); + xscale = xs_ToFixed(32 - DrawerContext::SpanXBits(), _xscale); + yscale = xs_ToFixed(32 - DrawerContext::SpanYBits(), _yscale); if (planeang != 0) { double cosine = cos(planeang), sine = sin(planeang); @@ -1631,15 +1329,14 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t planeheight = fabs(pl->height.Zat0() - ViewPos.Z); GlobVis = r_FloorVisibility / planeheight; - ds_light = 0; if (fixedlightlev >= 0) { - R_SetDSColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetSpanLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); plane_shade = false; } else if (fixedcolormap) { - R_SetDSColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetSpanLight(fixedcolormap, 0, 0); plane_shade = false; } else @@ -1647,61 +1344,8 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t plane_shade = true; } - if (spanfunc != R_FillSpan) - { - if (masked) - { - if (alpha < OPAQUE || additive) - { - if (!additive) - { - spanfunc = R_DrawSpanMaskedTranslucent; - dc_srcblend = Col2RGB8[alpha>>10]; - dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10]; - dc_srcalpha = alpha; - dc_destalpha = OPAQUE - alpha; - } - else - { - spanfunc = R_DrawSpanMaskedAddClamp; - dc_srcblend = Col2RGB8_LessPrecision[alpha>>10]; - dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10]; - dc_srcalpha = alpha; - dc_destalpha = OPAQUE - alpha; - } - } - else - { - spanfunc = R_DrawSpanMasked; - } - } - else - { - if (alpha < OPAQUE || additive) - { - if (!additive) - { - spanfunc = R_DrawSpanTranslucent; - dc_srcblend = Col2RGB8[alpha>>10]; - dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10]; - dc_srcalpha = alpha; - dc_destalpha = OPAQUE - alpha; - } - else - { - spanfunc = R_DrawSpanAddClamp; - dc_srcblend = Col2RGB8_LessPrecision[alpha>>10]; - dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10]; - dc_srcalpha = alpha; - dc_destalpha = OPAQUE - alpha; - } - } - else - { - spanfunc = R_DrawSpan; - } - } - } + DrawerContext::SetSpanStyle(alpha, additive, masked); + R_MapVisPlane (pl, R_MapPlane); } @@ -1733,14 +1377,14 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t return; } - lxscale = _xscale * ifloatpow2[ds_xbits]; - lyscale = _yscale * ifloatpow2[ds_ybits]; + lxscale = _xscale * ifloatpow2[DrawerContext::SpanXBits()]; + lyscale = _yscale * ifloatpow2[DrawerContext::SpanYBits()]; xscale = 64.f / lxscale; yscale = 64.f / lyscale; zeroheight = pl->height.ZatPoint(ViewPos); - pviewx = xs_ToFixed(32 - ds_xbits, pl->xform.xOffs * pl->xform.xScale); - pviewy = xs_ToFixed(32 - ds_ybits, pl->xform.yOffs * pl->xform.yScale); + pviewx = xs_ToFixed(32 - DrawerContext::SpanXBits(), pl->xform.xOffs * pl->xform.xScale); + pviewy = xs_ToFixed(32 - DrawerContext::SpanYBits(), pl->xform.yOffs * pl->xform.yScale); planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians(); // p is the texture origin in view space @@ -1810,42 +1454,22 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t if (fixedlightlev >= 0) { - R_SetDSColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetSpanLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); plane_shade = false; } else if (fixedcolormap) { - R_SetDSColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetSpanLight(fixedcolormap, 0, 0); plane_shade = false; } else { - R_SetDSColorMapLight(basecolormap, 0, 0); + DrawerContext::SetSpanLight(basecolormap, 0, 0); plane_shade = true; } - if (!plane_shade) - { - for (int i = 0; i < viewwidth; ++i) - { - tiltlighting[i] = ds_colormap; - } - } - -#if defined(X86_ASM) - if (!r_swtruecolor) - { - if (ds_source != ds_curtiltedsource) - R_SetTiltedSpanSource_ASM(ds_source); - R_MapVisPlane(pl, R_DrawTiltedPlane_ASM); - } - else - { - R_MapVisPlane(pl, R_MapTiltedPlane); - } -#else - R_MapVisPlane (pl, R_MapTiltedPlane); -#endif + DrawerContext::SetTiltedSpanState(plane_sz, plane_su, plane_sv, plane_shade, planelightfloat, pviewx, pviewy); + R_MapVisPlane (pl, [](int y, int x1) { DrawerContext::DrawTiltedSpan(y, x1, spanend[y]); }); } //========================================================================== diff --git a/src/r_plane.h b/src/r_plane.h index b199d3477..d4db3dc09 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -93,14 +93,6 @@ void R_DrawNormalPlane (visplane_t *pl, double xscale, double yscale, fixed_t al void R_DrawTiltedPlane (visplane_t *pl, double xscale, double yscale, fixed_t alpha, bool additive, bool masked); void R_MapVisPlane (visplane_t *pl, void (*mapfunc)(int y, int x1)); -extern void(*R_MapColoredPlane)(int y, int x1); -extern void(*R_MapTiltedPlane)(int y, int x1); - -void R_MapTiltedPlane_C(int y, int x1); -void R_MapTiltedPlane_rgba(int y, int x); -void R_MapColoredPlane_C(int y, int x1); -void R_MapColoredPlane_rgba(int y, int x1); - visplane_t *R_FindPlane ( const secplane_t &height, FTextureID picnum, diff --git a/src/r_segs.cpp b/src/r_segs.cpp index ad242b2f9..2476e07ac 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -52,6 +52,7 @@ #include "r_3dfloors.h" #include "v_palette.h" #include "r_data/colormaps.h" +#include "r_drawer_context.h" #define WALLYREPEAT 8 @@ -172,19 +173,19 @@ CVAR(Bool, r_drawmirrors, true, 0) float *MaskedSWall; float MaskedScaleY; -static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FTexture::Span *spans), FTexture *tex) +static void BlastMaskedColumn (int x, void (*blastfunc)(int x, const BYTE *pixels, const FTexture::Span *spans), FTexture *tex) { // calculate lighting if (fixedcolormap == NULL && fixedlightlev < 0) { - R_SetColorMapLight(basecolormap, rw_light, wallshade); + DrawerContext::SetLight(basecolormap, rw_light, wallshade); } - dc_iscale = xs_Fix<16>::ToFix(MaskedSWall[dc_x] * MaskedScaleY); + DrawerContext::SetTextureStep(xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY)); if (sprflipvert) - sprtopscreen = CenterY + dc_texturemid * spryscale; + sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale; else - sprtopscreen = CenterY - dc_texturemid * spryscale; + sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale; // killough 1/25/98: here's where Medusa came in, because // it implicitly assumed that the column was all one patch. @@ -194,10 +195,12 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText // the Medusa effect. The fix is to construct true columns // when forming multipatched textures (see r_data.c). + DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert); + // draw the texture const FTexture::Span *spans; - const BYTE *pixels = tex->GetColumn (maskedtexturecol[dc_x] >> FRACBITS, &spans); - blastfunc (pixels, spans); + const BYTE *pixels = tex->GetColumn (maskedtexturecol[x] >> FRACBITS, &spans); + blastfunc (x, pixels, spans); rw_light += rw_lightstep; spryscale += rw_scalestep; } @@ -243,7 +246,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) // [RH] modified because we don't use user-definable translucency maps ESPSResult drawmode; - drawmode = R_SetPatchStyle (LegacyRenderStyles[curline->linedef->flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent], + drawmode = DrawerContext::SetPatchStyle (LegacyRenderStyles[curline->linedef->flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent], (float)MIN(curline->linedef->alpha, 1.), 0, 0); if ((drawmode == DontDraw && !ds->bFogBoundary && !ds->bFakeBoundary)) @@ -295,7 +298,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) // [RH] Draw fog partition if (ds->bFogBoundary) { - R_DrawFogBoundary (x1, x2, mceilingclip, mfloorclip); + DrawerContext::DrawFogBoundary (x1, x2, mceilingclip, mfloorclip); if (ds->maskedtexturecol == -1) { goto clearfog; @@ -313,9 +316,9 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) rw_scalestep = ds->iscalestep; if (fixedlightlev >= 0) - R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); // find positioning texheight = tex->GetScaledHeightDouble(); @@ -326,11 +329,11 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) } if (curline->linedef->flags & ML_DONTPEGBOTTOM) { - dc_texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; + DrawerContext::SetTextureMid(MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight); } else { - dc_texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + DrawerContext::SetTextureMid(MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling))); } rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); @@ -349,21 +352,21 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) { // rowoffset is added before the multiply so that the masked texture will // still be positioned in world units rather than texels. - dc_texturemid += rowoffset - ViewPos.Z; - textop = dc_texturemid; - dc_texturemid *= MaskedScaleY; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset - ViewPos.Z); + textop = DrawerContext::TextureMid(); + DrawerContext::SetTextureMid(DrawerContext::TextureMid() * MaskedScaleY); } else { // rowoffset is added outside the multiply so that it positions the texture // by texels instead of world units. - textop = dc_texturemid + rowoffset / MaskedScaleY - ViewPos.Z; - dc_texturemid = (dc_texturemid - ViewPos.Z) * MaskedScaleY + rowoffset; + textop = DrawerContext::TextureMid() + rowoffset / MaskedScaleY - ViewPos.Z; + DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z) * MaskedScaleY + rowoffset); } if (sprflipvert) { MaskedScaleY = -MaskedScaleY; - dc_texturemid -= tex->GetHeight() << FRACBITS; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - tex->GetHeight()); } // [RH] Don't bother drawing segs that are completely offscreen @@ -438,9 +441,9 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) // draw the columns one at a time if (drawmode == DoDraw0) { - for (dc_x = x1; dc_x < x2; ++dc_x) + for (int x = x1; x < x2; ++x) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex); } } else @@ -451,29 +454,29 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) if (x1 >= x2) goto clearfog; - dc_x = x1; + int x = x1; - while ((dc_x < stop) && (dc_x & 3)) + while ((x < stop) && (x & 3)) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); - dc_x++; + BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex); + x++; } - while (dc_x < stop) + while (x < stop) { - rt_initcols(nullptr); - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); - rt_draw4cols (dc_x - 3); - dc_x++; + DrawerContext::RtInitCols(nullptr); + BlastMaskedColumn (x, DrawerContext::DrawMaskedColumnHoriz, tex); + BlastMaskedColumn (x + 1, DrawerContext::DrawMaskedColumnHoriz, tex); + BlastMaskedColumn (x + 2, DrawerContext::DrawMaskedColumnHoriz, tex); + BlastMaskedColumn (x + 3, DrawerContext::DrawMaskedColumnHoriz, tex); + DrawerContext::DrawRt4cols (x); + x += 4; } - while (dc_x < x2) + while (x < x2) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); - dc_x++; + BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex); + x++; } } } @@ -483,13 +486,13 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) { // rowoffset is added before the multiply so that the masked texture will // still be positioned in world units rather than texels. - dc_texturemid = (dc_texturemid - ViewPos.Z + rowoffset) * MaskedScaleY; + DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z + rowoffset) * MaskedScaleY); } else { // rowoffset is added outside the multiply so that it positions the texture // by texels instead of world units. - dc_texturemid = (dc_texturemid - ViewPos.Z) * MaskedScaleY + rowoffset; + DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z) * MaskedScaleY + rowoffset); } WallC.sz1 = ds->sz1; @@ -535,7 +538,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) } clearfog: - R_FinishSetPatchStyle (); + DrawerContext::FinishSetPatchStyle (); if (ds->bFakeBoundary & 3) { R_RenderFakeWallRange(ds, x1, x2); @@ -567,11 +570,11 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255); ESPSResult drawmode; - drawmode = R_SetPatchStyle (LegacyRenderStyles[rover->flags & FF_ADDITIVETRANS ? STYLE_Add : STYLE_Translucent], + drawmode = DrawerContext::SetPatchStyle (LegacyRenderStyles[rover->flags & FF_ADDITIVETRANS ? STYLE_Add : STYLE_Translucent], Alpha, 0, 0); if(drawmode == DontDraw) { - R_FinishSetPatchStyle(); + DrawerContext::FinishSetPatchStyle(); return; } @@ -613,26 +616,26 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) { rowoffset += rw_pic->GetHeight(); } - dc_texturemid = (planez - ViewPos.Z) * yscale; + DrawerContext::SetTextureMid((planez - ViewPos.Z) * yscale); if (rw_pic->bWorldPanning) { // rowoffset is added before the multiply so that the masked texture will // still be positioned in world units rather than texels. - dc_texturemid = dc_texturemid + rowoffset * yscale; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset * yscale); rw_offset = xs_RoundToInt(rw_offset * xscale); } else { // rowoffset is added outside the multiply so that it positions the texture // by texels instead of world units. - dc_texturemid += rowoffset; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset); } if (fixedlightlev >= 0) - R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); WallC.sz1 = ds->sz1; WallC.sz2 = ds->sz2; @@ -660,7 +663,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) PrepLWall (lwall, curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2); wallscan_np2_ds(ds, x1, x2, wallupper, walllower, MaskedSWall, lwall, yscale); - R_FinishSetPatchStyle(); + DrawerContext::FinishSetPatchStyle(); } // kg3D - walls of fake floors @@ -1065,360 +1068,6 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2) return; } -// Draw a column with support for non-power-of-two ranges -uint32_t wallscan_drawcol1(int x, int y1, int y2, uint32_t uv_start, uint32_t uv_step, uint32_t uv_max, const BYTE *source, DWORD(*draw1column)()) -{ - int pixelsize = r_swtruecolor ? 4 : 1; - if (uv_max == 0) // power of two - { - int count = y2 - y1; - - dc_source = source; - dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; - dc_count = count; - dc_iscale = uv_step; - dc_texturefrac = uv_start; - draw1column(); - - uint64_t step64 = uv_step; - uint64_t pos64 = uv_start; - return (uint32_t)(pos64 + step64 * count); - } - else - { - uint32_t uv_pos = uv_start; - - uint32_t left = y2 - y1; - while (left > 0) - { - uint32_t available = uv_max - uv_pos; - uint32_t next_uv_wrap = available / uv_step; - if (available % uv_step != 0) - next_uv_wrap++; - uint32_t count = MIN(left, next_uv_wrap); - - dc_source = source; - dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; - dc_count = count; - dc_iscale = uv_step; - dc_texturefrac = uv_pos; - draw1column(); - - left -= count; - uv_pos += uv_step * count; - if (uv_pos >= uv_max) - uv_pos -= uv_max; - } - - return uv_pos; - } -} - -// Draw four columns with support for non-power-of-two ranges -void wallscan_drawcol4(int x, int y1, int y2, uint32_t *uv_pos, uint32_t *uv_step, uint32_t uv_max, const BYTE **source, void(*draw4columns)()) -{ - int pixelsize = r_swtruecolor ? 4 : 1; - if (uv_max == 0) // power of two, no wrap handling needed - { - int count = y2 - y1; - for (int i = 0; i < 4; i++) - { - bufplce[i] = source[i]; - vplce[i] = uv_pos[i]; - vince[i] = uv_step[i]; - - uint64_t step64 = uv_step[i]; - uint64_t pos64 = uv_pos[i]; - uv_pos[i] = (uint32_t)(pos64 + step64 * count); - } - dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; - dc_count = count; - draw4columns(); - } - else - { - dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg; - for (int i = 0; i < 4; i++) - bufplce[i] = source[i]; - - uint32_t left = y2 - y1; - while (left > 0) - { - // Find which column wraps first - uint32_t count = left; - for (int i = 0; i < 4; i++) - { - uint32_t available = uv_max - uv_pos[i]; - uint32_t next_uv_wrap = available / uv_step[i]; - if (available % uv_step[i] != 0) - next_uv_wrap++; - count = MIN(next_uv_wrap, count); - } - - // Draw until that column wraps - for (int i = 0; i < 4; i++) - { - vplce[i] = uv_pos[i]; - vince[i] = uv_step[i]; - } - dc_count = count; - draw4columns(); - - // Wrap the uv position - for (int i = 0; i < 4; i++) - { - uv_pos[i] += uv_step[i] * count; - if (uv_pos[i] >= uv_max) - uv_pos[i] -= uv_max; - } - - left -= count; - } - } -} - -// Calculates a wrapped uv start position value for a column -void calc_uv_start_and_step(int y1, float swal, double yrepeat, uint32_t uv_height, int fracbits, uint32_t &uv_start_out, uint32_t &uv_step_out) -{ - double uv_stepd = swal * yrepeat; - - // Find start uv in [0-uv_height[ range. - // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. - double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / uv_height; - v = v - floor(v); - v *= uv_height; - v *= (1 << fracbits); - - uv_start_out = (uint32_t)v; - uv_step_out = xs_ToFixed(fracbits, uv_stepd); -} - -typedef DWORD(*Draw1ColumnFuncPtr)(); -typedef void(*Draw4ColumnsFuncPtr)(); - -void wallscan_any( - int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, - const BYTE *(*getcol)(FTexture *tex, int x), - void(setupwallscan(int bits,Draw1ColumnFuncPtr &draw1, Draw4ColumnsFuncPtr &draw2))) -{ - if (rw_pic->UseType == FTexture::TEX_Null) - return; - - uint32_t uv_height = rw_pic->GetHeight(); - uint32_t fracbits = 32 - rw_pic->HeightBits; - uint32_t uv_max = uv_height << fracbits; - - DWORD(*draw1column)(); - void(*draw4columns)(); - setupwallscan(fracbits, draw1column, draw4columns); - - fixed_t xoffset = rw_offset; - - bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0); - if (fixed) - { - palookupoffse[0] = dc_colormap; - palookupoffse[1] = dc_colormap; - palookupoffse[2] = dc_colormap; - palookupoffse[3] = dc_colormap; - palookuplight[0] = 0; - palookuplight[1] = 0; - palookuplight[2] = 0; - palookuplight[3] = 0; - } - - if (fixedcolormap) - R_SetColorMapLight(fixedcolormap, 0, 0); - else - R_SetColorMapLight(basecolormap, 0, 0); - - float light = rw_light; - - // Calculate where 4 column alignment begins and ends: - int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2); - int aligned_x2 = clamp(x2 / 4 * 4, x1, x2); - - // First unaligned columns: - for (int x = x1; x < aligned_x1; x++, light += rw_lightstep) - { - int y1 = uwal[x]; - int y2 = dwal[x]; - if (y2 <= y1) - continue; - - if (!fixed) - R_SetColorMapLight(basecolormap, light, wallshade); - - const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS); - - uint32_t uv_start, uv_step; - calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step); - - wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column); - } - - // The aligned columns - for (int x = aligned_x1; x < aligned_x2; x += 4) - { - // Find y1, y2, light and uv values for four columns: - int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] }; - int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] }; - - const BYTE *source[4]; - for (int i = 0; i < 4; i++) - source[i] = getcol(rw_pic, (lwal[x + i] + xoffset) >> FRACBITS); - - float lights[4]; - for (int i = 0; i < 4; i++) - { - lights[i] = light; - light += rw_lightstep; - } - - uint32_t uv_pos[4], uv_step[4]; - for (int i = 0; i < 4; i++) - calc_uv_start_and_step(y1[i], swal[x + i], yrepeat, uv_height, fracbits, uv_pos[i], uv_step[i]); - - // Figure out where we vertically can start and stop drawing 4 columns in one go - int middle_y1 = y1[0]; - int middle_y2 = y2[0]; - for (int i = 1; i < 4; i++) - { - middle_y1 = MAX(y1[i], middle_y1); - middle_y2 = MIN(y2[i], middle_y2); - } - - // If we got an empty column in our set we cannot draw 4 columns in one go: - bool empty_column_in_set = false; - for (int i = 0; i < 4; i++) - { - if (y2[i] <= y1[i]) - empty_column_in_set = true; - } - - if (empty_column_in_set || middle_y2 <= middle_y1) - { - for (int i = 0; i < 4; i++) - { - if (y2[i] <= y1[i]) - continue; - - if (!fixed) - R_SetColorMapLight(basecolormap, lights[i], wallshade); - wallscan_drawcol1(x + i, y1[i], y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column); - } - continue; - } - - // Draw the first rows where not all 4 columns are active - for (int i = 0; i < 4; i++) - { - if (!fixed) - R_SetColorMapLight(basecolormap, lights[i], wallshade); - - if (y1[i] < middle_y1) - uv_pos[i] = wallscan_drawcol1(x + i, y1[i], middle_y1, uv_pos[i], uv_step[i], uv_max, source[i], draw1column); - } - - // Draw the area where all 4 columns are active - if (!fixed) - { - for (int i = 0; i < 4; i++) - { - if (r_swtruecolor) - { - palookupoffse[i] = basecolormap->Maps; - palookuplight[i] = LIGHTSCALE(lights[i], wallshade); - } - else - { - palookupoffse[i] = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT); - palookuplight[i] = 0; - } - } - } - wallscan_drawcol4(x, middle_y1, middle_y2, uv_pos, uv_step, uv_max, source, draw4columns); - - // Draw the last rows where not all 4 columns are active - for (int i = 0; i < 4; i++) - { - if (!fixed) - R_SetColorMapLight(basecolormap, lights[i], wallshade); - - if (middle_y2 < y2[i]) - uv_pos[i] = wallscan_drawcol1(x + i, middle_y2, y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column); - } - } - - // The last unaligned columns: - for (int x = aligned_x2; x < x2; x++, light += rw_lightstep) - { - int y1 = uwal[x]; - int y2 = dwal[x]; - if (y2 <= y1) - continue; - - if (!fixed) - R_SetColorMapLight(basecolormap, light, wallshade); - - const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS); - - uint32_t uv_start, uv_step; - calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step); - - wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column); - } - - NetUpdate (); -} - -void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x)) -{ - wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) - { - setupvline(bits); - line1 = dovline1; - line4 = dovline4; - }); -} - -void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x)) -{ - if (!rw_pic->bMasked) // Textures that aren't masked can use the faster wallscan. - { - wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol); - } - else - { - wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) - { - setupmvline(bits); - line1 = domvline1; - line4 = domvline4; - }); - } -} - -void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x)) -{ - static fixed_t(*tmvline1)(); - static void(*tmvline4)(); - if (!R_GetTransMaskDrawers(&tmvline1, &tmvline4)) - { - // The current translucency is unsupported, so draw with regular maskwallscan instead. - maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol); - } - else - { - wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4) - { - setuptmvline(bits); - line1 = reinterpret_cast(tmvline1); - line4 = tmvline4; - }); - } -} - void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat) { FDynamicColormap *startcolormap = basecolormap; @@ -1444,7 +1093,7 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fi { down[j] = clamp (most3[j], up[j], dwal[j]); } - wallscan (x1, x2, up, down, swal, lwal, yrepeat); + DrawerContext::DrawWall (x1, x2, up, down, swal, lwal, yrepeat, rw_pic, rw_offset); up = down; down = (down == most1) ? most2 : most1; } @@ -1455,7 +1104,7 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fi *lit->p_lightlevel, lit->lightsource != NULL) + r_actualextralight); } - wallscan (x1, x2, up, dwal, swal, lwal, yrepeat); + DrawerContext::DrawWall (x1, x2, up, dwal, swal, lwal, yrepeat, rw_pic, rw_offset); basecolormap = startcolormap; wallshade = startshade; } @@ -1464,20 +1113,20 @@ static void call_wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, { if (mask) { - if (colfunc == basecolfunc) + if (DrawerContext::IsBaseColumn()) { - maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); + DrawerContext::DrawMaskedWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset); } else { - transmaskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); + DrawerContext::DrawTransMaskedWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset); } } else { if (fixedcolormap != NULL || fixedlightlev >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size())) { - wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); + DrawerContext::DrawWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset); } else { @@ -1513,14 +1162,14 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t if (yrepeat >= 0) { // normal orientation: draw strips from top to bottom - partition = top - fmod(top - dc_texturemid / yrepeat - ViewPos.Z, scaledtexheight); + partition = top - fmod(top - DrawerContext::TextureMid() / yrepeat - ViewPos.Z, scaledtexheight); if (partition == top) { partition -= scaledtexheight; } up = uwal; down = most1; - dc_texturemid = (partition - ViewPos.Z) * yrepeat + texheight; + DrawerContext::SetTextureMid((partition - ViewPos.Z) * yrepeat + texheight); while (partition > bot) { int j = OWallMost(most3, partition - ViewPos.Z, &WallC); @@ -1535,16 +1184,16 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t down = (down == most1) ? most2 : most1; } partition -= scaledtexheight; - dc_texturemid -= texheight; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - texheight); } call_wallscan(x1, x2, up, dwal, swal, lwal, yrepeat, mask); } else { // upside down: draw strips from bottom to top - partition = bot - fmod(bot - dc_texturemid / yrepeat - ViewPos.Z, scaledtexheight); + partition = bot - fmod(bot - DrawerContext::TextureMid() / yrepeat - ViewPos.Z, scaledtexheight); up = most1; down = dwal; - dc_texturemid = (partition - ViewPos.Z) * yrepeat + texheight; + DrawerContext::SetTextureMid((partition - ViewPos.Z) * yrepeat + texheight); while (partition < top) { int j = OWallMost(most3, partition - ViewPos.Z, &WallC); @@ -1559,7 +1208,7 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t up = (up == most1) ? most2 : most1; } partition -= scaledtexheight; - dc_texturemid -= texheight; + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - texheight); } call_wallscan(x1, x2, uwal, down, swal, lwal, yrepeat, mask); } @@ -1612,9 +1261,9 @@ void R_RenderSegLoop () fixed_t xoffset = rw_offset; if (fixedlightlev >= 0) - R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); // clip wall to the floor and ceiling for (x = x1; x < x2; ++x) @@ -1695,7 +1344,7 @@ void R_RenderSegLoop () { // one sided line if (midtexture->UseType != FTexture::TEX_Null && viewactive) { - dc_texturemid = rw_midtexturemid; + DrawerContext::SetTextureMid(rw_midtexturemid); rw_pic = midtexture; xscale = rw_pic->Scale.X * rw_midtexturescalex; yscale = rw_pic->Scale.Y * rw_midtexturescaley; @@ -1738,7 +1387,7 @@ void R_RenderSegLoop () } if (viewactive) { - dc_texturemid = rw_toptexturemid; + DrawerContext::SetTextureMid(rw_toptexturemid); rw_pic = toptexture; xscale = rw_pic->Scale.X * rw_toptexturescalex; yscale = rw_pic->Scale.Y * rw_toptexturescaley; @@ -1784,7 +1433,7 @@ void R_RenderSegLoop () } if (viewactive) { - dc_texturemid = rw_bottomtexturemid; + DrawerContext::SetTextureMid(rw_bottomtexturemid); rw_pic = bottomtexture; xscale = rw_pic->Scale.X * rw_bottomtexturescalex; yscale = rw_pic->Scale.Y * rw_bottomtexturescaley; @@ -2974,7 +2623,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, } yscale = decal->ScaleY; - dc_texturemid = WallSpriteTile->TopOffset + (zpos - ViewPos.Z) / yscale; + DrawerContext::SetTextureMid(WallSpriteTile->TopOffset + (zpos - ViewPos.Z) / yscale); // Clip sprite to drawseg x1 = MAX(clipper->x1, x1); @@ -3011,11 +2660,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep; if (fixedlightlev >= 0) - R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) - R_SetColorMapLight(usecolormap, 0, 0); + DrawerContext::SetLight(usecolormap, 0, 0); else calclighting = true; @@ -3024,7 +2673,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { sprflipvert = true; yscale = -yscale; - dc_texturemid -= WallSpriteTile->GetHeight(); + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - WallSpriteTile->GetHeight()); } else { @@ -3034,10 +2683,9 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, MaskedScaleY = float(1 / yscale); do { - dc_x = x1; ESPSResult mode; - mode = R_SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor); + mode = DrawerContext::SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor); // R_SetPatchStyle can modify basecolormap. if (rereadcolormap) @@ -3053,48 +2701,50 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { int stop4; + int x = x1; + if (mode == DoDraw0) { // 1 column at a time - stop4 = dc_x; + stop4 = x; } else // DoDraw1 { // up to 4 columns at a time stop4 = x2 & ~3; } - while ((dc_x < stop4) && (dc_x & 3)) + while ((x < stop4) && (x & 3)) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, wallshade); + DrawerContext::SetLight(usecolormap, rw_light, wallshade); } - R_WallSpriteColumn (R_DrawMaskedColumn); - dc_x++; + R_WallSpriteColumn (x, DrawerContext::DrawMaskedColumn); + x++; } - while (dc_x < stop4) + while (x < stop4) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, wallshade); + DrawerContext::SetLight(usecolormap, rw_light, wallshade); } - rt_initcols(nullptr); - for (int zz = 4; zz; --zz) + DrawerContext::RtInitCols(nullptr); + for (int zz = 0; zz < 4; ++zz) { - R_WallSpriteColumn (R_DrawMaskedColumnHoriz); - dc_x++; + R_WallSpriteColumn (x + zz, DrawerContext::DrawMaskedColumnHoriz); } - rt_draw4cols (dc_x - 4); + DrawerContext::DrawRt4cols (x); + x += 4; } - while (dc_x < x2) + while (x < x2) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, wallshade); + DrawerContext::SetLight(usecolormap, rw_light, wallshade); } - R_WallSpriteColumn (R_DrawMaskedColumn); - dc_x++; + R_WallSpriteColumn (x, DrawerContext::DrawMaskedColumn); + x++; } } @@ -3103,14 +2753,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // needrepeat will be 0, and the while will fail. mceilingclip = floorclip; mfloorclip = wallbottom; - R_FinishSetPatchStyle (); + DrawerContext::FinishSetPatchStyle (); } while (needrepeat--); - colfunc = basecolfunc; - hcolfunc_post1 = rt_map1col; - hcolfunc_post4 = rt_map4cols; - - R_FinishSetPatchStyle (); + DrawerContext::SetBaseStyle(); + DrawerContext::FinishSetPatchStyle (); done: WallC = savecoord; } diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index c4347236d..480cdd02b 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -32,6 +32,7 @@ ** */ +#define DRAWER_INTERNALS #include "r_local.h" #include "v_palette.h" diff --git a/src/r_things.cpp b/src/r_things.cpp index 836f58690..b856b968a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -58,7 +58,7 @@ #include "r_plane.h" #include "r_segs.h" #include "r_3dfloors.h" -#include "r_draw_rgba.h" +#include "r_drawer_context.h" #include "v_palette.h" #include "r_data/r_translate.h" #include "r_data/colormaps.h" @@ -229,12 +229,6 @@ vissprite_t *R_NewVisSprite (void) return *(vissprite_p-1); } -// -// R_DrawMaskedColumn -// Used for sprites and masked mid textures. -// Masked means: partly transparent, i.e. stored -// in posts/runs of opaque pixels. -// short* mfloorclip; short* mceilingclip; @@ -243,88 +237,6 @@ double sprtopscreen; bool sprflipvert; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span) -{ - int pixelsize = r_swtruecolor ? 4 : 1; - const fixed_t centeryfrac = FLOAT2FIXED(CenterY); - const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); - while (span->Length != 0) - { - const int length = span->Length; - const int top = span->TopOffset; - - // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1; - - if (sprflipvert) - { - swapvalues (dc_yl, dc_yh); - } - - if (dc_yh >= mfloorclip[dc_x]) - { - dc_yh = mfloorclip[dc_x] - 1; - } - if (dc_yl < mceilingclip[dc_x]) - { - dc_yl = mceilingclip[dc_x]; - } - - if (dc_yl <= dc_yh) - { - if (sprflipvert) - { - dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - - FixedMul (centeryfrac, dc_iscale) - texturemid; - const fixed_t maxfrac = length << FRACBITS; - while (dc_texturefrac >= maxfrac) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - while (endfrac < 0) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - else - { - dc_texturefrac = texturemid - (top << FRACBITS) - + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale); - while (dc_texturefrac < 0) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) - { - dc_yh++; - } - else while (endfrac >= maxfrac) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - dc_source = column + top; - dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg; - dc_count = dc_yh - dc_yl + 1; - colfunc (); - } -nextpost: - span++; - } -} - // [ZZ] // R_ClipSpriteColumnWithPortals // @@ -361,7 +273,7 @@ static inline void R_CollectPortals() } } -static inline bool R_ClipSpriteColumnWithPortals(vissprite_t* spr) +bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr) { // [ZZ] 10.01.2016: don't clip sprites from the root of a skybox. if (CurrentPortalInSkybox) @@ -380,7 +292,7 @@ static inline bool R_ClipSpriteColumnWithPortals(vissprite_t* spr) continue; // now if current column is covered by this drawseg, we clip it away - if ((dc_x >= seg->x1) && (dc_x < seg->x2)) + if ((x >= seg->x1) && (x < seg->x2)) return true; } @@ -409,15 +321,15 @@ void R_DrawVisSprite (vissprite_t *vis) } fixed_t centeryfrac = FLOAT2FIXED(CenterY); - R_SetColorMapLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS); + DrawerContext::SetLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS); - mode = R_SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); + mode = DrawerContext::SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded]) { // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but // it is the brightest one. We need to get back to the proper light level for // this sprite. - R_SetColorMapLight(dc_fcolormap, 0, vis->Style.ColormapNum << FRACBITS); + DrawerContext::SetLight(DrawerContext::LightColormap(), 0, vis->Style.ColormapNum << FRACBITS); } if (mode != DontDraw) @@ -436,65 +348,67 @@ void R_DrawVisSprite (vissprite_t *vis) tex = vis->pic; spryscale = vis->yscale; sprflipvert = false; - dc_iscale = FLOAT2FIXED(1 / vis->yscale); + DrawerContext::SetTextureStep(FLOAT2FIXED(1 / vis->yscale)); frac = vis->startfrac; xiscale = vis->xiscale; - dc_texturemid = vis->texturemid; + DrawerContext::SetTextureMid(vis->texturemid); if (vis->renderflags & RF_YFLIP) { sprflipvert = true; spryscale = -spryscale; - dc_iscale = -dc_iscale; - dc_texturemid -= vis->pic->GetHeight(); - sprtopscreen = CenterY + dc_texturemid * spryscale; + DrawerContext::SetTextureStep(-DrawerContext::TextureStep()); + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - vis->pic->GetHeight()); + sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale; } else { sprflipvert = false; - sprtopscreen = CenterY - dc_texturemid * spryscale; + sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale; } - dc_x = vis->x1; + int x = vis->x1; x2 = vis->x2; - if (dc_x < x2) + if (x < x2) { - while ((dc_x < stop4) && (dc_x & 3)) + DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert); + + while ((x < stop4) && (x & 3)) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); - if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); - dc_x++; + if (ispsprite || !R_ClipSpriteColumnWithPortals(x, vis)) + DrawerContext::DrawMaskedColumn (x, pixels, spans); + x++; frac += xiscale; } - while (dc_x < stop4) + while (x < stop4) { - rt_initcols(nullptr); - for (int zz = 4; zz; --zz) + DrawerContext::RtInitCols(nullptr); + for (int zz = 0; zz < 4; ++zz) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); - if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumnHoriz (pixels, spans); - dc_x++; + if (ispsprite || !R_ClipSpriteColumnWithPortals(x + zz, vis)) + DrawerContext::DrawMaskedColumnHoriz (x + zz, pixels, spans); frac += xiscale; } - rt_draw4cols (dc_x - 4); + DrawerContext::DrawRt4cols(x); + x += 4; } - while (dc_x < x2) + while (x < x2) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); - if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); - dc_x++; + if (ispsprite || !R_ClipSpriteColumnWithPortals(x, vis)) + DrawerContext::DrawMaskedColumn (x, pixels, spans); + x++; frac += xiscale; } } } - R_FinishSetPatchStyle (); + DrawerContext::FinishSetPatchStyle (); NetUpdate (); } @@ -511,7 +425,7 @@ void R_DrawWallSprite(vissprite_t *spr) WallT.InitFromWallCoords(&spr->wallc); PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); iyscale = 1 / spr->yscale; - dc_texturemid = (spr->gzt - ViewPos.Z) * iyscale; + DrawerContext::SetTextureMid((spr->gzt - ViewPos.Z) * iyscale); if (spr->renderflags & RF_XFLIP) { int right = (spr->pic->GetWidth() << FRACBITS) - 1; @@ -539,11 +453,11 @@ void R_DrawWallSprite(vissprite_t *spr) rw_lightstep = float((GlobVis / spr->wallc.sz2 - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep; if (fixedlightlev >= 0) - R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); + DrawerContext::SetLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL) - R_SetColorMapLight(fixedcolormap, 0, 0); + DrawerContext::SetLight(fixedcolormap, 0, 0); else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) - R_SetColorMapLight(usecolormap, 0, 0); + DrawerContext::SetLight(usecolormap, 0, 0); else calclighting = true; @@ -553,7 +467,7 @@ void R_DrawWallSprite(vissprite_t *spr) { sprflipvert = true; iyscale = -iyscale; - dc_texturemid -= spr->pic->GetHeight(); + DrawerContext::SetTextureMid(DrawerContext::TextureMid() - spr->pic->GetHeight()); } else { @@ -562,10 +476,9 @@ void R_DrawWallSprite(vissprite_t *spr) MaskedScaleY = (float)iyscale; - dc_x = x1; ESPSResult mode; - mode = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); + mode = DrawerContext::SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); // R_SetPatchStyle can modify basecolormap. if (rereadcolormap) @@ -581,71 +494,74 @@ void R_DrawWallSprite(vissprite_t *spr) { int stop4; + int x = x1; + if (mode == DoDraw0) { // 1 column at a time - stop4 = dc_x; + stop4 = x; } else // DoDraw1 { // up to 4 columns at a time stop4 = x2 & ~3; } - while ((dc_x < stop4) && (dc_x & 3)) + while ((x < stop4) && (x & 3)) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, shade); + DrawerContext::SetLight(usecolormap, rw_light, shade); } - if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); - dc_x++; + if (!R_ClipSpriteColumnWithPortals(x, spr)) + R_WallSpriteColumn(x, DrawerContext::DrawMaskedColumn); + x++; } - while (dc_x < stop4) + while (x < stop4) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, shade); + DrawerContext::SetLight(usecolormap, rw_light, shade); } - rt_initcols(nullptr); - for (int zz = 4; zz; --zz) + DrawerContext::RtInitCols(nullptr); + for (int zz = 0; zz < 4; ++zz) { - if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumnHoriz); - dc_x++; + if (!R_ClipSpriteColumnWithPortals(x + zz, spr)) + R_WallSpriteColumn(x + zz, DrawerContext::DrawMaskedColumnHoriz); } - rt_draw4cols(dc_x - 4); + DrawerContext::DrawRt4cols(x); + x += 4; } - while (dc_x < x2) + while (x < x2) { if (calclighting) { // calculate lighting - R_SetColorMapLight(usecolormap, rw_light, shade); + DrawerContext::SetLight(usecolormap, rw_light, shade); } - if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); - dc_x++; + if (!R_ClipSpriteColumnWithPortals(x, spr)) + R_WallSpriteColumn(x, DrawerContext::DrawMaskedColumn); + x++; } } - R_FinishSetPatchStyle(); + DrawerContext::FinishSetPatchStyle(); } -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) +void R_WallSpriteColumn (int x, void (*drawfunc)(int x, const BYTE *column, const FTexture::Span *spans)) { - float iscale = swall[dc_x] * MaskedScaleY; - dc_iscale = FLOAT2FIXED(iscale); + float iscale = swall[x] * MaskedScaleY; + DrawerContext::SetTextureStep(FLOAT2FIXED(iscale)); spryscale = 1 / iscale; if (sprflipvert) - sprtopscreen = CenterY + dc_texturemid * spryscale; + sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale; else - sprtopscreen = CenterY - dc_texturemid * spryscale; + sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale; const BYTE *column; const FTexture::Span *spans; - column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans); - dc_texturefrac = 0; - drawfunc (column, spans); + column = WallSpriteTile->GetColumn (lwall[x] >> FRACBITS, &spans); + DrawerContext::SetTextureFrac(0); + DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert); + drawfunc (x, column, spans); rw_light += rw_lightstep; } @@ -655,18 +571,18 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop int flags = 0; // Do setup for blending. - R_SetColorMapLight(spr->Style.BaseColormap, 0, spr->Style.ColormapNum << FRACBITS); - mode = R_SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); + DrawerContext::SetLight(spr->Style.BaseColormap, 0, spr->Style.ColormapNum << FRACBITS); + mode = DrawerContext::SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); if (mode == DontDraw) { return; } - if (colfunc == fuzzcolfunc || colfunc == R_FillColumn) + if (DrawerContext::IsFuzzColumn() || DrawerContext::IsFillColumn()) { flags = DVF_OFFSCREEN | DVF_SPANSONLY; } - else if (colfunc != basecolfunc) + else if (!DrawerContext::IsBaseColumn()) { flags = DVF_OFFSCREEN; } @@ -692,32 +608,32 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop { if (!(flags & DVF_SPANSONLY) && (x & 3) == 0) { - rt_initcols(OffscreenColorBuffer + x * OffscreenBufferHeight); + DrawerContext::RtInitCols(OffscreenColorBuffer + x * OffscreenBufferHeight); } for (FCoverageBuffer::Span *span = OffscreenCoverageBuffer->Spans[x]; span != NULL; span = span->NextSpan) { if (flags & DVF_SPANSONLY) { - dc_x = x; - dc_yl = span->Start; - dc_yh = span->Stop - 1; - dc_count = span->Stop - span->Start; - dc_dest = (ylookup[span->Start] + x) * pixelsize + dc_destorg; - colfunc(); + DrawerContext::SetX(x); + DrawerContext::SetY1(span->Start); + DrawerContext::SetY2(span->Stop - 1); + DrawerContext::SetDrawCount(span->Stop - span->Start); + DrawerContext::SetDest(x, span->Start); + DrawerContext::DrawColumn(); } else { - rt_span_coverage(x, span->Start, span->Stop - 1); + DrawerContext::RtSpanCoverage(x, span->Start, span->Stop - 1); } } if (!(flags & DVF_SPANSONLY) && (x & 3) == 3) { - rt_draw4cols(x - 3); + DrawerContext::DrawRt4cols(x - 3); } } } - R_FinishSetPatchStyle(); + DrawerContext::FinishSetPatchStyle(); NetUpdate(); } @@ -2585,7 +2501,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, } } -static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis) +void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis) { const int x1 = vis->x1; const int x2 = vis->x2; @@ -2610,120 +2526,24 @@ static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis) } } -void R_DrawParticle_C (vissprite_t *vis) +void R_DrawParticle(vissprite_t *vis) { - DWORD *bg2rgb; - int spacing; - BYTE *dest; - DWORD fg; BYTE color = vis->Style.BaseColormap->Maps[(vis->Style.ColormapNum << COLORMAPSHIFT) + vis->startfrac]; int yl = vis->y1; - int ycount = vis->y2 - yl + 1; - int x1 = vis->x1; - int countbase = vis->x2 - x1; - - R_DrawMaskedSegsBehindParticle (vis); - - // vis->renderflags holds translucency level (0-255) - { - fixed_t fglevel, bglevel; - DWORD *fg2rgb; - - fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff; - bglevel = FRACUNIT-fglevel; - fg2rgb = Col2RGB8[fglevel>>10]; - bg2rgb = Col2RGB8[bglevel>>10]; - fg = fg2rgb[color]; - } - - /* - - spacing = RenderTarget->GetPitch() - countbase; - dest = ylookup[yl] + x1 + dc_destorg; - - do - { - int count = countbase; - do - { - DWORD bg = bg2rgb[*dest]; - bg = (fg+bg) | 0x1f07c1f; - *dest++ = RGB32k.All[bg & (bg>>15)]; - } while (--count); - dest += spacing; - } while (--ycount);*/ - - // original was row-wise - // width = countbase - // height = ycount - - spacing = RenderTarget->GetPitch(); - - for (int x = x1; x < (x1+countbase); x++) - { - dc_x = x; - if (R_ClipSpriteColumnWithPortals(vis)) - continue; - dest = ylookup[yl] + x + dc_destorg; - for (int y = 0; y < ycount; y++) - { - DWORD bg = bg2rgb[*dest]; - bg = (fg+bg) | 0x1f07c1f; - *dest = RGB32k.All[bg & (bg>>15)]; - dest += spacing; - } - } -} - -void R_DrawParticle_rgba(vissprite_t *vis) -{ - int spacing; - uint32_t *dest; - BYTE color = vis->Style.BaseColormap->Maps[vis->startfrac]; - int yl = vis->y1; - int ycount = vis->y2 - yl + 1; + int yh = vis->y2; int x1 = vis->x1; int countbase = vis->x2 - x1; R_DrawMaskedSegsBehindParticle(vis); - - DrawerCommandQueue::WaitForWorkers(); - - uint32_t fg = shade_pal_index_simple(color, calc_light_multiplier(LIGHTSCALE(0, vis->Style.ColormapNum << FRACBITS))); - uint32_t fg_red = (fg >> 16) & 0xff; - uint32_t fg_green = (fg >> 8) & 0xff; - uint32_t fg_blue = fg & 0xff; // vis->renderflags holds translucency level (0-255) - fixed_t fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff; - uint32_t alpha = fglevel * 256 / FRACUNIT; - uint32_t inv_alpha = 256 - alpha; - - fg_red *= alpha; - fg_green *= alpha; - fg_blue *= alpha; - - spacing = RenderTarget->GetPitch(); + int alpha = vis->renderflags; for (int x = x1; x < (x1 + countbase); x++) { - dc_x = x; - if (R_ClipSpriteColumnWithPortals(vis)) + if (R_ClipSpriteColumnWithPortals(x, vis)) continue; - dest = ylookup[yl] + x + (uint32_t*)dc_destorg; - for (int y = 0; y < ycount; y++) - { - uint32_t bg_red = (*dest >> 16) & 0xff; - uint32_t bg_green = (*dest >> 8) & 0xff; - uint32_t bg_blue = (*dest) & 0xff; - - uint32_t red = (fg_red + bg_red * inv_alpha) / 256; - uint32_t green = (fg_green + bg_green * inv_alpha) / 256; - uint32_t blue = (fg_blue + bg_blue * inv_alpha) / 256; - - *dest = 0xff000000 | (red << 16) | (green << 8) | blue; - dest += spacing; - } + DrawerContext::FillTransColumn(x, yl, yh, color, alpha); } } @@ -2769,9 +2589,7 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle, sprcosang = FLOAT2FIXED(dasprang.Cos()) >> 2; sprsinang = FLOAT2FIXED(-dasprang.Sin()) >> 2; - R_SetupDrawSlab(colormap); - - int pixelsize = r_swtruecolor ? 4 : 1; + DrawerContext::SetSlabLight(colormap); // Select mip level i = abs(DMulScale6(dasprx - globalposx, cosang, daspry - globalposy, sinang)); @@ -3026,25 +2844,25 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle, if (!(flags & DVF_OFFSCREEN)) { // Draw directly to the screen. - R_DrawSlab(xxr - xxl, yplc[xxl], z2 - z1, yinc, col, (ylookup[z1] + lxt + xxl) * pixelsize + dc_destorg); + DrawerContext::DrawSlab(xxr - xxl, yplc[xxl], z2 - z1, yinc, col, lxt + xxl, z1); } else { // Record the area covered and possibly draw to an offscreen buffer. - dc_yl = z1; - dc_yh = z2 - 1; - dc_count = z2 - z1; - dc_iscale = yinc; + DrawerContext::SetY1(z1); + DrawerContext::SetY2(z2 - 1); + DrawerContext::SetDrawCount(z2 - z1); + DrawerContext::SetTextureStep(yinc); for (int x = xxl; x < xxr; ++x) { OffscreenCoverageBuffer->InsertSpan(lxt + x, z1, z2); if (!(flags & DVF_SPANSONLY)) { - dc_x = lxt + x; - rt_initcols(OffscreenColorBuffer + (dc_x & ~3) * OffscreenBufferHeight); - dc_source = col; - dc_texturefrac = yplc[xxl]; - hcolfunc_pre(); + DrawerContext::RtInitCols(OffscreenColorBuffer + ((lxt + x) & ~3) * OffscreenBufferHeight); + DrawerContext::SetX(lxt + x); + DrawerContext::SetSource(col); + DrawerContext::SetTextureFrac(yplc[xxl]); + DrawerContext::DrawHColumnPre(); } } } diff --git a/src/r_things.h b/src/r_things.h index f5cd30e00..869de4da2 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -96,11 +96,8 @@ struct vissprite_t struct particle_t; -extern void(*R_DrawParticle)(vissprite_t *); -void R_DrawParticle_C (vissprite_t *); -void R_DrawParticle_rgba (vissprite_t *); - void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside); +void R_DrawParticle (vissprite_t *vis); extern int MaxVisSprites; @@ -112,7 +109,6 @@ extern vissprite_t **vissprite_p; extern short zeroarray[MAXWIDTH]; extern short screenheightarray[MAXWIDTH]; -// vars for R_DrawMaskedColumn extern short* mfloorclip; extern short* mceilingclip; extern double spryscale; @@ -126,8 +122,7 @@ extern double pspriteyscale; extern FTexture *WallSpriteTile; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); +void R_WallSpriteColumn (int x, void (*drawfunc)(int x, const BYTE *column, const FTexture::Span *spans)); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 6a8dad047..21cbd1a33 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -43,8 +43,7 @@ #include "r_defs.h" #include "r_utility.h" #ifndef NO_SWRENDER -#include "r_draw.h" -#include "r_draw_rgba.h" +#include "r_drawer_context.h" #include "r_main.h" #include "r_things.h" #endif @@ -130,12 +129,14 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH]; const BYTE *translation = NULL; - if (r_swtruecolor != IsBgra()) + DCanvas *destorgsave = DrawerContext::Canvas(); + if (screen->GetBuffer() == NULL) { - r_swtruecolor = IsBgra(); - R_InitColumnDrawers(); + I_FatalError("Attempt to write to buffer of hardware canvas"); } + DrawerContext::SetCanvas(screen); + if (parms.masked) { spanptr = &spans; @@ -172,22 +173,15 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) if (translation != NULL) { - R_SetTranslationMap((lighttable_t *)translation); + DrawerContext::SetTranslationMap((lighttable_t *)translation); } else { - R_SetTranslationMap(identitymap); + DrawerContext::SetTranslationMap(nullptr); } - fixedcolormap = dc_fcolormap; - ESPSResult mode = R_SetPatchStyle (parms.style, parms.Alpha, 0, parms.fillcolor); - - BYTE *destorgsave = dc_destorg; - dc_destorg = screen->GetBuffer(); - if (dc_destorg == NULL) - { - I_FatalError("Attempt to write to buffer of hardware canvas"); - } + fixedcolormap = DrawerContext::LightColormap(); + ESPSResult mode = DrawerContext::SetPatchStyle (parms.style, parms.Alpha, 0, parms.fillcolor); double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth; double y0 = parms.y - parms.top * parms.destheight / parms.texheight; @@ -220,11 +214,11 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) assert(spryscale > 0); sprflipvert = false; - //dc_iscale = FLOAT2FIXED(iyscale); - //dc_texturemid = (-y0) * iyscale; - //dc_iscale = 0xffffffffu / (unsigned)spryscale; - dc_iscale = FLOAT2FIXED(1 / spryscale); - dc_texturemid = (CenterY - 1 - sprtopscreen) * dc_iscale / 65536; + //DrawerContext::SetTextureStep(FLOAT2FIXED(iyscale)); + //DrawerContext::SetTextureMid((-y0) * iyscale); + //DrawerContext::SetTextureStep(0xffffffffu / (unsigned)spryscale); + DrawerContext::SetTextureStep(FLOAT2FIXED(1 / spryscale)); + DrawerContext::SetTextureMid((CenterY - 1 - sprtopscreen) * DrawerContext::TextureStep() / 65536); fixed_t frac = 0; double xiscale = img->GetWidth() / parms.destwidth; double x2 = x0 + parms.destwidth; @@ -278,14 +272,14 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) mode = DoDraw0; } - dc_x = int(x0); + int x = int(x0); int x2_i = int(x2); fixed_t xiscale_i = FLOAT2FIXED(xiscale); if (mode == DoDraw0) { // One column at a time - stop4 = dc_x; + stop4 = x; } else // DoDraw1` { @@ -293,42 +287,44 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) stop4 = x2_i & ~3; } - if (dc_x < x2_i) + if (x < x2_i) { - while ((dc_x < stop4) && (dc_x & 3)) + DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert); + + while ((x < stop4) && (x & 3)) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); - dc_x++; + DrawerContext::DrawMaskedColumn(x, pixels, spans); + x++; frac += xiscale_i; } - while (dc_x < stop4) + while (x < stop4) { - rt_initcols(nullptr); - for (int zz = 4; zz; --zz) + DrawerContext::RtInitCols(nullptr); + for (int zz = 0; zz < 4; ++zz) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumnHoriz(pixels, spans); - dc_x++; + DrawerContext::DrawMaskedColumnHoriz(x + zz, pixels, spans); frac += xiscale_i; } - rt_draw4cols(dc_x - 4); + DrawerContext::DrawRt4cols(x); + x += 4; } - while (dc_x < x2_i) + while (x < x2_i) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); - dc_x++; + DrawerContext::DrawMaskedColumn(x, pixels, spans); + x++; frac += xiscale_i; } } CenterY = centeryback; } - R_FinishSetPatchStyle (); + DrawerContext::FinishSetPatchStyle (); - dc_destorg = destorgsave; + DrawerContext::SetCanvas(destorgsave); if (ticdup != 0 && menuactive == MENU_Off) { @@ -1024,9 +1020,11 @@ void DCanvas::PUTTRANSDOT (int xx, int yy, int basecolor, int level) if (IsBgra()) { + int inv_level = 64 - level; + uint32_t *spot = (uint32_t*)GetBuffer() + oldyyshifted + xx; - uint32_t fg = shade_pal_index_simple(basecolor, calc_light_multiplier(0)); + uint32_t fg = GPalette.BaseColors[basecolor].d; uint32_t fg_red = (fg >> 16) & 0xff; uint32_t fg_green = (fg >> 8) & 0xff; uint32_t fg_blue = fg & 0xff; @@ -1035,9 +1033,9 @@ void DCanvas::PUTTRANSDOT (int xx, int yy, int basecolor, int level) uint32_t bg_green = (*spot >> 8) & 0xff; uint32_t bg_blue = (*spot) & 0xff; - uint32_t red = (fg_red + bg_red + 1) / 2; - uint32_t green = (fg_green + bg_green + 1) / 2; - uint32_t blue = (fg_blue + bg_blue + 1) / 2; + uint32_t red = (fg_red * level + bg_red * inv_level + 1) / 64; + uint32_t green = (fg_green * level + bg_green * inv_level + 1) / 64; + uint32_t blue = (fg_blue * level + bg_blue * inv_level + 1) / 64; *spot = 0xff000000 | (red << 16) | (green << 8) | blue; } @@ -1399,16 +1397,15 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, sinrot = sin(rotation.Radians()); // Setup constant texture mapping parameters. - R_SetupSpanBits(tex); if (colormap) - R_SetSpanColormap(colormap, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1)); + DrawerContext::SetSpanLight(colormap, 0, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1)); else - R_SetSpanColormap(&identitycolormap, 0); - R_SetSpanSource(r_swtruecolor ? (const BYTE*)tex->GetPixelsBgra() : tex->GetPixels()); - scalex = double(1u << (32 - ds_xbits)) / scalex; - scaley = double(1u << (32 - ds_ybits)) / scaley; - ds_xstep = xs_RoundToInt(cosrot * scalex); - ds_ystep = xs_RoundToInt(sinrot * scaley); + DrawerContext::SetSpanLight(nullptr, 0, 0); + DrawerContext::SetSpanSource(tex); + scalex = double(1u << (32 - DrawerContext::SpanXBits())) / scalex; + scaley = double(1u << (32 - DrawerContext::SpanYBits())) / scaley; + DrawerContext::SetSpanXStep(xs_RoundToInt(cosrot * scalex)); + DrawerContext::SetSpanYStep(xs_RoundToInt(sinrot * scaley)); // Travel down the right edge and create an outline of that edge. pt1 = toppt; @@ -1472,9 +1469,9 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, #if 0 memset(this->Buffer + y * this->Pitch + x1, (int)tex, x2 - x1); #else - ds_y = y; - ds_x1 = x1; - ds_x2 = x2 - 1; + DrawerContext::SetSpanY(y); + DrawerContext::SetSpanX1(x1); + DrawerContext::SetSpanX2(x2 - 1); DVector2 tex(x1 - originx, y - originy); if (dorotate) @@ -1483,10 +1480,10 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, tex.X = t * cosrot - tex.Y * sinrot; tex.Y = tex.Y * cosrot + t * sinrot; } - ds_xfrac = xs_RoundToInt(tex.X * scalex); - ds_yfrac = xs_RoundToInt(tex.Y * scaley); + DrawerContext::SetSpanXFrac(xs_RoundToInt(tex.X * scalex)); + DrawerContext::SetSpanYFrac(xs_RoundToInt(tex.Y * scaley)); - R_DrawSpan(); + DrawerContext::DrawSimplePolySpan(); #endif } x += xinc;