Software multithread

This commit is contained in:
Jaime Ita Passos 2021-11-06 01:38:25 -03:00
parent 06dfd360ee
commit 3a9987e390
49 changed files with 3969 additions and 8332 deletions

View file

@ -8,8 +8,6 @@ target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in)
set(SRB2_ASM_SOURCES vid_copy.s) set(SRB2_ASM_SOURCES vid_copy.s)
set(SRB2_NASM_SOURCES tmap_mmx.nas tmap.nas)
### Configuration ### Configuration
set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL
"Enable PNG support. Depends on zlib, so will be disabled if you don't enable that too.") "Enable PNG support. Depends on zlib, so will be disabled if you don't enable that too.")
@ -213,8 +211,7 @@ if(${SRB2_CONFIG_USEASM})
target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM) target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse")
target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES} target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES})
${SRB2_NASM_SOURCES})
else() else()
set(SRB2_USEASM OFF) set(SRB2_USEASM OFF)
target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM) target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM)

View file

@ -210,7 +210,7 @@ sources+=\
$(call List,blua/Sourcefile)\ $(call List,blua/Sourcefile)\
depends:=$(basename $(filter %.c %.s,$(sources))) depends:=$(basename $(filter %.c %.s,$(sources)))
objects:=$(basename $(filter %.c %.s %.nas,$(sources))) objects:=$(basename $(filter %.c %.s,$(sources)))
depends:=$(depends:%=$(depdir)/%.d) depends:=$(depends:%=$(depdir)/%.d)

View file

@ -20,7 +20,6 @@ endif
ifndef NOASM ifndef NOASM
ifndef NONX86 ifndef NONX86
sources+=tmap.nas tmap_mmx.nas
opts+=-DUSEASM opts+=-DUSEASM
endif endif
endif endif

View file

@ -511,8 +511,10 @@ static void D_Display(void)
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
} }
} }
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime;
// Image postprocessing effect // Image postprocessing effect
ps_postprocesstime = I_GetPreciseTime();
if (rendermode == render_soft) if (rendermode == render_soft)
{ {
if (!splitscreen) if (!splitscreen)
@ -523,7 +525,7 @@ static void D_Display(void)
if (postimgtype2) if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(1, postimgtype2, postimgparam2);
} }
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime; ps_postprocesstime = I_GetPreciseTime() - ps_postprocesstime;
} }
if (lastdraw) if (lastdraw)

View file

@ -537,6 +537,9 @@ INT32 I_GetKey(void);
// Max gamepad/joysticks that can be detected/used. // Max gamepad/joysticks that can be detected/used.
#define MAX_JOYSTICKS 4 #define MAX_JOYSTICKS 4
// Software multithreading
#define MAX_RENDER_THREADS 8
#ifndef M_PIl #ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L #define M_PIl 3.1415926535897932384626433832795029L
#endif #endif
@ -608,13 +611,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls.
//#define PAPER_COLLISIONCORRECTION //#define PAPER_COLLISIONCORRECTION
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
/// on the bright side it fixes some weird issues with translucent walls
/// \note SRB2CB port.
/// SRB2CB itself ported this from PrBoom+
#define NEWCLIP
/// OpenGL shaders /// OpenGL shaders
#define GL_SHADERS #define GL_SHADERS

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,6 @@ void HWR_ClearSkyDome(void);
void HWR_BuildSkyDome(void); void HWR_BuildSkyDome(void);
void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void); void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);

View file

@ -15,6 +15,17 @@
#define I_THREADS_H #define I_THREADS_H
typedef void (*I_thread_fn)(void *userdata); typedef void (*I_thread_fn)(void *userdata);
typedef void * I_thread_handle;
#ifdef HAVE_SDL
#include <SDL.h>
#define ATOMIC_TYPE SDL_atomic_t
#else
#define ATOMIC_TYPE UINT32
#endif
typedef ATOMIC_TYPE I_Atomicval_t;
typedef I_Atomicval_t * I_Atomicptr_t;
typedef void * I_mutex; typedef void * I_mutex;
typedef void * I_cond; typedef void * I_cond;
@ -22,7 +33,7 @@ typedef void * I_cond;
void I_start_threads (void); void I_start_threads (void);
void I_stop_threads (void); void I_stop_threads (void);
void I_spawn_thread (const char *name, I_thread_fn, void *userdata); I_thread_handle I_spawn_thread (const char *name, I_thread_fn, void *userdata);
/* check in your thread whether to return early */ /* check in your thread whether to return early */
int I_thread_is_stopped (void); int I_thread_is_stopped (void);
@ -35,5 +46,8 @@ void I_hold_cond (I_cond *, I_mutex);
void I_wake_one_cond (I_cond *); void I_wake_one_cond (I_cond *);
void I_wake_all_cond (I_cond *); void I_wake_all_cond (I_cond *);
INT32 I_atomic_load (I_Atomicptr_t atomic);
INT32 I_atomic_exchange (I_Atomicptr_t atomic, INT32 val);
#endif/*I_THREADS_H*/ #endif/*I_THREADS_H*/
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/

View file

@ -100,7 +100,30 @@ enum {
PERF_COUNT, PERF_COUNT,
}; };
static void M_DrawPerfString(perfstatcol_t *col, int type) static void M_DrawPerfString(const char *string, INT32 lores_x, INT32 hires_x, INT32 flags)
{
const boolean hires = M_HighResolution();
INT32 draw_flags = V_MONOSPACE | flags;
if (hires)
draw_flags |= V_ALLOWLOWERCASE;
if (hires)
{
V_DrawFillConsoleMap(hires_x, draw_row, V_SmallStringWidth(string, draw_flags), 5, 0);
V_DrawSmallString(hires_x, draw_row, draw_flags, string);
draw_row += 5;
}
else
{
V_DrawFillConsoleMap(lores_x, draw_row, V_ThinStringWidth(string, draw_flags), 8, 0);
V_DrawThinString(lores_x, draw_row, draw_flags, string);
draw_row += 8;
}
}
static void M_DrawPerfMeasurement(perfstatcol_t *col, int type)
{ {
const boolean hires = M_HighResolution(); const boolean hires = M_HighResolution();
@ -122,15 +145,19 @@ static void M_DrawPerfString(perfstatcol_t *col, int type)
if (hires) if (hires)
{ {
V_DrawSmallString(col->hires_x, draw_row, draw_flags, const char *string = va("%s %d", row->hires_label, value);
va("%s %d", row->hires_label, value));
V_DrawFillConsoleMap(col->hires_x, draw_row, V_SmallStringWidth(string, draw_flags), 5, 0);
V_DrawSmallString(col->hires_x, draw_row, draw_flags, string);
draw_row += 5; draw_row += 5;
} }
else else
{ {
V_DrawThinString(col->lores_x, draw_row, draw_flags, const char *string = va("%s %d", row->lores_label, value);
va("%s %d", row->lores_label, value));
V_DrawFillConsoleMap(col->lores_x, draw_row, V_SmallStringWidth(string, draw_flags), 8, 0);
V_DrawThinString(col->lores_x, draw_row, draw_flags, string);
draw_row += 8; draw_row += 8;
} }
@ -139,12 +166,12 @@ static void M_DrawPerfString(perfstatcol_t *col, int type)
static void M_DrawPerfTiming(perfstatcol_t *col) static void M_DrawPerfTiming(perfstatcol_t *col)
{ {
M_DrawPerfString(col, PERF_TIME); M_DrawPerfMeasurement(col, PERF_TIME);
} }
static void M_DrawPerfCount(perfstatcol_t *col) static void M_DrawPerfCount(perfstatcol_t *col)
{ {
M_DrawPerfString(col, PERF_COUNT); M_DrawPerfMeasurement(col, PERF_COUNT);
} }
static void M_DrawRenderStats(void) static void M_DrawRenderStats(void)
@ -161,7 +188,7 @@ static void M_DrawRenderStats(void)
}; };
perfstatrow_t rendercalltime_row[] = { perfstatrow_t rendercalltime_row[] = {
{"drwtime", "3d rendering: ", &ps_rendercalltime}, {"drwtime", "3D rendering: ", &ps_rendercalltime},
{0} {0}
}; };
@ -176,16 +203,6 @@ static void M_DrawRenderStats(void)
{0} {0}
}; };
perfstatrow_t softwaretime_row[] = {
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
{"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime},
{"portals", "Portals+Skybox:", &ps_sw_portaltime},
{"planes ", "R_DrawPlanes: ", &ps_sw_planetime},
{"masked ", "R_DrawMasked: ", &ps_sw_maskedtime},
{"other ", "Other: ", &extrarendertime},
{0}
};
perfstatrow_t uiswaptime_row[] = { perfstatrow_t uiswaptime_row[] = {
{"ui ", "UI render: ", &ps_uitime}, {"ui ", "UI render: ", &ps_uitime},
{"finupdt", "I_FinishUpdate:", &ps_swaptime}, {"finupdt", "I_FinishUpdate:", &ps_swaptime},
@ -197,14 +214,6 @@ static void M_DrawRenderStats(void)
{0} {0}
}; };
perfstatrow_t rendercalls_row[] = {
{"bspcall", "BSP calls: ", &ps_numbspcalls},
{"sprites", "Sprites: ", &ps_numsprites},
{"drwnode", "Drawnodes: ", &ps_numdrawnodes},
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects},
{0}
};
perfstatrow_t batchtime_row[] = { perfstatrow_t batchtime_row[] = {
{"batsort", "Batch sort: ", &ps_hw_batchsorttime}, {"batsort", "Batch sort: ", &ps_hw_batchsorttime},
{"batdraw", "Batch render:", &ps_hw_batchdrawtime}, {"batdraw", "Batch render:", &ps_hw_batchdrawtime},
@ -230,13 +239,10 @@ static void M_DrawRenderStats(void)
perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row}; perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row};
perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row}; perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row};
perfstatcol_t softwaretime_col = {24, 24, V_YELLOWMAP, softwaretime_row};
perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row}; perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row};
perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row}; perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row};
perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row};
perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row}; perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row};
perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row}; perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row};
@ -256,12 +262,13 @@ static void M_DrawRenderStats(void)
M_DrawPerfTiming(&rendercalltime_col); M_DrawPerfTiming(&rendercalltime_col);
// Remember to update this calculation when adding more 3d rendering stats! // Remember to update this calculation when adding more 3d rendering stats!
extrarendertime = ps_rendercalltime - ps_bsptime; extrarendertime = ps_rendercalltime;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode == render_opengl) if (rendermode == render_opengl)
{ {
extrarendertime -= extrarendertime =
ps_bsptime[0] +
ps_hw_skyboxtime + ps_hw_skyboxtime +
ps_hw_nodesorttime + ps_hw_nodesorttime +
ps_hw_nodedrawtime + ps_hw_nodedrawtime +
@ -280,14 +287,33 @@ static void M_DrawRenderStats(void)
else else
#endif #endif
{ {
extrarendertime -= INT32 i = 0;
ps_sw_spritecliptime +
ps_sw_portaltime +
ps_sw_planetime +
ps_sw_maskedtime;
perfstatrow_t other_row[] = {
{"postprc", "Postprocessing:", &ps_postprocesstime},
{0}
};
perfstatcol_t other_col = {24, 24, V_YELLOWMAP, other_row};
for (i = 0; i < numusablerendercontexts; i++) {
perfstatrow_t softwaretime_row[] = {
{"bsptime", "RenderBSPNode: ", &ps_bsptime[i]},
{"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime[i]},
{"portals", "Portals+Skybox:", &ps_sw_portaltime[i]},
{"planes ", "R_DrawPlanes: ", &ps_sw_planetime[i]},
{"masked ", "R_DrawMasked: ", &ps_sw_maskedtime[i]},
{0}
};
perfstatcol_t softwaretime_col = {28, 28, V_YELLOWMAP, softwaretime_row};
M_DrawPerfString(va("Thread %d:", i+1), 24, 24, V_REDMAP);
M_DrawPerfTiming(&softwaretime_col); M_DrawPerfTiming(&softwaretime_col);
} }
M_DrawPerfTiming(&other_col);
}
} }
M_DrawPerfTiming(&uiswaptime_col); M_DrawPerfTiming(&uiswaptime_col);
@ -298,7 +324,40 @@ static void M_DrawRenderStats(void)
if (rendering) if (rendering)
{ {
draw_row = 10; draw_row = 10;
#ifdef HWRENDER
if (rendermode == render_opengl) {
perfstatrow_t rendercalls_row[] = {
{"bspcall", "BSP calls: ", &ps_numbspcalls},
{"sprites", "Sprites: ", &ps_numsprites},
{"drwnode", "Drawnodes: ", &ps_numdrawnodes},
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects},
{0}
};
perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row};
M_DrawPerfCount(&rendercalls_col); M_DrawPerfCount(&rendercalls_col);
} else
#endif
{
INT32 i;
for (i = 0; i < numusablerendercontexts; i++) {
perfstatrow_t rendercalls_row[] = {
{"bspcall", "BSP calls: ", &ps_numbspcalls[i]},
{"sprites", "Sprites: ", &ps_numsprites[i]},
{"drwnode", "Drawnodes: ", &ps_numdrawnodes[i]},
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects[i]},
{0}
};
perfstatcol_t rendercalls_col = {94, 120, V_BLUEMAP, rendercalls_row};
M_DrawPerfString(va("Thread %d:", i+1), 90, 115, V_REDMAP);
M_DrawPerfCount(&rendercalls_col);
}
}
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode == render_opengl && cv_glbatching.value) if (rendermode == render_opengl && cv_glbatching.value)

View file

@ -23,50 +23,37 @@
#include "z_zone.h" // Check R_Prep3DFloors #include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h" #include "taglist.h"
seg_t *curline; #ifdef HAVE_THREADS
side_t *sidedef; static I_mutex R_BSP_mutex;
line_t *linedef; # define Lock_state() I_lock_mutex(&R_BSP_mutex)
sector_t *frontsector; # define Unlock_state() I_unlock_mutex(R_BSP_mutex)
sector_t *backsector; #else
# define Lock_state()
// very ugly realloc() of drawsegs at run-time, I upped it to 512 # define Unlock_state()
// instead of 256.. and someone managed to send me a level with #endif
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
drawseg_t *drawsegs = NULL;
drawseg_t *ds_p = NULL;
// indicates doors closed wrt automap bugfix:
INT32 doorclosed;
// //
// R_ClearDrawSegs // R_ClearDrawSegs
// //
void R_ClearDrawSegs(void) void R_ClearDrawSegs(bspcontext_t *context)
{ {
ds_p = drawsegs; context->ds_p = context->drawsegs;
} }
// Fix from boom.
#define MAXSEGS (MAXVIDWIDTH/2+1)
// newend is one past the last valid seg
static cliprange_t *newend;
static cliprange_t solidsegs[MAXSEGS];
// //
// R_ClipSolidWallSegment // R_ClipSolidWallSegment
// Does handle solid walls, // Does handle solid walls,
// e.g. single sided LineDefs (middle texture) // e.g. single sided LineDefs (middle texture)
// that entirely block the view. // that entirely block the view.
// //
static void R_ClipSolidWallSegment(INT32 first, INT32 last) static void R_ClipSolidWallSegment(rendercontext_t *context, wallcontext_t *wallcontext, INT32 first, INT32 last)
{ {
bspcontext_t *bspcontext = &context->bspcontext;
cliprange_t *next; cliprange_t *next;
cliprange_t *start; cliprange_t *start;
// Find the first range that touches the range (adjacent pixels are touching). // Find the first range that touches the range (adjacent pixels are touching).
start = solidsegs; start = bspcontext->solidsegs;
while (start->last < first - 1) while (start->last < first - 1)
start++; start++;
@ -75,11 +62,11 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
if (last < start->first - 1) if (last < start->first - 1)
{ {
// Post is entirely visible (above start), so insert a new clippost. // Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange(first, last); R_StoreWallRange(context, wallcontext, first, last);
next = newend; next = bspcontext->newend;
newend++; bspcontext->newend++;
// NO MORE CRASHING! // NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS) if (bspcontext->newend - bspcontext->solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
while (next != start) while (next != start)
@ -93,7 +80,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
} }
// There is a fragment above *start. // There is a fragment above *start.
R_StoreWallRange(first, start->first - 1); R_StoreWallRange(context, wallcontext, first, start->first - 1);
// Now adjust the clip size. // Now adjust the clip size.
start->first = first; start->first = first;
} }
@ -106,7 +93,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
while (last >= (next+1)->first - 1) while (last >= (next+1)->first - 1)
{ {
// There is a fragment between two posts. // There is a fragment between two posts.
R_StoreWallRange(next->last + 1, (next+1)->first - 1); R_StoreWallRange(context, wallcontext, next->last + 1, (next+1)->first - 1);
next++; next++;
if (last <= next->last) if (last <= next->last)
@ -119,7 +106,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
} }
// There is a fragment after *next. // There is a fragment after *next.
R_StoreWallRange(next->last + 1, last); R_StoreWallRange(context, wallcontext, next->last + 1, last);
// Adjust the clip size. // Adjust the clip size.
start->last = last; start->last = last;
@ -128,13 +115,13 @@ crunch:
if (next == start) if (next == start)
return; // Post just extended past the bottom of one post. return; // Post just extended past the bottom of one post.
while (next++ != newend) while (next++ != bspcontext->newend)
*++start = *next; // Remove a post. *++start = *next; // Remove a post.
newend = start + 1; bspcontext->newend = start + 1;
// NO MORE CRASHING! // NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS) if (bspcontext->newend - bspcontext->solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
} }
@ -143,13 +130,13 @@ crunch:
// Clips the given range of columns, but does not include it in the clip list. // Clips the given range of columns, but does not include it in the clip list.
// Does handle windows, e.g. LineDefs with upper and lower texture. // Does handle windows, e.g. LineDefs with upper and lower texture.
// //
static inline void R_ClipPassWallSegment(INT32 first, INT32 last) static inline void R_ClipPassWallSegment(rendercontext_t *context, wallcontext_t *wallcontext, INT32 first, INT32 last)
{ {
cliprange_t *start; cliprange_t *start;
// Find the first range that touches the range // Find the first range that touches the range
// (adjacent pixels are touching). // (adjacent pixels are touching).
start = solidsegs; start = context->bspcontext.solidsegs;
while (start->last < first - 1) while (start->last < first - 1)
start++; start++;
@ -158,12 +145,12 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
if (last < start->first - 1) if (last < start->first - 1)
{ {
// Post is entirely visible (above start). // Post is entirely visible (above start).
R_StoreWallRange(first, last); R_StoreWallRange(context, wallcontext, first, last);
return; return;
} }
// There is a fragment above *start. // There is a fragment above *start.
R_StoreWallRange(first, start->first - 1); R_StoreWallRange(context, wallcontext, first, start->first - 1);
} }
// Bottom contained in start? // Bottom contained in start?
@ -173,7 +160,7 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
while (last >= (start+1)->first - 1) while (last >= (start+1)->first - 1)
{ {
// There is a fragment between two posts. // There is a fragment between two posts.
R_StoreWallRange(start->last + 1, (start+1)->first - 1); R_StoreWallRange(context, wallcontext, start->last + 1, (start+1)->first - 1);
start++; start++;
if (last <= start->last) if (last <= start->last)
@ -181,27 +168,19 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
} }
// There is a fragment after *next. // There is a fragment after *next.
R_StoreWallRange(start->last + 1, last); R_StoreWallRange(context, wallcontext, start->last + 1, last);
} }
// //
// R_ClearClipSegs // R_ClearClipSegs
// //
void R_ClearClipSegs(void) void R_ClearClipSegs(bspcontext_t *context, INT32 start, INT32 end)
{ {
solidsegs[0].first = -0x7fffffff; context->solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = -1; context->solidsegs[0].last = start-1;
solidsegs[1].first = viewwidth; context->solidsegs[1].first = end;
solidsegs[1].last = 0x7fffffff; context->solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2; context->newend = context->solidsegs + 2;
}
void R_PortalClearClipSegs(INT32 start, INT32 end)
{
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = start-1;
solidsegs[1].first = end;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
} }
@ -212,17 +191,17 @@ void R_PortalClearClipSegs(INT32 start, INT32 end)
// //
// It assumes that Doom has already ruled out a door being closed because // It assumes that Doom has already ruled out a door being closed because
// of front-back closure (e.g. front floor is taller than back ceiling). // of front-back closure (e.g. front floor is taller than back ceiling).
static INT32 R_DoorClosed(void) static INT32 R_DoorClosed(bspcontext_t *bspcontext)
{ {
return return
// if door is closed because back is shut: // if door is closed because back is shut:
backsector->ceilingheight <= backsector->floorheight bspcontext->backsector->ceilingheight <= bspcontext->backsector->floorheight
// preserve a kind of transparent door/lift special effect: // preserve a kind of transparent door/lift special effect:
&& (backsector->ceilingheight >= frontsector->ceilingheight || curline->sidedef->toptexture) && (bspcontext->backsector->ceilingheight >= bspcontext->frontsector->ceilingheight || bspcontext->curline->sidedef->toptexture)
&& (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); && (bspcontext->backsector->floorheight <= bspcontext->frontsector->floorheight || bspcontext->curline->sidedef->bottomtexture);
} }
// //
@ -233,8 +212,8 @@ static INT32 R_DoorClosed(void)
// //
// Similar for ceiling, only reflected. // Similar for ceiling, only reflected.
// //
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sector_t *R_FakeFlat(viewcontext_t *viewcontext, sector_t *sec, sector_t *tempsec,
INT32 *ceilinglightlevel, boolean back) INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back)
{ {
if (floorlightlevel) if (floorlightlevel)
*floorlightlevel = sec->floorlightsec == -1 ? *floorlightlevel = sec->floorlightsec == -1 ?
@ -250,19 +229,19 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
if (!sec->extra_colormap && sec->heightsec != -1) if (!sec->extra_colormap && sec->heightsec != -1)
{ {
const sector_t *s = &sectors[sec->heightsec]; const sector_t *s = &sectors[sec->heightsec];
mobj_t *viewmobj = viewplayer->mo; mobj_t *viewmobj = viewcontext->player->mo;
INT32 heightsec; INT32 heightsec;
boolean underwater; boolean underwater;
if (splitscreen && viewplayer == &players[secondarydisplayplayer] && camera2.chase) if (splitscreen && viewcontext->player == &players[secondarydisplayplayer] && camera2.chase)
heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec; heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec;
else if (camera.chase && viewplayer == &players[displayplayer]) else if (camera.chase && viewcontext->player == &players[displayplayer])
heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec; heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec;
else if (viewmobj) else if (viewmobj)
heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec; heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec;
else else
return sec; return sec;
underwater = heightsec != -1 && viewz <= sectors[heightsec].floorheight; underwater = heightsec != -1 && viewcontext->z <= sectors[heightsec].floorheight;
// Replace sector being drawn, with a copy to be hacked // Replace sector being drawn, with a copy to be hacked
*tempsec = *sec; *tempsec = *sec;
@ -272,7 +251,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->ceilingheight = s->ceilingheight; tempsec->ceilingheight = s->ceilingheight;
if ((underwater && (tempsec-> floorheight = sec->floorheight, if ((underwater && (tempsec-> floorheight = sec->floorheight,
tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) tempsec->ceilingheight = s->floorheight - 1, !back)) || viewcontext->z <= s->floorheight)
{ // head-below-floor hack { // head-below-floor hack
tempsec->floorpic = s->floorpic; tempsec->floorpic = s->floorpic;
tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_xoffs = s->floor_xoffs;
@ -308,7 +287,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
*ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel
: sectors[s->ceilinglightsec].lightlevel; : sectors[s->ceilinglightsec].lightlevel;
} }
else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight else if (heightsec != -1 && viewcontext->z >= sectors[heightsec].ceilingheight
&& sec->ceilingheight > s->ceilingheight) && sec->ceilingheight > s->ceilingheight)
{ // Above-ceiling hack { // Above-ceiling hack
tempsec->ceilingheight = s->ceilingheight; tempsec->ceilingheight = s->ceilingheight;
@ -382,22 +361,25 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// R_AddLine // R_AddLine
// Clips the given segment and adds any visible pieces to the line list. // Clips the given segment and adds any visible pieces to the line list.
// //
static void R_AddLine(seg_t *line) static void R_AddLine(rendercontext_t *rendercontext, seg_t *line)
{ {
INT32 x1, x2; INT32 x1, x2;
angle_t angle1, angle2, span, tspan; angle_t angle1, angle2, span, tspan;
static sector_t tempsec;
boolean bothceilingssky = false, bothfloorssky = false; boolean bothceilingssky = false, bothfloorssky = false;
portalline = false; bspcontext_t *bspcontext = &rendercontext->bspcontext;
viewcontext_t *viewcontext = &rendercontext->viewcontext;
wallcontext_t wallcontext;
bspcontext->portalline = false;
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return; return;
// big room fix // big room fix
angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y); angle1 = R_PointToAngleEx(viewcontext->x, viewcontext->y, line->v1->x, line->v1->y);
angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y); angle2 = R_PointToAngleEx(viewcontext->x, viewcontext->y, line->v2->x, line->v2->y);
curline = line; bspcontext->curline = line;
// Clip to view edges. // Clip to view edges.
span = angle1 - angle2; span = angle1 - angle2;
@ -407,9 +389,9 @@ static void R_AddLine(seg_t *line)
return; return;
// Global angle needed by segcalc. // Global angle needed by segcalc.
rw_angle1 = angle1; wallcontext.angle1 = angle1;
angle1 -= viewangle; angle1 -= viewcontext->angle;
angle2 -= viewangle; angle2 -= viewcontext->angle;
tspan = angle1 + clipangle; tspan = angle1 + clipangle;
if (tspan > doubleclipangle) if (tspan > doubleclipangle)
@ -440,18 +422,21 @@ static void R_AddLine(seg_t *line)
x1 = viewangletox[angle1]; x1 = viewangletox[angle1];
x2 = viewangletox[angle2]; x2 = viewangletox[angle2];
x1 = max(rendercontext->begincolumn, x1);
x2 = min(rendercontext->endcolumn, x2);
// Does not cross a pixel? // Does not cross a pixel?
if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
return; return;
backsector = line->backsector; bspcontext->backsector = line->backsector;
// Portal line // Portal line
if (line->linedef->special == 40 && line->side == 0) if (line->linedef->special == 40 && line->side == 0)
{ {
// Render portal if recursiveness limit hasn't been reached. // Render portal if recursiveness limit hasn't been reached.
// Otherwise, render the wall normally. // Otherwise, render the wall normally.
if (portalrender < cv_maxportals.value) if (bspcontext->portalrender < cv_maxportals.value)
{ {
size_t p; size_t p;
mtag_t tag = Tag_FGet(&line->linedef->tags); mtag_t tag = Tag_FGet(&line->linedef->tags);
@ -464,38 +449,40 @@ static void R_AddLine(seg_t *line)
if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2)) if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
continue; continue;
Portal_Add2Lines(li1, li2, x1, x2); Portal_Add2Lines(rendercontext, li1, li2, x1, x2);
goto clipsolid; goto clipsolid;
} }
} }
} }
// Single sided line? // Single sided line?
if (!backsector) if (!bspcontext->backsector)
goto clipsolid; goto clipsolid;
backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); bspcontext->backsector = R_FakeFlat(viewcontext, bspcontext->backsector, &bspcontext->btempsec, NULL, NULL, true);
doorclosed = 0; // indicates doors closed wrt automap bugfix:
bspcontext->doorclosed = 0;
if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum) if (bspcontext->backsector->ceilingpic == skyflatnum && bspcontext->frontsector->ceilingpic == skyflatnum)
bothceilingssky = true; bothceilingssky = true;
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum) if (bspcontext->backsector->floorpic == skyflatnum && bspcontext->frontsector->floorpic == skyflatnum)
bothfloorssky = true; bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
{ {
if (!line->polyseg && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors) && ((!bspcontext->frontsector->ffloors && !bspcontext->backsector->ffloors)
|| Tag_Compare(&frontsector->tags, &backsector->tags))) || Tag_Compare(&bspcontext->frontsector->tags, &bspcontext->backsector->tags)))
return; // line is empty, don't even bother return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead goto clippass; // treat like wide open window instead
} }
// Closed door. // Closed door.
if (frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope) if (bspcontext->frontsector->f_slope || bspcontext->frontsector->c_slope
|| bspcontext->backsector->f_slope || bspcontext->backsector->c_slope)
{ {
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
@ -503,10 +490,10 @@ static void R_AddLine(seg_t *line)
end1 = P_GetZAt(slope, line->v1->x, line->v1->y, normalheight); \ end1 = P_GetZAt(slope, line->v1->x, line->v1->y, normalheight); \
end2 = P_GetZAt(slope, line->v2->x, line->v2->y, normalheight); end2 = P_GetZAt(slope, line->v2->x, line->v2->y, normalheight);
SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector-> floorheight) SLOPEPARAMS(bspcontext->frontsector->f_slope, frontf1, frontf2, bspcontext->frontsector-> floorheight)
SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight) SLOPEPARAMS(bspcontext->frontsector->c_slope, frontc1, frontc2, bspcontext->frontsector->ceilingheight)
SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector-> floorheight) SLOPEPARAMS( bspcontext->backsector->f_slope, backf1, backf2, bspcontext->backsector-> floorheight)
SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight) SLOPEPARAMS( bspcontext->backsector->c_slope, backc1, backc2, bspcontext->backsector->ceilingheight)
#undef SLOPEPARAMS #undef SLOPEPARAMS
// if both ceilings are skies, consider it always "open" // if both ceilings are skies, consider it always "open"
// same for floors // same for floors
@ -519,11 +506,11 @@ static void R_AddLine(seg_t *line)
} }
// Check for automap fix. Store in doorclosed for r_segs.c // Check for automap fix. Store in doorclosed for r_segs.c
doorclosed = (backc1 <= backf1 && backc2 <= backf2 bspcontext->doorclosed = (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture) && ((backc1 >= frontc1 && backc2 >= frontc2) || bspcontext->curline->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)); && ((backf1 <= frontf1 && backf2 >= frontf2) || bspcontext->curline->sidedef->bottomtexture));
if (doorclosed) if (bspcontext->doorclosed)
goto clipsolid; goto clipsolid;
} }
@ -541,40 +528,39 @@ static void R_AddLine(seg_t *line)
// same for floors // same for floors
if (!bothceilingssky && !bothfloorssky) if (!bothceilingssky && !bothfloorssky)
{ {
if (backsector->ceilingheight <= frontsector->floorheight if (bspcontext->backsector->ceilingheight <= bspcontext->frontsector->floorheight
|| backsector->floorheight >= frontsector->ceilingheight) || bspcontext->backsector->floorheight >= bspcontext->frontsector->ceilingheight)
{ {
goto clipsolid; goto clipsolid;
} }
// Check for automap fix. Store in doorclosed for r_segs.c // Check for automap fix. Store in doorclosed for r_segs.c
doorclosed = R_DoorClosed(); bspcontext->doorclosed = R_DoorClosed(bspcontext);
if (doorclosed) if (bspcontext->doorclosed)
goto clipsolid; goto clipsolid;
} }
// Window. // Window.
if (!bothceilingssky) // ceilings are always the "same" when sky if (!bothceilingssky) // ceilings are always the "same" when sky
if (backsector->ceilingheight != frontsector->ceilingheight) if (bspcontext->backsector->ceilingheight != bspcontext->frontsector->ceilingheight)
goto clippass; goto clippass;
if (!bothfloorssky) // floors are always the "same" when sky if (!bothfloorssky) // floors are always the "same" when sky
if (backsector->floorheight != frontsector->floorheight) if (bspcontext->backsector->floorheight != bspcontext->frontsector->floorheight)
goto clippass; goto clippass;
} }
// Reject empty lines used for triggers and special events. // Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides, identical light levels on both sides, // Identical floor and ceiling on both sides, identical light levels on both sides,
// and no middle texture. // and no middle texture.
if (R_IsEmptyLine(line, bspcontext->frontsector, bspcontext->backsector))
if (R_IsEmptyLine(line, frontsector, backsector))
return; return;
clippass: clippass:
R_ClipPassWallSegment(x1, x2 - 1); R_ClipPassWallSegment(rendercontext, &wallcontext, x1, x2 - 1);
return; return;
clipsolid: clipsolid:
R_ClipSolidWallSegment(x1, x2 - 1); R_ClipSolidWallSegment(rendercontext, &wallcontext, x1, x2 - 1);
} }
// //
@ -602,22 +588,24 @@ INT32 checkcoord[12][4] =
{2, 1, 3, 0} {2, 1, 3, 0}
}; };
static boolean R_CheckBBox(const fixed_t *bspcoord) static boolean R_CheckBBox(rendercontext_t *context, const fixed_t *bspcoord)
{ {
angle_t angle1, angle2; angle_t angle1, angle2;
INT32 sx1, sx2, boxpos; INT32 sx1, sx2, boxpos;
const INT32* check; const INT32* check;
cliprange_t *start; cliprange_t *start;
viewcontext_t *viewcontext = &context->viewcontext;
// Find the corners of the box that define the edges from current viewpoint. // Find the corners of the box that define the edges from current viewpoint.
if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5) if ((boxpos = (viewcontext->x <= bspcoord[BOXLEFT] ? 0 : viewcontext->x < bspcoord[BOXRIGHT] ? 1 : 2)
+ (viewcontext->y >= bspcoord[BOXTOP] ? 0 : viewcontext->y > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
return true; return true;
check = checkcoord[boxpos]; check = checkcoord[boxpos];
// big room fix // big room fix
angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle; angle1 = R_PointToAngleEx(viewcontext->x, viewcontext->y, bspcoord[check[0]], bspcoord[check[1]]) - viewcontext->angle;
angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle; angle2 = R_PointToAngleEx(viewcontext->x, viewcontext->y, bspcoord[check[2]], bspcoord[check[3]]) - viewcontext->angle;
if ((signed)angle1 < (signed)angle2) if ((signed)angle1 < (signed)angle2)
{ {
@ -641,7 +629,7 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
// Does not cross a pixel. // Does not cross a pixel.
if (sx1 >= sx2) return false; if (sx1 >= sx2) return false;
start = solidsegs; start = context->bspcontext.solidsegs;
while (start->last < sx2) while (start->last < sx2)
start++; start++;
@ -789,7 +777,7 @@ static int R_PolysegCompare(const void *p1, const void *p2)
// haleyjd 02/19/06 // haleyjd 02/19/06
// Adds all segs in all polyobjects in the given subsector. // Adds all segs in all polyobjects in the given subsector.
// //
static void R_AddPolyObjects(subsector_t *sub) static void R_AddPolyObjects(rendercontext_t *context, subsector_t *sub)
{ {
polyobj_t *po = sub->polyList; polyobj_t *po = sub->polyList;
size_t i, j; size_t i, j;
@ -804,7 +792,7 @@ static void R_AddPolyObjects(subsector_t *sub)
} }
// for render stats // for render stats
ps_numpolyobjects += numpolys; ps_numpolyobjects[context->num] += numpolys;
// sort polyobjects // sort polyobjects
R_SortPolyObjects(sub); R_SortPolyObjects(sub);
@ -814,7 +802,7 @@ static void R_AddPolyObjects(subsector_t *sub)
{ {
qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare); qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
for (j = 0; j < po_ptrs[i]->segCount; ++j) for (j = 0; j < po_ptrs[i]->segCount; ++j)
R_AddLine(po_ptrs[i]->segs[j]); R_AddLine(context, po_ptrs[i]->segs[j]);
} }
} }
@ -825,17 +813,19 @@ static void R_AddPolyObjects(subsector_t *sub)
// Draw one or more line segments. // Draw one or more line segments.
// //
drawseg_t *firstseg; static void R_Subsector(rendercontext_t *context, size_t num)
static void R_Subsector(size_t num)
{ {
INT32 count, floorlightlevel, ceilinglightlevel, light; INT32 count, floorlightlevel, ceilinglightlevel, light;
seg_t *line; seg_t *line;
subsector_t *sub; subsector_t *sub;
static sector_t tempsec; // Deep water hack
extracolormap_t *floorcolormap; extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap; extracolormap_t *ceilingcolormap;
fixed_t floorcenterz, ceilingcenterz; fixed_t floorcenterz, ceilingcenterz;
sector_t *frontsector;
bspcontext_t *bspcontext = &context->bspcontext;
planecontext_t *planecontext = &context->planecontext;
viewcontext_t *viewcontext = &context->viewcontext;
#ifdef RANGECHECK #ifdef RANGECHECK
if (num >= numsubsectors) if (num >= numsubsectors)
@ -847,12 +837,11 @@ static void R_Subsector(size_t num)
return; return;
sub = &subsectors[num]; sub = &subsectors[num];
frontsector = sub->sector;
count = sub->numlines; count = sub->numlines;
line = &segs[sub->firstline]; line = &segs[sub->firstline];
// Deep water/fake ceiling effect. // Deep water/fake ceiling effect.
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); frontsector = R_FakeFlat(viewcontext, sub->sector, &bspcontext->ftempsec, &floorlightlevel, &ceilinglightlevel, false);
floorcolormap = ceilingcolormap = frontsector->extra_colormap; floorcolormap = ceilingcolormap = frontsector->extra_colormap;
@ -866,9 +855,12 @@ static void R_Subsector(size_t num)
{ {
frontsector->numlights = sub->sector->numlights = 0; frontsector->numlights = sub->sector->numlights = 0;
R_Prep3DFloors(frontsector); R_Prep3DFloors(frontsector);
Lock_state();
sub->sector->lightlist = frontsector->lightlist; sub->sector->lightlist = frontsector->lightlist;
sub->sector->numlights = frontsector->numlights; sub->sector->numlights = frontsector->numlights;
sub->sector->moved = frontsector->moved = false; sub->sector->moved = frontsector->moved = false;
Unlock_state();
} }
light = R_GetPlaneLight(frontsector, floorcenterz, false); light = R_GetPlaneLight(frontsector, floorcenterz, false);
@ -883,106 +875,109 @@ static void R_Subsector(size_t num)
sub->sector->extra_colormap = frontsector->extra_colormap; sub->sector->extra_colormap = frontsector->extra_colormap;
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz if (P_GetSectorFloorZAt(frontsector, viewcontext->x, viewcontext->y) < viewcontext->z
|| frontsector->floorpic == skyflatnum || frontsector->floorpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum)) || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
{ {
floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, planecontext->floorplane = R_FindPlane(planecontext, viewcontext, frontsector->floorheight, frontsector->floorpic, floorlightlevel,
frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope); frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope);
} }
else else
floorplane = NULL; planecontext->floorplane = NULL;
if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz if (P_GetSectorCeilingZAt(frontsector, viewcontext->x, viewcontext->y) > viewcontext->z
|| frontsector->ceilingpic == skyflatnum || frontsector->ceilingpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
{ {
ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, planecontext->ceilingplane = R_FindPlane(planecontext, viewcontext, frontsector->ceilingheight, frontsector->ceilingpic,
ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
ceilingcolormap, NULL, NULL, frontsector->c_slope); ceilingcolormap, NULL, NULL, frontsector->c_slope);
} }
else else
ceilingplane = NULL; planecontext->ceilingplane = NULL;
planecontext->numffloors = 0;
planecontext->ffloor[0].slope = NULL;
planecontext->ffloor[0].plane = NULL;
planecontext->ffloor[0].polyobj = NULL;
numffloors = 0;
ffloor[numffloors].slope = NULL;
ffloor[numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL;
if (frontsector->ffloors) if (frontsector->ffloors)
{ {
ffloor_t *rover; ffloor_t *rover;
fixed_t heightcheck, planecenterz; fixed_t heightcheck, planecenterz;
for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next) for (rover = frontsector->ffloors; rover && planecontext->numffloors < MAXFFLOORS; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
continue; continue;
if (frontsector->cullheight) if (frontsector->cullheight)
{ {
if (R_DoCulling(frontsector->cullheight, viewsector->cullheight, viewz, *rover->bottomheight, *rover->topheight)) if (R_DoCulling(frontsector->cullheight, viewcontext->sector->cullheight, viewcontext->z, *rover->bottomheight, *rover->topheight))
{ {
rover->norender = leveltime; rover->norender = leveltime;
continue; continue;
} }
} }
ffloor[numffloors].plane = NULL; planecontext->ffloor[planecontext->numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL; planecontext->ffloor[planecontext->numffloors].polyobj = NULL;
heightcheck = P_GetFFloorBottomZAt(rover, viewx, viewy); heightcheck = P_GetFFloorBottomZAt(rover, viewcontext->x, viewcontext->y);
planecenterz = P_GetFFloorBottomZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y); planecenterz = P_GetFFloorBottomZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y);
if (planecenterz <= ceilingcenterz if (planecenterz <= ceilingcenterz
&& planecenterz >= floorcenterz && planecenterz >= floorcenterz
&& ((viewz < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) && ((viewcontext->z < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) || (viewcontext->z > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
{ {
light = R_GetPlaneLight(frontsector, planecenterz, light = R_GetPlaneLight(frontsector, planecenterz,
viewz < heightcheck); viewcontext->z < heightcheck);
ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, planecontext->ffloor[planecontext->numffloors].plane = R_FindPlane(planecontext, viewcontext,
*rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
*rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope); *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope);
ffloor[numffloors].slope = *rover->b_slope; planecontext->ffloor[planecontext->numffloors].slope = *rover->b_slope;
// Tell the renderer this sector has slopes in it. // Tell the renderer this sector has slopes in it.
if (ffloor[numffloors].slope) if (planecontext->ffloor[planecontext->numffloors].slope)
frontsector->hasslope = true; frontsector->hasslope = true;
ffloor[numffloors].height = heightcheck; planecontext->ffloor[planecontext->numffloors].height = heightcheck;
ffloor[numffloors].ffloor = rover; planecontext->ffloor[planecontext->numffloors].ffloor = rover;
numffloors++; planecontext->numffloors++;
} }
if (numffloors >= MAXFFLOORS) if (planecontext->numffloors >= MAXFFLOORS)
break; break;
ffloor[numffloors].plane = NULL; planecontext->ffloor[planecontext->numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL; planecontext->ffloor[planecontext->numffloors].polyobj = NULL;
heightcheck = P_GetFFloorTopZAt(rover, viewx, viewy); heightcheck = P_GetFFloorTopZAt(rover, viewcontext->x, viewcontext->y);
planecenterz = P_GetFFloorTopZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y); planecenterz = P_GetFFloorTopZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y);
if (planecenterz >= floorcenterz if (planecenterz >= floorcenterz
&& planecenterz <= ceilingcenterz && planecenterz <= ceilingcenterz
&& ((viewz > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) && ((viewcontext->z > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) || (viewcontext->z < heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
{ {
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); light = R_GetPlaneLight(frontsector, planecenterz, viewcontext->z < heightcheck);
ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, planecontext->ffloor[planecontext->numffloors].plane = R_FindPlane(planecontext, viewcontext,
*rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope); *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope);
ffloor[numffloors].slope = *rover->t_slope; planecontext->ffloor[planecontext->numffloors].slope = *rover->t_slope;
// Tell the renderer this sector has slopes in it. // Tell the renderer this sector has slopes in it.
if (ffloor[numffloors].slope) if (planecontext->ffloor[planecontext->numffloors].slope)
frontsector->hasslope = true; frontsector->hasslope = true;
ffloor[numffloors].height = heightcheck; planecontext->ffloor[planecontext->numffloors].height = heightcheck;
ffloor[numffloors].ffloor = rover; planecontext->ffloor[planecontext->numffloors].ffloor = rover;
numffloors++; planecontext->numffloors++;
} }
} }
} }
@ -995,7 +990,7 @@ static void R_Subsector(size_t num)
while (po) while (po)
{ {
if (numffloors >= MAXFFLOORS) if (planecontext->numffloors >= MAXFFLOORS)
break; break;
if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes
@ -1005,54 +1000,58 @@ static void R_Subsector(size_t num)
} }
polysec = po->lines[0]->backsector; polysec = po->lines[0]->backsector;
ffloor[numffloors].plane = NULL; planecontext->ffloor[planecontext->numffloors].plane = NULL;
if (polysec->floorheight <= ceilingcenterz if (polysec->floorheight <= ceilingcenterz
&& polysec->floorheight >= floorcenterz && polysec->floorheight >= floorcenterz
&& (viewz < polysec->floorheight)) && (viewcontext->z < polysec->floorheight))
{ {
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); light = R_GetPlaneLight(frontsector, polysec->floorheight, viewcontext->z < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, planecontext->ffloor[planecontext->numffloors].plane = R_FindPlane(planecontext, viewcontext,
polysec->floorheight, polysec->floorpic,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs,
polysec->floorpic_angle-po->angle, polysec->floorpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually? NULL); // will ffloors be slopable eventually?
ffloor[numffloors].height = polysec->floorheight; planecontext->ffloor[planecontext->numffloors].height = polysec->floorheight;
ffloor[numffloors].polyobj = po; planecontext->ffloor[planecontext->numffloors].polyobj = po;
ffloor[numffloors].slope = NULL; planecontext->ffloor[planecontext->numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover; //planecontext->ffloor[planecontext->numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane; po->visplane = planecontext->ffloor[planecontext->numffloors].plane;
numffloors++; planecontext->numffloors++;
} }
if (numffloors >= MAXFFLOORS) if (planecontext->numffloors >= MAXFFLOORS)
break; break;
ffloor[numffloors].plane = NULL; planecontext->ffloor[planecontext->numffloors].plane = NULL;
if (polysec->ceilingheight >= floorcenterz if (polysec->ceilingheight >= floorcenterz
&& polysec->ceilingheight <= ceilingcenterz && polysec->ceilingheight <= ceilingcenterz
&& (viewz > polysec->ceilingheight)) && (viewcontext->z > polysec->ceilingheight))
{ {
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); light = R_GetPlaneLight(frontsector, polysec->floorheight, viewcontext->z < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, planecontext->ffloor[planecontext->numffloors].plane = R_FindPlane(planecontext, viewcontext,
polysec->ceilingheight, polysec->ceilingpic,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually? NULL); // will ffloors be slopable eventually?
ffloor[numffloors].polyobj = po; planecontext->ffloor[planecontext->numffloors].polyobj = po;
ffloor[numffloors].height = polysec->ceilingheight; planecontext->ffloor[planecontext->numffloors].height = polysec->ceilingheight;
ffloor[numffloors].slope = NULL; planecontext->ffloor[planecontext->numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover; //planecontext->ffloor[planecontext->numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane; po->visplane = planecontext->ffloor[planecontext->numffloors].plane;
numffloors++; planecontext->numffloors++;
} }
po = (polyobj_t *)(po->link.next); po = (polyobj_t *)(po->link.next);
} }
} }
bspcontext->frontsector = frontsector;
// killough 9/18/98: Fix underwater slowdown, by passing real sector // killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite // instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area. // lightlevels on floor & ceiling lightlevels in the surrounding area.
@ -1065,21 +1064,20 @@ static void R_Subsector(size_t num)
// Either you must pass the fake sector and handle validcount here, on the // Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way, // real sector, or you must account for the lighting in some other way,
// like passing it as an argument. // like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2); R_AddSprites(context, sub->sector, (floorlightlevel+ceilinglightlevel)/2);
firstseg = NULL; bspcontext->firstseg = NULL;
// haleyjd 02/19/06: draw polyobjects before static lines // haleyjd 02/19/06: draw polyobjects before static lines
if (sub->polyList) if (sub->polyList)
R_AddPolyObjects(sub); R_AddPolyObjects(context, sub);
while (count--) while (count--)
{ {
// CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime);
if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
R_AddLine(line); R_AddLine(context, line);
line++; line++;
curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */ bspcontext->curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */
} }
} }
@ -1234,37 +1232,37 @@ INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside)
// //
// killough 5/2/98: reformatted, removed tail recursion // killough 5/2/98: reformatted, removed tail recursion
void R_RenderBSPNode(INT32 bspnum) void R_RenderBSPNode(rendercontext_t *context, INT32 bspnum)
{ {
node_t *bsp; node_t *bsp;
INT32 side; INT32 side;
ps_numbspcalls++; ps_numbspcalls[context->num]++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{ {
bsp = &nodes[bspnum]; bsp = &nodes[bspnum];
// Decide which side the view point is on. // Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp); side = R_PointOnSide(context->viewcontext.x, context->viewcontext.y, bsp);
// Recursively divide front space. // Recursively divide front space.
R_RenderBSPNode(bsp->children[side]); R_RenderBSPNode(context, bsp->children[side]);
// Possibly divide back space. // Possibly divide back space.
if (!R_CheckBBox(context, bsp->bbox[side^1]))
if (!R_CheckBBox(bsp->bbox[side^1]))
return; return;
bspnum = bsp->children[side^1]; bspnum = bsp->children[side^1];
} }
// PORTAL CULLING // PORTAL CULLING
if (portalcullsector) { if (context->bspcontext.portalcullsector) {
sector_t *sect = subsectors[bspnum & ~NF_SUBSECTOR].sector; sector_t *sect = subsectors[bspnum & ~NF_SUBSECTOR].sector;
if (sect != portalcullsector) if (sect != context->bspcontext.portalcullsector)
return; return;
portalcullsector = NULL; context->bspcontext.portalcullsector = NULL;
} }
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); R_Subsector(context, bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
} }

View file

@ -18,27 +18,16 @@
#pragma interface #pragma interface
#endif #endif
extern seg_t *curline;
extern side_t *sidedef;
extern line_t *linedef;
extern sector_t *frontsector;
extern sector_t *backsector;
extern boolean portalline; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c
extern INT32 checkcoord[12][4]; extern INT32 checkcoord[12][4];
extern drawseg_t *curdrawsegs; struct bspcontext_s;
extern drawseg_t *drawsegs; struct rendercontext_s;
extern drawseg_t *ds_p; struct viewcontext_s;
extern INT32 doorclosed;
// BSP? // BSP?
void R_ClearClipSegs(void); void R_ClearClipSegs(struct bspcontext_s *context, INT32 start, INT32 end);
void R_PortalClearClipSegs(INT32 start, INT32 end); void R_ClearDrawSegs(struct bspcontext_s *context);
void R_ClearDrawSegs(void); void R_RenderBSPNode(struct rendercontext_s *context, INT32 bspnum);
void R_RenderBSPNode(INT32 bspnum);
void R_SortPolyObjects(subsector_t *sub); void R_SortPolyObjects(subsector_t *sub);
@ -46,8 +35,8 @@ extern size_t numpolys; // number of polyobjects in current subsector
extern size_t num_po_ptrs; // number of polyobject pointers allocated extern size_t num_po_ptrs; // number of polyobject pointers allocated
extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sector_t *R_FakeFlat(struct viewcontext_s *viewcontext, sector_t *sec, sector_t *tempsec,
INT32 *ceilinglightlevel, boolean back); INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back);
boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back); boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside); INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);

187
src/r_context.h Normal file
View file

@ -0,0 +1,187 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2020 by Ethan Watson.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_context.h
/// \brief Render context
#ifndef __R_CONTEXT__
#define __R_CONTEXT__
#include "r_defs.h"
#include "r_bsp.h"
#include "r_plane.h"
#include "r_splats.h"
#include "r_things.h"
//
// Render context is required for threaded rendering.
// So everything "global" goes in here. Everything.
//
typedef struct viewcontext_s
{
fixed_t x, y, z;
angle_t angle, aimingangle;
fixed_t cos, sin;
sector_t *sector;
player_t *player;
mobj_t *mobj;
} viewcontext_t;
typedef struct bspcontext_s
{
seg_t *curline;
side_t *sidedef;
line_t *linedef;
sector_t *frontsector;
sector_t *backsector;
// very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
drawseg_t *curdrawsegs; /**< This is used to handle multiple lists for masked drawsegs. */
drawseg_t *drawsegs;
drawseg_t *ds_p;
drawseg_t *firstseg;
size_t maxdrawsegs;
// newend is one past the last valid seg
cliprange_t *newend;
cliprange_t solidsegs[MAXSEGS];
sector_t ftempsec;
sector_t btempsec;
UINT8 doorclosed;
// Linked list for portals.
struct portal_s *portal_base, *portal_cap;
// When rendering a portal, it establishes the depth of the current BSP traversal.
UINT8 portalrender;
boolean portalline;
line_t *portalclipline;
sector_t *portalcullsector;
INT32 portalclipstart, portalclipend;
} bspcontext_t;
typedef struct planecontext_s
{
//SoM: 3/23/2000: Use Boom visplane hashing.
visplane_t *visplanes[MAXVISPLANES];
visplane_t *freetail;
visplane_t **freehead;
visplane_t *floorplane;
visplane_t *ceilingplane;
visplane_t *currentplane;
planemgr_t ffloor[MAXFFLOORS];
INT32 numffloors;
//SoM: 3/23/2000: Use boom opening limit removal
size_t maxopenings;
INT16 *openings, *lastopening; /// \todo free leak
//
// Clip values are the solid pixel bounding the range.
// floorclip starts out SCREENHEIGHT
// ceilingclip starts out -1
//
INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
fixed_t frontscale[MAXVIDWIDTH];
//
// spanstart holds the start of a plane span
// initialized to 0 at start
//
INT32 spanstart[MAXVIDHEIGHT];
//
// texture mapping
//
lighttable_t **zlight;
fixed_t planeheight;
fixed_t cachedheight[MAXVIDHEIGHT];
fixed_t cacheddistance[MAXVIDHEIGHT];
fixed_t cachedxstep[MAXVIDHEIGHT];
fixed_t cachedystep[MAXVIDHEIGHT];
fixed_t xoffs, yoffs;
struct
{
INT32 offset;
fixed_t xfrac, yfrac;
boolean active;
} ripple;
struct rastery_s *prastertab;
struct rastery_s rastertab[MAXVIDHEIGHT];
} planecontext_t;
typedef struct spritecontext_s
{
UINT32 visspritecount;
UINT32 clippedvissprites;
vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS];
vissprite_t overflowsprite;
lighttable_t **spritelights;
boolean *sectorvisited;
drawnode_t nodebankhead;
vissprite_t vsprsortedhead;
} spritecontext_t;
typedef struct wallcontext_s
{
angle_t normalangle;
// angle to line origin
angle_t angle1;
fixed_t distance;
//
// regular wall
//
angle_t centerangle;
fixed_t offset;
fixed_t offset2; // for splats
fixed_t scale, scalestep;
fixed_t midtexturemid, toptexturemid, bottomtexturemid;
fixed_t toptextureslide, midtextureslide, bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
fixed_t midtextureback, midtexturebackslide; // Values for masked midtexture height calculation
INT32 *silhouette;
fixed_t *tsilheight;
fixed_t *bsilheight;
} wallcontext_t;
typedef struct rendercontext_s
{
// Setup
vbuffer_t buffer;
INT32 num;
INT32 begincolumn;
INT32 endcolumn;
viewcontext_t viewcontext;
bspcontext_t bspcontext;
planecontext_t planecontext;
spritecontext_t spritecontext;
colcontext_t colcontext;
spancontext_t spancontext;
} rendercontext_t;
#endif

View file

@ -1240,8 +1240,8 @@ void R_PrecacheLevel(void)
return; return;
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap() // do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()
if (rendermode != render_soft) // if (rendermode != render_soft)
return; // return;
// Precache flats. // Precache flats.
flatmemory = P_PrecacheLevelFlats(); flatmemory = P_PrecacheLevelFlats();

View file

@ -22,7 +22,7 @@
// SECTORS do store MObjs anyway. // SECTORS do store MObjs anyway.
#include "p_mobj.h" #include "p_mobj.h"
#include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT #include "screen.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "m_aatree.h" #include "m_aatree.h"
@ -41,6 +41,9 @@ typedef struct
INT32 last; INT32 last;
} cliprange_t; } cliprange_t;
// Fix from boom.
#define MAXSEGS (MAXVIDWIDTH/2+1)
// Silhouette, needed for clipping segs (mainly) and sprites representing things. // Silhouette, needed for clipping segs (mainly) and sprites representing things.
#define SIL_NONE 0 #define SIL_NONE 0
#define SIL_BOTTOM 1 #define SIL_BOTTOM 1
@ -56,6 +59,15 @@ typedef UINT8 lighttable_t;
#define CMF_FADEFULLBRIGHTSPRITES 1 #define CMF_FADEFULLBRIGHTSPRITES 1
#define CMF_FOG 4 #define CMF_FOG 4
typedef struct vbuffer_s
{
UINT8 *screens[5];
} vbuffer_t;
typedef struct {
float x, y, z;
} floatv3_t;
// ExtraColormap type. Use for extra_colormaps from now on. // ExtraColormap type. Use for extra_colormaps from now on.
typedef struct extracolormap_s typedef struct extracolormap_s
{ {

View file

@ -62,14 +62,6 @@ UINT8 *topleft;
// COLUMN DRAWING CODE STUFF // COLUMN DRAWING CODE STUFF
// ========================================================================= // =========================================================================
lighttable_t *dc_colormap;
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
fixed_t dc_iscale, dc_texturemid;
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
// soo lets make it a byte on all system for the ASM code
UINT8 *dc_source;
// ----------------------- // -----------------------
// translucency stuff here // translucency stuff here
// ----------------------- // -----------------------
@ -78,48 +70,11 @@ UINT8 *dc_source;
UINT8 *transtables; // translucency tables UINT8 *transtables; // translucency tables
UINT8 *blendtables[NUMBLENDMAPS]; UINT8 *blendtables[NUMBLENDMAPS];
/** \brief R_DrawTransColumn uses this
*/
UINT8 *dc_transmap; // one of the translucency tables
// ----------------------
// translation stuff here
// ----------------------
/** \brief R_DrawTranslatedColumn uses this
*/
UINT8 *dc_translation;
struct r_lightlist_s *dc_lightlist = NULL;
INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
// ========================================================================= // =========================================================================
// SPAN DRAWING CODE STUFF // SPAN DRAWING CODE STUFF
// ========================================================================= // =========================================================================
INT32 ds_y, ds_x1, ds_x2; float focallengthf;
lighttable_t *ds_colormap;
lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
INT32 ds_waterofs, ds_bgofs;
UINT16 ds_flatwidth, ds_flatheight;
boolean ds_powersoftwo;
UINT8 *ds_source; // points to the start of a flat
UINT8 *ds_transmap; // one of the translucency tables
// Vectors for Software's tilted slope drawers
floatv3_t *ds_su, *ds_sv, *ds_sz;
floatv3_t *ds_sup, *ds_svp, *ds_szp;
float focallengthf, zeroheight;
/** \brief Variable flat sizes
*/
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
// ========================================================================= // =========================================================================
// TRANSLATION COLORMAP CODE // TRANSLATION COLORMAP CODE
@ -572,6 +527,15 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
dest_colormap[starttranscolor + i] = (UINT8)skincolors[color].ramp[i]; dest_colormap[starttranscolor + i] = (UINT8)skincolors[color].ramp[i];
} }
#ifdef HAVE_THREADS
static I_mutex r_colormap_mutex;
# define Lock_state() I_lock_mutex(&r_colormap_mutex)
# define Unlock_state() I_unlock_mutex(r_colormap_mutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
/** \brief Retrieves a translation colormap from the cache. /** \brief Retrieves a translation colormap from the cache.
@ -589,13 +553,16 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
if (flags & GTC_CACHE) if (flags & GTC_CACHE)
{ {
Lock_state();
// Allocate table for skin if necessary // Allocate table for skin if necessary
if (!translationtablecache[skintableindex]) if (!translationtablecache[skintableindex])
translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL);
Unlock_state();
// Get colormap // Get colormap
ret = translationtablecache[skintableindex][color]; ret = translationtablecache[skintableindex][color];
Lock_state();
// Rebuild the cache if necessary // Rebuild the cache if necessary
if (skincolor_modified[color]) if (skincolor_modified[color])
{ {
@ -605,18 +572,21 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
skincolor_modified[color] = false; skincolor_modified[color] = false;
} }
Unlock_state();
} }
else ret = NULL; else ret = NULL;
// Generate the colormap if necessary // Generate the colormap if necessary
if (!ret) if (!ret)
{ {
Lock_state();
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8);
R_GenerateTranslationColormap(ret, skinnum, color); R_GenerateTranslationColormap(ret, skinnum, color);
// Cache the colormap if desired // Cache the colormap if desired
if (flags & GTC_CACHE) if (flags & GTC_CACHE)
translationtablecache[skintableindex][color] = ret; translationtablecache[skintableindex][color] = ret;
Unlock_state();
} }
return ret; return ret;
@ -887,13 +857,37 @@ void R_DrawViewBorder(void)
// INCLUDE 8bpp DRAWING CODE HERE // INCLUDE 8bpp DRAWING CODE HERE
// ========================================================================== // ==========================================================================
// R_CalcTiltedLighting
// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
static void R_CalcTiltedLighting(spancontext_t *ds, fixed_t start, fixed_t end)
{
// ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version
// of this function. Here's my own.
INT32 left = ds->x1, right = ds->x2;
fixed_t step = (end-start)/(ds->x2-ds->x1+1);
INT32 i;
// I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once,
// but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now...
for (i = left; i <= right; i++) {
ds->tiltlighting[i] = (start += step) >> FRACBITS;
if (ds->tiltlighting[i] < 0)
ds->tiltlighting[i] = 0;
else if (ds->tiltlighting[i] >= MAXLIGHTSCALE)
ds->tiltlighting[i] = MAXLIGHTSCALE-1;
}
}
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan))
// Lighting is simple. It's just linear interpolation from start to end
#define CALC_TILTED_LIGHTING { \
float planelightfloat = PLANELIGHTFLOAT; \
float lightend = (iz + ds->szp->x*width) * planelightfloat; \
float lightstart = iz * planelightfloat; \
R_CalcTiltedLighting(ds, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); \
}
#include "r_draw8.c" #include "r_draw8.c"
#include "r_draw8_npo2.c" #include "r_draw8_npo2.c"
// ==========================================================================
// INCLUDE 16bpp DRAWING CODE HERE
// ==========================================================================
#ifdef HIGHCOLOR
#include "r_draw16.c"
#endif

View file

@ -25,61 +25,7 @@ extern UINT8 *ylookup2[MAXVIDHEIGHT*4];
extern INT32 columnofs[MAXVIDWIDTH*4]; extern INT32 columnofs[MAXVIDWIDTH*4];
extern UINT8 *topleft; extern UINT8 *topleft;
// ------------------------- extern float focallengthf;
// COLUMN DRAWING CODE STUFF
// -------------------------
extern lighttable_t *dc_colormap;
extern INT32 dc_x, dc_yl, dc_yh;
extern fixed_t dc_iscale, dc_texturemid;
extern UINT8 dc_hires;
extern UINT8 *dc_source; // first pixel in a column
// translucency stuff here
extern UINT8 *dc_transmap;
// translation stuff here
extern UINT8 *dc_translation;
extern struct r_lightlist_s *dc_lightlist;
extern INT32 dc_numlights, dc_maxlights;
//Fix TUTIFRUTI
extern INT32 dc_texheight;
// -----------------------
// SPAN DRAWING CODE STUFF
// -----------------------
extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap;
extern lighttable_t *ds_translation;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern INT32 ds_waterofs, ds_bgofs;
extern UINT16 ds_flatwidth, ds_flatheight;
extern boolean ds_powersoftwo;
extern UINT8 *ds_source;
extern UINT8 *ds_transmap;
typedef struct {
float x, y, z;
} floatv3_t;
// Vectors for Software's tilted slope drawers
extern floatv3_t *ds_su, *ds_sv, *ds_sz;
extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
extern float focallengthf, zeroheight;
// Variable flat sizes
extern UINT32 nflatxshift;
extern UINT32 nflatyshift;
extern UINT32 nflatshiftup;
extern UINT32 nflatmask;
/// \brief Top border /// \brief Top border
#define BRDR_T 0 #define BRDR_T 0
@ -163,85 +109,180 @@ void R_DrawViewBorder(void);
#define TRANSPARENTPIXEL 255 #define TRANSPARENTPIXEL 255
typedef struct colcontext_s
{
void (*func) (struct colcontext_s *);
vbuffer_t *dest;
INT32 x, yl, yh;
fixed_t iscale, texturemid;
lighttable_t *colormap;
UINT8 *source; // first pixel in a column
// translucency stuff here
UINT8 *transmap;
// translation stuff here
UINT8 *translation;
struct r_lightlist_s *lightlist;
INT32 numlights, maxlights;
//Fix TUTIFRUTI
INT32 texheight;
// vars for R_DrawMaskedColumn
// Rum and Raisin put these on the sprite context.
// I put them on the column context because it felt
// more appropriate (for [REDACTED] anyway)
INT16 *mfloorclip;
INT16 *mceilingclip;
fixed_t spryscale, sprtopscreen, sprbotscreen;
fixed_t windowtop, windowbottom;
// column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height
INT32 lengthcol;
} colcontext_t;
typedef struct spancontext_s
{
void (*func) (struct spancontext_s *);
vbuffer_t *dest;
INT32 y, x1, x2;
lighttable_t *colormap;
lighttable_t *translation;
fixed_t xfrac, yfrac, xstep, ystep;
INT32 waterofs, bgofs;
UINT16 flatwidth, flatheight;
boolean powersoftwo;
UINT8 *source;
UINT8 *transmap;
// Vectors for Software's tilted slope drawers
floatv3_t *su, *sv, *sz;
floatv3_t *sup, *svp, *szp;
floatv3_t slope_origin, slope_u, slope_v;
float zeroheight;
// Variable flat sizes
UINT32 nflatxshift;
UINT32 nflatyshift;
UINT32 nflatshiftup;
UINT32 nflatmask;
lighttable_t **zlight;
INT32 tiltlighting[MAXVIDWIDTH];
} spancontext_t;
typedef void (*colfunc_t) (colcontext_t *);
typedef void (*spanfunc_t) (spancontext_t *);
// ---------------------------------------------
// color mode dependent drawer function pointers
// ---------------------------------------------
#define BASEDRAWFUNC 0
enum
{
COLDRAWFUNC_BASE = BASEDRAWFUNC,
COLDRAWFUNC_FUZZY,
COLDRAWFUNC_TRANS,
COLDRAWFUNC_SHADE,
COLDRAWFUNC_SHADOWED,
COLDRAWFUNC_TRANSTRANS,
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG,
COLDRAWFUNC_MAX
};
extern colfunc_t colfuncs[COLDRAWFUNC_MAX];
enum
{
SPANDRAWFUNC_BASE = BASEDRAWFUNC,
SPANDRAWFUNC_TRANS,
SPANDRAWFUNC_TILTED,
SPANDRAWFUNC_TILTEDTRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_TILTEDSPLAT,
SPANDRAWFUNC_SPRITE,
SPANDRAWFUNC_TRANSSPRITE,
SPANDRAWFUNC_TILTEDSPRITE,
SPANDRAWFUNC_TILTEDTRANSSPRITE,
SPANDRAWFUNC_WATER,
SPANDRAWFUNC_TILTEDWATER,
SPANDRAWFUNC_FOG,
SPANDRAWFUNC_MAX
};
extern spanfunc_t spanfuncs[SPANDRAWFUNC_MAX];
extern spanfunc_t spanfuncs_npo2[SPANDRAWFUNC_MAX];
// ----------------- // -----------------
// 8bpp DRAWING CODE // 8bpp DRAWING CODE
// ----------------- // -----------------
void R_DrawColumn_8(void); void R_DrawColumn_8(colcontext_t *dc);
void R_DrawShadeColumn_8(void); void R_DrawShadeColumn_8(colcontext_t *dc);
void R_DrawTranslucentColumn_8(void); void R_DrawTranslucentColumn_8(colcontext_t *dc);
void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedColumn_8(colcontext_t *dc);
void R_DrawTranslatedTranslucentColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(colcontext_t *dc);
void R_Draw2sMultiPatchColumn_8(void); void R_Draw2sMultiPatchColumn_8(colcontext_t *dc);
void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_Draw2sMultiPatchTranslucentColumn_8(colcontext_t *dc);
void R_DrawFogColumn_8(void); void R_DrawFogColumn_8(colcontext_t *dc);
void R_DrawColumnShadowed_8(void); void R_DrawColumnShadowed_8(colcontext_t *dc);
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) void R_DrawSpan_8(spancontext_t *ds);
void R_DrawTranslucentSpan_8(spancontext_t *ds);
void R_DrawTiltedSpan_8(spancontext_t *ds);
void R_DrawTiltedTranslucentSpan_8(spancontext_t *ds);
void R_DrawSpan_8(void); void R_DrawSplat_8(spancontext_t *ds);
void R_DrawTranslucentSpan_8(void); void R_DrawTranslucentSplat_8(spancontext_t *ds);
void R_DrawTiltedSpan_8(void); void R_DrawTiltedSplat_8(spancontext_t *ds);
void R_DrawTiltedTranslucentSpan_8(void);
void R_DrawSplat_8(void); void R_DrawFloorSprite_8(spancontext_t *ds);
void R_DrawTranslucentSplat_8(void); void R_DrawTranslucentFloorSprite_8(spancontext_t *ds);
void R_DrawTiltedSplat_8(void); void R_DrawTiltedFloorSprite_8(spancontext_t *ds);
void R_DrawTiltedTranslucentFloorSprite_8(spancontext_t *ds);
void R_DrawFloorSprite_8(void); void R_DrawTranslucentWaterSpan_8(spancontext_t *ds);
void R_DrawTranslucentFloorSprite_8(void); void R_DrawTiltedTranslucentWaterSpan_8(spancontext_t *ds);
void R_DrawTiltedFloorSprite_8(void);
void R_DrawTiltedTranslucentFloorSprite_8(void);
void R_CalcTiltedLighting(fixed_t start, fixed_t end); void R_DrawFogSpan_8(spancontext_t *ds);
extern INT32 tiltlighting[MAXVIDWIDTH];
void R_DrawTranslucentWaterSpan_8(void);
void R_DrawTiltedTranslucentWaterSpan_8(void);
void R_DrawFogSpan_8(void);
// Lactozilla: Non-powers-of-two // Lactozilla: Non-powers-of-two
void R_DrawSpan_NPO2_8(void); void R_DrawSpan_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentSpan_NPO2_8(void); void R_DrawTranslucentSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedSpan_NPO2_8(void); void R_DrawTiltedSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawTiltedTranslucentSpan_NPO2_8(spancontext_t *ds);
void R_DrawSplat_NPO2_8(void); void R_DrawSplat_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(spancontext_t *ds);
void R_DrawTiltedSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(spancontext_t *ds);
void R_DrawFloorSprite_NPO2_8(void); void R_DrawFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentFloorSprite_NPO2_8(void); void R_DrawTranslucentFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTiltedFloorSprite_NPO2_8(void); void R_DrawTiltedFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void); void R_DrawTiltedTranslucentFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentWaterSpan_NPO2_8(void); void R_DrawTranslucentWaterSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); void R_DrawTiltedTranslucentWaterSpan_NPO2_8(spancontext_t *ds);
#ifdef USEASM
void ASMCALL R_DrawColumn_8_ASM(void);
void ASMCALL R_DrawShadeColumn_8_ASM(void);
void ASMCALL R_DrawTranslucentColumn_8_ASM(void);
void ASMCALL R_Draw2sMultiPatchColumn_8_ASM(void);
void ASMCALL R_DrawColumn_8_MMX(void);
void ASMCALL R_Draw2sMultiPatchColumn_8_MMX(void);
void ASMCALL R_DrawSpan_8_MMX(void);
#endif
// ------------------
// 16bpp DRAWING CODE
// ------------------
#ifdef HIGHCOLOR
void R_DrawColumn_16(void);
void R_DrawWallColumn_16(void);
void R_DrawTranslucentColumn_16(void);
void R_DrawTranslatedColumn_16(void);
void R_DrawSpan_16(void);
#endif
// ========================================================================= // =========================================================================
#endif // __R_DRAW__ #endif // __R_DRAW__

View file

@ -1,214 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_draw16.c
/// \brief 16bpp (HIGHCOLOR) span/column drawer functions
/// \note no includes because this is included as part of r_draw.c
// ==========================================================================
// COLUMNS
// ==========================================================================
/// \brief kick out the upper bit of each component (we're in 5 : 5 : 5)
#define HIMASK1 0x7bde
/** \brief The R_DrawColumn_16 function
standard upto 128high posts column drawer
*/
void R_DrawColumn_16(void)
{
INT32 count;
INT16 *dest;
fixed_t frac, fracstep;
count = dc_yh - dc_yl + 1;
// Zero length, column does not exceed a pixel.
if (count <= 0)
return;
#ifdef RANGECHECK
if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height)
I_Error("R_DrawColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
// Framebuffer destination address.
// Use ylookup LUT to avoid multiply with ScreenWidth.
// Use columnofs LUT for subwindows?
dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]);
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl - centery)*fracstep;
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
do
{
// Re-map color indices from wall texture column using a lighting/special effects LUT.
*dest = hicolormaps[((INT16 *)(void *)dc_source)[(frac>>FRACBITS)&127]>>1];
dest += vid.width;
frac += fracstep;
} while (--count);
}
/** \brief The R_DrawWallColumn_16 function
LAME cutnpaste: same as R_DrawColumn_16 but wraps around 256
instead of 128 for the tall sky textures (256x240)
*/
void R_DrawWallColumn_16(void)
{
INT32 count;
INT16 *dest;
fixed_t frac, fracstep;
count = dc_yh - dc_yl + 1;
// Zero length, column does not exceed a pixel.
if (count <= 0)
return;
#ifdef RANGECHECK
if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height)
I_Error("R_DrawWallColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]);
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl - centery)*fracstep;
do
{
*dest = hicolormaps[((INT16 *)(void *)dc_source)[(frac>>FRACBITS)&255]>>1];
dest += vid.width;
frac += fracstep;
} while (--count);
}
/** \brief The R_DrawTranslucentColumn_16 function
LAME cutnpaste: same as R_DrawColumn_16 but does
translucent
*/
void R_DrawTranslucentColumn_16(void)
{
INT32 count;
INT16 *dest;
fixed_t frac, fracstep;
// check out coords for src*
if ((dc_yl < 0) || (dc_x >= vid.width))
return;
count = dc_yh - dc_yl;
if (count < 0)
return;
#ifdef RANGECHECK
if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height)
I_Error("R_DrawTranslucentColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
// FIXME. As above.
dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]);
// Looks familiar.
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl - centery)*fracstep;
// Here we do an additional index re-mapping.
do
{
*dest = (INT16)((INT16)((color8to16[dc_source[frac>>FRACBITS]]>>1) & 0x39ce)
+ (INT16)(((*dest & HIMASK1)) & 0x7fff));
dest += vid.width;
frac += fracstep;
} while (count--);
}
/** \brief The R_DrawTranslatedColumn_16 function
?
*/
void R_DrawTranslatedColumn_16(void)
{
INT32 count;
INT16 *dest;
fixed_t frac, fracstep;
count = dc_yh - dc_yl;
if (count < 0)
return;
#ifdef RANGECHECK
if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height)
I_Error("R_DrawTranslatedColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]);
// Looks familiar.
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl - centery)*fracstep;
// Here we do an additional index re-mapping.
do
{
*dest = color8to16[dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]];
dest += vid.width;
frac += fracstep;
} while (count--);
}
// ==========================================================================
// SPANS
// ==========================================================================
/** \brief The R_*_16 function
Draws the actual span.
*/
void R_DrawSpan_16(void)
{
fixed_t xfrac, yfrac;
INT16 *dest;
INT32 count, spot;
#ifdef RANGECHECK
if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= vid.width || ds_y > vid.height)
I_Error("R_DrawSpan_16: %d to %d at %d", ds_x1, ds_x2, ds_y);
#endif
xfrac = ds_xfrac;
yfrac = ds_yfrac;
dest = (INT16 *)(void *)(ylookup[ds_y] + columnofs[ds_x1]);
// We do not check for zero spans here?
count = ds_x2 - ds_x1;
if (count <= 0) // We do now!
return;
do
{
// Current texture index in u, v.
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
// Lookup pixel from flat texture tile, re-index using light/colormap.
*dest++ = hicolormaps[((INT16 *)(void *)ds_source)[spot]>>1];
// Next step in u, v.
xfrac += ds_xstep;
yfrac += ds_ystep;
} while (count--);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -34,8 +34,7 @@
#include "r_textures.h" #include "r_textures.h"
#include "r_things.h" #include "r_things.h"
#include "r_draw.h" #include "r_draw.h"
#include "r_context.h"
extern drawseg_t *firstseg;
void SplitScreen_OnChange(void); void SplitScreen_OnChange(void);

View file

@ -53,6 +53,22 @@ INT64 mytotal = 0;
// Fineangles in the SCREENWIDTH wide window. // Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048 #define FIELDOFVIEW 2048
typedef struct renderdata_s
{
rendercontext_t context;
I_thread_handle thread;
I_Atomicval_t running;
I_Atomicval_t shouldquit;
I_Atomicval_t framewaiting;
I_Atomicval_t framefinished;
} renderdata_t;
static renderdata_t *renderdatas;
INT32 numrendercontexts = MAX_RENDER_THREADS;
INT32 numusablerendercontexts = 0;
boolean renderthreaded = false;
// increment every time a check is made // increment every time a check is made
size_t validcount = 1; size_t validcount = 1;
@ -102,20 +118,21 @@ extracolormap_t *extra_colormaps = NULL;
// Render stats // Render stats
precise_t ps_prevframetime = 0; precise_t ps_prevframetime = 0;
precise_t ps_rendercalltime = 0; precise_t ps_rendercalltime = 0;
precise_t ps_postprocesstime = 0;
precise_t ps_uitime = 0; precise_t ps_uitime = 0;
precise_t ps_swaptime = 0; precise_t ps_swaptime = 0;
precise_t ps_bsptime = 0; precise_t ps_bsptime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_spritecliptime = 0; precise_t ps_sw_spritecliptime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_portaltime = 0; precise_t ps_sw_portaltime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_planetime = 0; precise_t ps_sw_planetime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_maskedtime = 0; precise_t ps_sw_maskedtime[MAX_RENDER_THREADS] = {0};
int ps_numbspcalls = 0; int ps_numbspcalls[MAX_RENDER_THREADS] = {0};
int ps_numsprites = 0; int ps_numsprites[MAX_RENDER_THREADS] = {0};
int ps_numdrawnodes = 0; int ps_numdrawnodes[MAX_RENDER_THREADS] = {0};
int ps_numpolyobjects = 0; int ps_numpolyobjects[MAX_RENDER_THREADS] = {0};
static CV_PossibleValue_t drawdist_cons_t[] = { static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"}, {256, "256"}, {512, "512"}, {768, "768"},
@ -132,7 +149,7 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = {
static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}};
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};
static void Fov_OnChange(void); static void Fov_OnChange(void);
@ -163,9 +180,11 @@ consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, dr
//consvar_t cv_precipdensity = CVAR_INIT ("precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL); //consvar_t cv_precipdensity = CVAR_INIT ("precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL);
consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange); consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange);
// Okay, whoever said homremoval causes a performance hit should be shot.
consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL); consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL);
static CV_PossibleValue_t numthreads_cons_t[] = {{1, "MIN"}, {8, "MAX"}, {0, NULL}};
consvar_t cv_numthreads = CVAR_INIT ("numthreads", "2", CV_SAVE, numthreads_cons_t, NULL);
consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL);
consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL); consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL);
@ -411,35 +430,6 @@ angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
0; 0;
} }
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)
// at the given angle.
// rw_distance must be calculated first.
//
// killough 5/2/98: reformatted, cleaned up
//
// note: THIS IS USED ONLY FOR WALLS!
fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
{
angle_t anglea = ANGLE_90 + (visangle-viewangle);
angle_t angleb = ANGLE_90 + (visangle-rw_normalangle);
fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT));
// proff 11/06/98: Changed for high-res
fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT));
if (den > num>>16)
{
num = FixedDiv(num, den);
if (num > 64*FRACUNIT)
return 64*FRACUNIT;
if (num < 256)
return 256;
return num;
}
return 64*FRACUNIT;
}
// //
// R_DoCulling // R_DoCulling
// Checks viewz and top/bottom heights of an item against culling planes // Checks viewz and top/bottom heights of an item against culling planes
@ -883,6 +873,285 @@ void R_ApplyViewMorph(void)
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width); vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
} }
static void R_PortalFrame(rendercontext_t *context, portal_t *portal)
{
bspcontext_t *bspcontext = &context->bspcontext;
context->viewcontext.x = portal->viewx;
context->viewcontext.y = portal->viewy;
context->viewcontext.z = portal->viewz;
context->viewcontext.angle = portal->viewangle;
context->viewcontext.sin = FINESINE(portal->viewangle>>ANGLETOFINESHIFT);
context->viewcontext.cos = FINECOSINE(portal->viewangle>>ANGLETOFINESHIFT);
bspcontext->portalclipstart = portal->start;
bspcontext->portalclipend = portal->end;
if (portal->clipline != -1)
{
line_t *clipline = &lines[portal->clipline];
bspcontext->portalclipline = clipline;
bspcontext->portalcullsector = clipline->frontsector;
context->viewcontext.sector = clipline->frontsector;
}
else
{
bspcontext->portalclipline = NULL;
bspcontext->portalcullsector = NULL;
context->viewcontext.sector = R_PointInSubsector(context->viewcontext.x, context->viewcontext.y)->sector;
}
}
static void Mask_Pre (rendercontext_t *context, maskcount_t* m)
{
m->drawsegs[0] = context->bspcontext.ds_p - context->bspcontext.drawsegs;
m->vissprites[0] = context->spritecontext.visspritecount;
m->viewx = context->viewcontext.x;
m->viewy = context->viewcontext.y;
m->viewz = context->viewcontext.z;
m->viewsector = context->viewcontext.sector;
}
static void Mask_Post (rendercontext_t *context, maskcount_t* m)
{
m->drawsegs[1] = context->bspcontext.ds_p - context->bspcontext.drawsegs;
m->vissprites[1] = context->spritecontext.visspritecount;
}
static void R_RenderViewContext(rendercontext_t *rendercontext)
{
UINT8 nummasks = 1;
maskcount_t* masks = malloc(sizeof(maskcount_t));
bspcontext_t *bspcontext = &rendercontext->bspcontext;
planecontext_t *planecontext = &rendercontext->planecontext;
INT32 i = rendercontext->num;
// The head node is the last node output.
Mask_Pre(rendercontext, &masks[nummasks - 1]);
bspcontext->curdrawsegs = bspcontext->ds_p;
ps_numbspcalls[i] = ps_numpolyobjects[i] = ps_numdrawnodes[i] = 0;
ps_bsptime[i] = I_GetPreciseTime();
R_RenderBSPNode(rendercontext, (INT32)numnodes - 1);
ps_bsptime[i] = I_GetPreciseTime() - ps_bsptime[i];
ps_numsprites[i] = rendercontext->spritecontext.visspritecount;
Mask_Post(rendercontext, &masks[nummasks - 1]);
ps_sw_spritecliptime[i] = I_GetPreciseTime();
R_ClipSprites(rendercontext, bspcontext->drawsegs, NULL);
ps_sw_spritecliptime[i] = I_GetPreciseTime() - ps_sw_spritecliptime[i];
// Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0])
Portal_AddSkyboxPortals(rendercontext);
// Portal rendering. Hijacks the BSP traversal.
ps_sw_portaltime[i] = I_GetPreciseTime();
if (bspcontext->portal_base)
{
portal_t *portal = bspcontext->portal_base;
for (; portal; portal = bspcontext->portal_base)
{
bspcontext->portalrender = portal->pass; // Recursiveness depth.
R_ClearFFloorClips(planecontext);
// Apply the viewpoint stored for the portal.
R_PortalFrame(rendercontext, portal);
// Hack in the clipsegs to delimit the starting
// clipping for sprites and possibly other similar
// future items.
R_ClearClipSegs(bspcontext, portal->start, portal->end);
// Hack in the top/bottom clip values for the window
// that were previously stored.
Portal_ClipApply(planecontext, portal);
masks = realloc(masks, (++nummasks)*sizeof(maskcount_t));
Mask_Pre(rendercontext, &masks[nummasks - 1]);
bspcontext->curdrawsegs = bspcontext->ds_p;
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode(rendercontext, (INT32)numnodes - 1);
Mask_Post(rendercontext, &masks[nummasks - 1]);
R_ClipSprites(rendercontext, bspcontext->ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(bspcontext, portal);
}
}
ps_sw_portaltime[i] = I_GetPreciseTime() - ps_sw_portaltime[i];
ps_sw_planetime[i] = I_GetPreciseTime();
R_DrawPlanes(rendercontext);
ps_sw_planetime[i] = I_GetPreciseTime() - ps_sw_planetime[i];
// draw mid texture and sprite
// And now 3D floors/sides!
ps_sw_maskedtime[i] = I_GetPreciseTime();
R_DrawMasked(rendercontext, masks, nummasks);
ps_sw_maskedtime[i] = I_GetPreciseTime() - ps_sw_maskedtime[i];
free(masks);
#ifdef HAVE_THREADS
if (renderthreaded)
{
INT32 x = rendercontext->begincolumn;
INT32 w = (rendercontext->endcolumn - rendercontext->begincolumn);
INT32 c = 35 | V_NOSCALESTART;
V_DrawFill(x, 0, w, 1, c);
V_DrawFill(x, viewheight - 1, w, 1, c);
V_DrawFill(x, 0, 1, viewheight, c);
V_DrawFill(x+w-1, 0, 1, viewheight, c);
}
#endif
}
static void R_ResetContext(rendercontext_t *context, INT32 leftclip, INT32 rightclip)
{
context->begincolumn = leftclip;
context->endcolumn = rightclip;
// Clear buffers.
R_ClearPlanes(&context->planecontext);
if (viewmorph.use)
{
INT32 left = max(leftclip, viewmorph.x1);
INT32 right = min(viewwidth-viewmorph.x1-1, rightclip);
context->bspcontext.portalclipstart = left;
context->bspcontext.portalclipend = right;
R_ClearClipSegs(&context->bspcontext, left, right);
memcpy(context->planecontext.ceilingclip, viewmorph.ceilingclip, sizeof(INT16)*vid.width);
memcpy(context->planecontext.floorclip, viewmorph.floorclip, sizeof(INT16)*vid.width);
}
else
{
context->bspcontext.portalclipstart = leftclip;
context->bspcontext.portalclipend = rightclip;
R_ClearClipSegs(&context->bspcontext, leftclip, rightclip);
}
R_ClearDrawSegs(&context->bspcontext);
R_ClearSprites(&context->spritecontext);
Portal_InitList(&context->bspcontext);
}
#ifdef HAVE_THREADS
static void R_ContextThreadFunc(void *userdata)
{
renderdata_t *data = (renderdata_t *)userdata;
I_atomic_exchange(&data->running, 1);
while (!I_atomic_load(&data->shouldquit))
{
if (I_atomic_exchange(&data->framewaiting, 0))
{
R_RenderViewContext(&data->context);
I_atomic_exchange(&data->framefinished, 1);
}
}
I_atomic_exchange(&data->running, 0);
}
#endif
static void R_StartThreads(void)
{
#ifdef HAVE_THREADS
INT32 currcontext;
for (currcontext = 0; currcontext < numusablerendercontexts; ++currcontext)
{
renderdata_t *renderdata = &renderdatas[currcontext];
rendercontext_t *context = &renderdata->context;
context->colcontext.func = colfuncs[BASEDRAWFUNC];
context->spancontext.func = spanfuncs[BASEDRAWFUNC];
I_atomic_exchange(&renderdata->running, 0);
I_atomic_exchange(&renderdata->shouldquit, 0);
I_atomic_exchange(&renderdata->framewaiting, 0);
I_atomic_exchange(&renderdata->framefinished, 0);
renderdata->thread = I_spawn_thread("software-renderer", (I_thread_fn)R_ContextThreadFunc, context);
}
#endif
}
void R_StopThreads(void)
{
#ifdef HAVE_THREADS
INT32 currcontext;
if (!numusablerendercontexts)
return;
for (currcontext = 0; currcontext < numusablerendercontexts; ++currcontext)
I_atomic_exchange(&renderdatas[currcontext].shouldquit, 1);
for (;;) {
INT32 stoppedthreads = 0;
for (currcontext = 0; currcontext < numusablerendercontexts; ++currcontext)
stoppedthreads += !I_atomic_load(&renderdatas[currcontext].running);
if (stoppedthreads == numusablerendercontexts)
break;
}
numusablerendercontexts = 0;
#endif
}
static void R_InitContexts(void)
{
INT32 currcontext;
INT32 currstart;
INT32 incrementby;
currstart = 0;
incrementby = vid.width / numrendercontexts;
renderdatas = Z_Calloc(sizeof(renderdata_t) * numrendercontexts, PU_STATIC, NULL);
for (currcontext = 0; currcontext < numrendercontexts; ++currcontext)
{
renderdata_t *renderdata = &renderdatas[currcontext];
rendercontext_t *context = &renderdata->context;
context->num = currcontext;
context->begincolumn = max(currstart, 0);
currstart += incrementby;
context->endcolumn = min(currstart, vid.width);
context->planecontext.freehead = &context->planecontext.freetail;
R_ResetContext(&renderdata->context, context->begincolumn, context->endcolumn);
R_InitDrawNodes(&renderdata->context.spritecontext.nodebankhead);
context->colcontext.func = colfuncs[BASEDRAWFUNC];
context->spancontext.func = spanfuncs[BASEDRAWFUNC];
}
}
// //
// R_SetViewSize // R_SetViewSize
@ -960,7 +1229,7 @@ void R_ExecuteSetViewSize(void)
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy); yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
} }
if (ds_su) /*if (ds_su)
Z_Free(ds_su); Z_Free(ds_su);
if (ds_sv) if (ds_sv)
Z_Free(ds_sv); Z_Free(ds_sv);
@ -968,7 +1237,7 @@ void R_ExecuteSetViewSize(void)
Z_Free(ds_sz); Z_Free(ds_sz);
ds_su = ds_sv = ds_sz = NULL; ds_su = ds_sv = ds_sz = NULL;
ds_sup = ds_svp = ds_szp = NULL; ds_sup = ds_svp = ds_szp = NULL;*/
} }
memset(scalelight, 0xFF, sizeof(scalelight)); memset(scalelight, 0xFF, sizeof(scalelight));
@ -1024,7 +1293,7 @@ void R_Init(void)
//I_OutputMsg("\nR_InitTranslucencyTables\n"); //I_OutputMsg("\nR_InitTranslucencyTables\n");
R_InitTranslucencyTables(); R_InitTranslucencyTables();
R_InitDrawNodes(); R_InitContexts();
framecount = 0; framecount = 0;
} }
@ -1394,63 +1663,57 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
return false; return false;
} }
static void R_PortalFrame(portal_t *portal)
{
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
viewangle = portal->viewangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
portalclipstart = portal->start;
portalclipend = portal->end;
if (portal->clipline != -1)
{
portalclipline = &lines[portal->clipline];
portalcullsector = portalclipline->frontsector;
viewsector = portalclipline->frontsector;
}
else
{
portalclipline = NULL;
portalcullsector = NULL;
viewsector = R_PointInSubsector(viewx, viewy)->sector;
}
}
static void Mask_Pre (maskcount_t* m)
{
m->drawsegs[0] = ds_p - drawsegs;
m->vissprites[0] = visspritecount;
m->viewx = viewx;
m->viewy = viewy;
m->viewz = viewz;
m->viewsector = viewsector;
}
static void Mask_Post (maskcount_t* m)
{
m->drawsegs[1] = ds_p - drawsegs;
m->vissprites[1] = visspritecount;
}
// ================ // ================
// R_RenderView // R_RenderView
// ================ // ================
// FAB NOTE FOR WIN32 PORT !! I'm not finished already, static void R_PrepareViewContext(viewcontext_t *context)
// but I suspect network may have problems with the video buffer being locked {
// for all duration of rendering, and being released only once at the end.. context->x = viewx;
// I mean, there is a win16lock() or something that lasts all the rendering, context->y = viewy;
// so maybe we should release screen lock before each netupdate below..? context->z = viewz;
context->angle = viewangle;
context->sin = viewsin;
context->cos = viewcos;
context->sector = viewsector;
context->player = viewplayer;
context->mobj = r_viewmobj;
}
static void R_PrepareContexts(void)
{
INT32 currcontext;
INT32 currstart = 0;
INT32 desiredwidth = viewwidth / numusablerendercontexts;
INT32 i;
for (currcontext = 0; currcontext < numusablerendercontexts; ++currcontext)
{
rendercontext_t *context = &renderdatas[currcontext].context;
context->buffer.screens[0] = topleft;
for (i = 1; i < NUMSCREENS; i++)
context->buffer.screens[i] = screens[i];
context->begincolumn = max(currstart, 0);
currstart += desiredwidth;
context->endcolumn = min(currstart, viewwidth);
R_ResetContext(context, context->begincolumn, context->endcolumn);
R_PrepareViewContext(&context->viewcontext);
if (context->spritecontext.sectorvisited == NULL)
context->spritecontext.sectorvisited = Z_Calloc(sizeof(boolean) * numsectors, PU_LEVEL, NULL);
memset(context->spritecontext.sectorvisited, 0, sizeof(boolean) * numsectors);
}
}
void R_RenderPlayerView(player_t *player) void R_RenderPlayerView(player_t *player)
{ {
UINT8 nummasks = 1; INT32 currcontext;
maskcount_t* masks = malloc(sizeof(maskcount_t)); INT32 finishedcontexts = 0;
if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
{ {
@ -1462,117 +1725,49 @@ void R_RenderPlayerView(player_t *player)
R_SetupFrame(player); R_SetupFrame(player);
framecount++; framecount++;
validcount++;
// Clear buffers.
R_ClearPlanes();
if (viewmorph.use)
{
portalclipstart = viewmorph.x1;
portalclipend = viewwidth-viewmorph.x1-1;
R_PortalClearClipSegs(portalclipstart, portalclipend);
memcpy(ceilingclip, viewmorph.ceilingclip, sizeof(INT16)*vid.width);
memcpy(floorclip, viewmorph.floorclip, sizeof(INT16)*vid.width);
}
else
{
portalclipstart = 0;
portalclipend = viewwidth;
R_ClearClipSegs();
}
R_ClearDrawSegs();
R_ClearSprites();
Portal_InitList();
// check for new console commands. // check for new console commands.
NetUpdate(); NetUpdate();
// The head node is the last node output. #ifdef HAVE_THREADS
if (cv_numthreads.value != numusablerendercontexts)
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
//profile stuff ---------------------------------------------------------
#ifdef TIMING
mytotal = 0;
ProfZeroTimer();
#endif
ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0;
ps_bsptime = I_GetPreciseTime();
R_RenderBSPNode((INT32)numnodes - 1);
ps_bsptime = I_GetPreciseTime() - ps_bsptime;
ps_numsprites = visspritecount;
#ifdef TIMING
RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add
CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal);
#endif
//profile stuff ---------------------------------------------------------
Mask_Post(&masks[nummasks - 1]);
ps_sw_spritecliptime = I_GetPreciseTime();
R_ClipSprites(drawsegs, NULL);
ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime;
// Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0])
Portal_AddSkyboxPortals();
// Portal rendering. Hijacks the BSP traversal.
ps_sw_portaltime = I_GetPreciseTime();
if (portal_base)
{ {
portal_t *portal; if (renderthreaded)
R_StopThreads();
for(portal = portal_base; portal; portal = portal_base) numusablerendercontexts = cv_numthreads.value;
renderthreaded = (numusablerendercontexts > 1);
if (renderthreaded)
R_StartThreads();
}
#else
numusablerendercontexts = 1;
renderthreaded = false;
#endif
R_PrepareContexts();
for (currcontext = 0; currcontext < numusablerendercontexts; currcontext++)
{ {
portalrender = portal->pass; // Recursiveness depth. #ifdef HAVE_THREADS
if (renderthreaded)
R_ClearFFloorClips(); I_atomic_exchange(&renderdatas[currcontext].framewaiting, 1);
else
// Apply the viewpoint stored for the portal. #endif
R_PortalFrame(portal); {
R_RenderViewContext(&renderdatas[currcontext].context);
// Hack in the clipsegs to delimit the starting finishedcontexts++;
// clipping for sprites and possibly other similar
// future items.
R_PortalClearClipSegs(portal->start, portal->end);
// Hack in the top/bottom clip values for the window
// that were previously stored.
Portal_ClipApply(portal);
validcount++;
masks = realloc(masks, (++nummasks)*sizeof(maskcount_t));
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
Mask_Post(&masks[nummasks - 1]);
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(portal);
} }
} }
ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime;
ps_sw_planetime = I_GetPreciseTime(); #ifdef HAVE_THREADS
R_DrawPlanes(); while (renderthreaded && finishedcontexts != numusablerendercontexts)
ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime; {
for (currcontext = 0; currcontext < numusablerendercontexts; currcontext++)
// draw mid texture and sprite finishedcontexts += I_atomic_exchange(&renderdatas[currcontext].framefinished, 0);
// And now 3D floors/sides! }
ps_sw_maskedtime = I_GetPreciseTime(); #endif
R_DrawMasked(masks, nummasks);
ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime;
free(masks);
} }
// ========================================================================= // =========================================================================
@ -1639,6 +1834,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_translucenthud); CV_RegisterVar(&cv_translucenthud);
CV_RegisterVar(&cv_maxportals); CV_RegisterVar(&cv_maxportals);
CV_RegisterVar(&cv_numthreads);
CV_RegisterVar(&cv_movebob); CV_RegisterVar(&cv_movebob);
} }

View file

@ -29,6 +29,10 @@ extern fixed_t centerxfrac, centeryfrac;
extern fixed_t projection, projectiony; extern fixed_t projection, projectiony;
extern fixed_t fovtan; extern fixed_t fovtan;
extern INT32 numrendercontexts;
extern INT32 numusablerendercontexts;
extern boolean renderthreaded;
// WARNING: a should be unsigned but to add with 2048, it isn't! // WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan) #define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan)
@ -70,7 +74,6 @@ angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1);
fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist(fixed_t x, fixed_t y);
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
@ -80,20 +83,21 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
extern precise_t ps_prevframetime; // time when previous frame was rendered extern precise_t ps_prevframetime; // time when previous frame was rendered
extern precise_t ps_rendercalltime; extern precise_t ps_rendercalltime;
extern precise_t ps_postprocesstime;
extern precise_t ps_uitime; extern precise_t ps_uitime;
extern precise_t ps_swaptime; extern precise_t ps_swaptime;
extern precise_t ps_bsptime; extern precise_t ps_bsptime[MAX_RENDER_THREADS];
extern precise_t ps_sw_spritecliptime; extern precise_t ps_sw_spritecliptime[MAX_RENDER_THREADS];
extern precise_t ps_sw_portaltime; extern precise_t ps_sw_portaltime[MAX_RENDER_THREADS];
extern precise_t ps_sw_planetime; extern precise_t ps_sw_planetime[MAX_RENDER_THREADS];
extern precise_t ps_sw_maskedtime; extern precise_t ps_sw_maskedtime[MAX_RENDER_THREADS];
extern int ps_numbspcalls; extern int ps_numbspcalls[MAX_RENDER_THREADS];
extern int ps_numsprites; extern int ps_numsprites[MAX_RENDER_THREADS];
extern int ps_numdrawnodes; extern int ps_numdrawnodes[MAX_RENDER_THREADS];
extern int ps_numpolyobjects; extern int ps_numpolyobjects[MAX_RENDER_THREADS];
// //
// REFRESH - the actual rendering functions. // REFRESH - the actual rendering functions.
@ -131,6 +135,8 @@ void R_SkyboxFrame(player_t *player);
boolean R_ViewpointHasChasecam(player_t *player); boolean R_ViewpointHasChasecam(player_t *player);
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox);
void R_StopThreads(void);
// Called by D_Display. // Called by D_Display.
void R_RenderPlayerView(player_t *player); void R_RenderPlayerView(player_t *player);

File diff suppressed because it is too large Load diff

View file

@ -55,52 +55,9 @@ typedef struct visplane_s
pslope_t *slope; pslope_t *slope;
} visplane_t; } visplane_t;
extern visplane_t *visplanes[MAXVISPLANES];
extern visplane_t *floorplane;
extern visplane_t *ceilingplane;
// Visplane related.
extern INT16 *lastopening, *openings;
extern size_t maxopenings;
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
extern fixed_t cachedheight[MAXVIDHEIGHT];
extern fixed_t cacheddistance[MAXVIDHEIGHT];
extern fixed_t cachedxstep[MAXVIDHEIGHT];
extern fixed_t cachedystep[MAXVIDHEIGHT];
extern fixed_t *yslope;
extern lighttable_t **planezlight;
void R_InitPlanes(void);
void R_ClearPlanes(void);
void R_ClearFFloorClips (void);
void R_DrawPlanes(void);
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope);
visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_PlaneBounds(visplane_t *plane);
void R_CheckFlatLength(size_t size);
boolean R_CheckPowersOfTwo(void);
// Draws a single visplane.
void R_DrawSinglePlane(visplane_t *pl);
// Calculates the slope vectors needed for tilted span drawing.
void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_CalculateSlopeVectors(void);
// Sets the slope vector pointers for the current tilted span.
void R_SetTiltedSpan(INT32 span);
typedef struct planemgr_s typedef struct planemgr_s
{ {
visplane_t *plane; struct visplane_s *plane;
fixed_t height; fixed_t height;
fixed_t f_pos; // F for Front sector fixed_t f_pos; // F for Front sector
fixed_t b_pos; // B for Back sector fixed_t b_pos; // B for Back sector
@ -117,10 +74,36 @@ typedef struct planemgr_s
struct ffloor_s *ffloor; struct ffloor_s *ffloor;
polyobj_t *polyobj; polyobj_t *polyobj;
} visffloor_t; } planemgr_t;
extern visffloor_t ffloor[MAXFFLOORS]; // Visplane related.
extern INT32 numffloors; extern fixed_t yslopetab[MAXVIDHEIGHT*16];
extern fixed_t *yslope;
void Portal_AddSkyboxPortals (void); struct planecontext_s;
struct rendercontext_s;
struct viewcontext_s;
void R_InitPlanes(void);
void R_ClearPlanes(struct planecontext_s *context);
void R_ClearFFloorClips (struct planecontext_s *context);
void R_DrawPlanes(struct rendercontext_s *planecontext);
visplane_t *R_FindPlane(struct planecontext_s *planecontext, struct viewcontext_s *viewcontext,
fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope);
visplane_t *R_CheckPlane(struct planecontext_s *planecontext, visplane_t *pl, INT32 start, INT32 stop);
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_PlaneBounds(visplane_t *plane);
// Draws a single visplane.
void R_DrawSinglePlane(struct rendercontext_s *rendercontext, visplane_t *pl);
// Calculates the slope vectors needed for tilted span drawing.
void R_SetSlopePlane(pslope_t *slope, spancontext_t *ds, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_SetScaledSlopePlane(pslope_t *slope, spancontext_t *ds, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_CalculateSlopeVectors(spancontext_t *ds);
// Sets the slope vector pointers for the current tilted span.
void R_SetTiltedSpan(spancontext_t *ds, INT32 span);
#endif #endif

View file

@ -14,27 +14,17 @@
#include "r_portal.h" #include "r_portal.h"
#include "r_plane.h" #include "r_plane.h"
#include "r_main.h" #include "r_main.h"
#include "r_context.h"
#include "doomstat.h" #include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints #include "p_spec.h" // Skybox viewpoints
#include "z_zone.h" #include "z_zone.h"
#include "r_things.h" #include "r_things.h"
#include "r_sky.h" #include "r_sky.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ void Portal_InitList (bspcontext_t *bspcontext)
// Linked list for portals.
portal_t *portal_base, *portal_cap;
line_t *portalclipline;
sector_t *portalcullsector;
INT32 portalclipstart, portalclipend;
boolean portalline; // is curline a portal seg?
void Portal_InitList (void)
{ {
portalrender = 0; bspcontext->portalrender = 0;
portal_base = portal_cap = NULL; bspcontext->portal_base = bspcontext->portal_cap = NULL;
} }
/** Store the clipping window for a portal in its given range. /** Store the clipping window for a portal in its given range.
@ -43,7 +33,7 @@ void Portal_InitList (void)
* the function is called, so it is useful for converting one-sided * the function is called, so it is useful for converting one-sided
* lines into portals. * lines into portals.
*/ */
void Portal_ClipRange (portal_t* portal) void Portal_ClipRange (planecontext_t *planecontext, portal_t* portal)
{ {
INT32 start = portal->start; INT32 start = portal->start;
INT32 end = portal->end; INT32 end = portal->end;
@ -54,18 +44,18 @@ void Portal_ClipRange (portal_t* portal)
INT32 i; INT32 i;
for (i = 0; i < end-start; i++) for (i = 0; i < end-start; i++)
{ {
*ceil = ceilingclip[start+i]; *ceil = planecontext->ceilingclip[start+i];
ceil++; ceil++;
*floor = floorclip[start+i]; *floor = planecontext->floorclip[start+i];
floor++; floor++;
*scale = frontscale[start+i]; *scale = planecontext->frontscale[start+i];
scale++; scale++;
} }
} }
/** Apply the clipping window from a portal. /** Apply the clipping window from a portal.
*/ */
void Portal_ClipApply (const portal_t* portal) void Portal_ClipApply (planecontext_t *planecontext, const portal_t* portal)
{ {
INT32 i; INT32 i;
INT32 start = portal->start; INT32 start = portal->start;
@ -76,28 +66,28 @@ void Portal_ClipApply (const portal_t* portal)
for (i = 0; i < end-start; i++) for (i = 0; i < end-start; i++)
{ {
ceilingclip[start+i] = *ceil; planecontext->ceilingclip[start+i] = *ceil;
ceil++; ceil++;
floorclip[start+i] = *floor; planecontext->floorclip[start+i] = *floor;
floor++; floor++;
frontscale[start+i] = *scale; planecontext->frontscale[start+i] = *scale;
scale++; scale++;
} }
// HACKS FOLLOW // HACKS FOLLOW
for (i = 0; i < start; i++) for (i = 0; i < start; i++)
{ {
floorclip[i] = -1; planecontext->floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight; planecontext->ceilingclip[i] = (INT16)viewheight;
} }
for (i = end; i < vid.width; i++) for (i = end; i < vid.width; i++)
{ {
floorclip[i] = -1; planecontext->floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight; planecontext->ceilingclip[i] = (INT16)viewheight;
} }
} }
static portal_t* Portal_Add (const INT16 x1, const INT16 x2) static portal_t* Portal_Add (bspcontext_t *context, const INT16 x1, const INT16 x2)
{ {
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
@ -105,15 +95,15 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL);
// Linked list. // Linked list.
if (!portal_base) if (!context->portal_base)
{ {
portal_base = portal; context->portal_base = portal;
portal_cap = portal; context->portal_cap = portal;
} }
else else
{ {
portal_cap->next = portal; context->portal_cap->next = portal;
portal_cap = portal; context->portal_cap = portal;
} }
portal->next = NULL; portal->next = NULL;
@ -125,14 +115,14 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
portal->end = x2; portal->end = x2;
// Increase recursion level. // Increase recursion level.
portal->pass = portalrender+1; portal->pass = context->portalrender+1;
return portal; return portal;
} }
void Portal_Remove (portal_t* portal) void Portal_Remove (bspcontext_t *context, portal_t* portal)
{ {
portal_base = portal->next; context->portal_base = portal->next;
Z_Free(portal->ceilingclip); Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip); Z_Free(portal->floorclip);
Z_Free(portal->frontscale); Z_Free(portal->frontscale);
@ -149,9 +139,10 @@ void Portal_Remove (portal_t* portal)
* When the portal renders, it will create the illusion of * When the portal renders, it will create the illusion of
* the two lines being seamed together. * the two lines being seamed together.
*/ */
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2) void Portal_Add2Lines (rendercontext_t *context,
const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
{ {
portal_t* portal = Portal_Add(x1, x2); portal_t* portal = Portal_Add(&context->bspcontext, x1, x2);
// Offset the portal view by the linedef centers // Offset the portal view by the linedef centers
line_t* start = &lines[line1]; line_t* start = &lines[line1];
@ -172,20 +163,20 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
dest_c.x = (dest->v1->x + dest->v2->x) / 2; dest_c.x = (dest->v1->x + dest->v2->x) / 2;
dest_c.y = (dest->v1->y + dest->v2->y) / 2; dest_c.y = (dest->v1->y + dest->v2->y) / 2;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); disttopoint = R_PointToDist2(start_c.x, start_c.y, context->viewcontext.x, context->viewcontext.y);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); angtopoint = R_PointToAngle2(start_c.x, start_c.y, context->viewcontext.x, context->viewcontext.y);
angtopoint += dangle; angtopoint += dangle;
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; portal->viewz = context->viewcontext.z + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle; portal->viewangle = context->viewcontext.angle + dangle;
portal->clipline = line2; portal->clipline = line2;
Portal_ClipRange(portal); Portal_ClipRange(&context->planecontext, portal);
portalline = true; // this tells R_StoreWallRange that curline is a portal seg context->bspcontext.portalline = true; // this tells R_StoreWallRange that curline is a portal seg
} }
/** Store the clipping window for a portal using a visplane. /** Store the clipping window for a portal using a visplane.
@ -256,7 +247,7 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16*
* Applies the necessary offsets and rotation to give * Applies the necessary offsets and rotation to give
* a depth illusion to the skybox. * a depth illusion to the skybox.
*/ */
void Portal_AddSkybox (const visplane_t* plane) void Portal_AddSkybox (bspcontext_t *bspcontext, viewcontext_t *viewcontext, const visplane_t* plane)
{ {
INT16 start, end; INT16 start, end;
mapheader_t *mh; mapheader_t *mh;
@ -265,14 +256,14 @@ void Portal_AddSkybox (const visplane_t* plane)
if (TrimVisplaneBounds(plane, &start, &end)) if (TrimVisplaneBounds(plane, &start, &end))
return; return;
portal = Portal_Add(start, end); portal = Portal_Add(bspcontext, start, end);
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x; portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y; portal->viewy = skyboxmo[0]->y;
portal->viewz = skyboxmo[0]->z; portal->viewz = skyboxmo[0]->z;
portal->viewangle = viewangle + skyboxmo[0]->angle; portal->viewangle = viewcontext->angle + skyboxmo[0]->angle;
mh = mapheaderinfo[gamemap-1]; mh = mapheaderinfo[gamemap-1];
@ -283,14 +274,14 @@ void Portal_AddSkybox (const visplane_t* plane)
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT; angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
if (mh->skybox_scalex > 0) if (mh->skybox_scalex > 0)
x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex; x = (viewcontext->x - skyboxmo[1]->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0) else if (mh->skybox_scalex < 0)
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex; x = (viewcontext->x - skyboxmo[1]->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0) if (mh->skybox_scaley > 0)
y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley; y = (viewcontext->y - skyboxmo[1]->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0) else if (mh->skybox_scaley < 0)
y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley; y = (viewcontext->y - skyboxmo[1]->y) * -mh->skybox_scaley;
// Apply transform to account for the skybox viewport angle. // Apply transform to account for the skybox viewport angle.
portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
@ -298,9 +289,9 @@ void Portal_AddSkybox (const visplane_t* plane)
} }
if (mh->skybox_scalez > 0) if (mh->skybox_scalez > 0)
portal->viewz += viewz / mh->skybox_scalez; portal->viewz += viewcontext->z / mh->skybox_scalez;
else if (mh->skybox_scalez < 0) else if (mh->skybox_scalez < 0)
portal->viewz += viewz * -mh->skybox_scalez; portal->viewz += viewcontext->z * -mh->skybox_scalez;
portal->clipline = -1; portal->clipline = -1;
} }
@ -308,7 +299,7 @@ void Portal_AddSkybox (const visplane_t* plane)
/** Creates portals for the currently existing sky visplanes. /** Creates portals for the currently existing sky visplanes.
* The visplanes are also removed and cleared from the list. * The visplanes are also removed and cleared from the list.
*/ */
void Portal_AddSkyboxPortals (void) void Portal_AddSkyboxPortals (rendercontext_t *context)
{ {
visplane_t *pl; visplane_t *pl;
INT32 i; INT32 i;
@ -316,11 +307,11 @@ void Portal_AddSkyboxPortals (void)
for (i = 0; i < MAXVISPLANES; i++, pl++) for (i = 0; i < MAXVISPLANES; i++, pl++)
{ {
for (pl = visplanes[i]; pl; pl = pl->next) for (pl = context->planecontext.visplanes[i]; pl; pl = pl->next)
{ {
if (pl->picnum == skyflatnum) if (pl->picnum == skyflatnum)
{ {
Portal_AddSkybox(pl); Portal_AddSkybox(&context->bspcontext, &context->viewcontext, pl);
pl->minx = 0; pl->minx = 0;
pl->maxx = -1; pl->maxx = -1;

View file

@ -41,21 +41,19 @@ typedef struct portal_s
fixed_t *frontscale;/**< Temporary screen bottom clipping array. */ fixed_t *frontscale;/**< Temporary screen bottom clipping array. */
} portal_t; } portal_t;
extern portal_t* portal_base; struct bspcontext_s;
extern portal_t* portal_cap; struct planecontext_s;
extern UINT8 portalrender; struct rendercontext_s;
struct viewcontext_s;
extern line_t *portalclipline; void Portal_InitList (struct bspcontext_s *bspcontext);
extern sector_t *portalcullsector; void Portal_Remove (struct bspcontext_s *context, portal_t* portal);
extern INT32 portalclipstart, portalclipend; void Portal_Add2Lines (struct rendercontext_s *context,
const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddSkybox (struct bspcontext_s *bspcontext, struct viewcontext_s *viewcontext, const visplane_t* plane);
void Portal_InitList (void); void Portal_ClipRange (struct planecontext_s *planecontext, portal_t* portal);
void Portal_Remove (portal_t* portal); void Portal_ClipApply (struct planecontext_s *planecontext, const portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddSkybox (const visplane_t* plane);
void Portal_ClipRange (portal_t* portal); void Portal_AddSkyboxPortals (struct rendercontext_s *context);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -18,9 +18,12 @@
#pragma interface #pragma interface
#endif #endif
struct rendercontext_s;
struct wallcontext_s;
transnum_t R_GetLinedefTransTable(fixed_t alpha); transnum_t R_GetLinedefTransTable(fixed_t alpha);
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderMaskedSegRange(struct rendercontext_s *context, drawseg_t *ds, INT32 x1, INT32 x2);
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_RenderThickSideRange(struct rendercontext_s *context, drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
void R_StoreWallRange(INT32 start, INT32 stop); void R_StoreWallRange(struct rendercontext_s *context, struct wallcontext_s *wallcontext, INT32 start, INT32 stop);
#endif #endif

View file

@ -54,9 +54,6 @@ INT32 globallevelskynum;
Called at loadlevel after skytexture is set, or when sky texture changes. Called at loadlevel after skytexture is set, or when sky texture changes.
\warning wallcolfunc should be set at R_ExecuteSetViewSize()
I don't bother because we don't use low detail anymore
\return void \return void
*/ */
void R_SetupSkyDraw(void) void R_SetupSkyDraw(void)

View file

@ -13,37 +13,22 @@
#include "r_draw.h" #include "r_draw.h"
#include "r_main.h" #include "r_main.h"
#include "r_splats.h" #include "r_splats.h"
#include "r_context.h"
#include "r_bsp.h" #include "r_bsp.h"
#include "p_local.h" #include "p_local.h"
#include "p_slopes.h" #include "p_slopes.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
struct rastery_s *prastertab; // for ASM code static void prepare_rastertab(planecontext_t *planecontext);
static struct rastery_s rastertab[MAXVIDHEIGHT];
static void prepare_rastertab(void);
// ========================================================================== // ==========================================================================
// FLOOR SPLATS // FLOOR SPLATS
// ========================================================================== // ==========================================================================
static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); static void R_RasterizeFloorSplat(rendercontext_t *context, floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis);
#ifdef USEASM static void rasterize_segment_tex(planecontext_t *planecontext, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir)
void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir);
#endif
static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir)
{
#ifdef USEASM
if (R_ASM)
{
rasterize_segment_tex_asm(x1, y1, x2, y2, tv1, tv2, tc, dir);
return;
}
else
#endif
{ {
fixed_t xs, xe, count; fixed_t xs, xe, count;
fixed_t dx0, dx1; fixed_t dx0, dx1;
@ -66,9 +51,9 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
{ {
for (;;) for (;;)
{ {
rastertab[y1].maxx = xs; planecontext->rastertab[y1].maxx = xs;
rastertab[y1].tx2 = xe; planecontext->rastertab[y1].tx2 = xe;
rastertab[y1].ty2 = tc; planecontext->rastertab[y1].ty2 = tc;
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
@ -81,9 +66,9 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
{ {
for (;;) for (;;)
{ {
rastertab[y1].maxx = xs; planecontext->rastertab[y1].maxx = xs;
rastertab[y1].tx2 = tc; planecontext->rastertab[y1].tx2 = tc;
rastertab[y1].ty2 = xe; planecontext->rastertab[y1].ty2 = xe;
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
@ -108,9 +93,9 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
{ {
for (;;) for (;;)
{ {
rastertab[y2].minx = xs; planecontext->rastertab[y2].minx = xs;
rastertab[y2].tx1 = xe; planecontext->rastertab[y2].tx1 = xe;
rastertab[y2].ty1 = tc; planecontext->rastertab[y2].ty1 = tc;
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
@ -123,9 +108,9 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
{ {
for (;;) for (;;)
{ {
rastertab[y2].minx = xs; planecontext->rastertab[y2].minx = xs;
rastertab[y2].tx1 = tc; planecontext->rastertab[y2].tx1 = tc;
rastertab[y2].ty1 = xe; planecontext->rastertab[y2].ty1 = xe;
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
@ -136,9 +121,8 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
} }
} }
} }
}
void R_DrawFloorSplat(vissprite_t *spr) void R_DrawFloorSplat(rendercontext_t *context, vissprite_t *spr)
{ {
floorsplat_t splat; floorsplat_t splat;
mobj_t *mobj = spr->mobj; mobj_t *mobj = spr->mobj;
@ -308,7 +292,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS;
} }
R_RasterizeFloorSplat(&splat, v2d, spr); R_RasterizeFloorSplat(context, &splat, v2d, spr);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@ -316,7 +300,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
// fill the polygon with linear interpolation, call span drawer for each // fill the polygon with linear interpolation, call span drawer for each
// scan line // scan line
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) static void R_RasterizeFloorSplat(rendercontext_t *context, floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis)
{ {
// rasterizing // rasterizing
INT32 miny = viewheight + 1, maxy = 0; INT32 miny = viewheight + 1, maxy = 0;
@ -325,9 +309,13 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
fixed_t planeheight = 0; fixed_t planeheight = 0;
fixed_t step; fixed_t step;
planecontext_t *planecontext = &context->planecontext;
colcontext_t *dc = &context->colcontext;
spancontext_t *ds = &context->spancontext;
int spanfunctype = SPANDRAWFUNC_SPRITE; int spanfunctype = SPANDRAWFUNC_SPRITE;
prepare_rastertab(); prepare_rastertab(planecontext);
#define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \ #define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \
x1 = verts[vnum1].x; \ x1 = verts[vnum1].x; \
@ -372,7 +360,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
} \ } \
y2 = vid.height - 1; \ y2 = vid.height - 1; \
} \ } \
rasterize_segment_tex(x1, ry1, x2, y2, tv1, tv2, tc, dir); \ rasterize_segment_tex(planecontext, x1, ry1, x2, y2, tv1, tv2, tc, dir); \
if (ry1 < miny) \ if (ry1 < miny) \
miny = ry1; \ miny = ry1; \
if (ry1 > maxy) \ if (ry1 > maxy) \
@ -387,27 +375,27 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
// do segment d -> left side of texture // do segment d -> left side of texture
RASTERPARAMS(0,3,pSplat->width-1,0,0,1); RASTERPARAMS(0,3,pSplat->width-1,0,0,1);
ds_source = (UINT8 *)pSplat->pic; ds->source = (UINT8 *)pSplat->pic;
ds_flatwidth = pSplat->width; ds->flatwidth = pSplat->width;
ds_flatheight = pSplat->height; ds->flatheight = pSplat->height;
if (R_CheckPowersOfTwo()) if (R_CheckPowersOfTwo(ds->flatwidth, ds->flatheight))
R_CheckFlatLength(ds_flatwidth * ds_flatheight); R_CheckFlatLength(ds, ds->flatwidth * ds->flatheight);
if (pSplat->slope) if (pSplat->slope)
{ {
R_SetTiltedSpan(0); R_SetTiltedSpan(ds, 0);
R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); R_SetScaledSlopePlane(pSplat->slope, ds, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
R_CalculateSlopeVectors(); R_CalculateSlopeVectors(ds);
spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
} }
else else
{ {
planeheight = abs(pSplat->z - vis->viewpoint.z); planecontext->planeheight = abs(pSplat->z - vis->viewpoint.z);
if (pSplat->angle) if (pSplat->angle)
{ {
memset(cachedheight, 0, sizeof(cachedheight)); memset(planecontext->cachedheight, 0, sizeof(planecontext->cachedheight));
// Add the view offset, rotated by the plane angle. // Add the view offset, rotated by the plane angle.
fixed_t a = -pSplat->verts[0].x + vis->viewpoint.x; fixed_t a = -pSplat->verts[0].x + vis->viewpoint.x;
@ -423,22 +411,22 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
} }
} }
ds_colormap = vis->colormap; ds->colormap = vis->colormap;
ds_translation = R_GetSpriteTranslation(vis); ds->translation = R_GetSpriteTranslation(vis);
if (ds_translation == NULL) if (ds->translation == NULL)
ds_translation = colormaps; ds->translation = colormaps;
if (vis->extra_colormap) if (vis->extra_colormap)
{ {
if (!ds_colormap) if (!ds->colormap)
ds_colormap = vis->extra_colormap->colormap; ds->colormap = vis->extra_colormap->colormap;
else else
ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; ds->colormap = &vis->extra_colormap->colormap[ds->colormap - colormaps];
} }
if (vis->transmap) if (vis->transmap)
{ {
ds_transmap = vis->transmap; ds->transmap = vis->transmap;
if (pSplat->slope) if (pSplat->slope)
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
@ -446,12 +434,12 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
spanfunctype = SPANDRAWFUNC_TRANSSPRITE; spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
} }
else else
ds_transmap = NULL; ds->transmap = NULL;
if (ds_powersoftwo) if (ds->powersoftwo)
spanfunc = spanfuncs[spanfunctype]; ds->func = spanfuncs[spanfunctype];
else else
spanfunc = spanfuncs_npo2[spanfunctype]; ds->func = spanfuncs_npo2[spanfunctype];
if (maxy >= vid.height) if (maxy >= vid.height)
maxy = vid.height-1; maxy = vid.height-1;
@ -460,8 +448,8 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
{ {
boolean cliptab[MAXVIDWIDTH+1]; boolean cliptab[MAXVIDWIDTH+1];
x1 = rastertab[y].minx>>FRACBITS; x1 = planecontext->rastertab[y].minx>>FRACBITS;
x2 = rastertab[y].maxx>>FRACBITS; x2 = planecontext->rastertab[y].maxx>>FRACBITS;
if (x1 > x2) if (x1 > x2)
{ {
@ -482,7 +470,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
continue; continue;
for (i = x1; i <= x2; i++) for (i = x1; i <= x2; i++)
cliptab[i] = (y >= mfloorclip[i]); cliptab[i] = (y >= dc->mfloorclip[i]);
// clip left // clip left
while (cliptab[x1]) while (cliptab[x1])
@ -516,10 +504,10 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
angle_t planecos = FINECOSINE(angle); angle_t planecos = FINECOSINE(angle);
angle_t planesin = FINESINE(angle); angle_t planesin = FINESINE(angle);
if (planeheight != cachedheight[y]) if (planecontext->planeheight != planecontext->cachedheight[y])
{ {
cachedheight[y] = planeheight; planecontext->cachedheight[y] = planeheight;
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); distance = planecontext->cacheddistance[y] = FixedMul(planeheight, yslope[y]);
span = abs(centery - y); span = abs(centery - y);
if (span) // Don't divide by zero if (span) // Don't divide by zero
@ -530,43 +518,43 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
else else
xstep = ystep = FRACUNIT; xstep = ystep = FRACUNIT;
cachedxstep[y] = xstep; planecontext->cachedxstep[y] = xstep;
cachedystep[y] = ystep; planecontext->cachedystep[y] = ystep;
} }
else else
{ {
distance = cacheddistance[y]; distance = planecontext->cacheddistance[y];
xstep = cachedxstep[y]; xstep = planecontext->cachedxstep[y];
ystep = cachedystep[y]; ystep = planecontext->cachedystep[y];
} }
ds_xstep = FixedDiv(xstep, pSplat->xscale); ds->xstep = FixedDiv(xstep, pSplat->xscale);
ds_ystep = FixedDiv(ystep, pSplat->yscale); ds->ystep = FixedDiv(ystep, pSplat->yscale);
ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale); ds->xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale);
ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); ds->yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale);
} }
ds_y = y; ds->y = y;
ds_x1 = x1; ds->x1 = x1;
ds_x2 = x2; ds->x2 = x2;
spanfunc(); ds->func(ds);
rastertab[y].minx = INT32_MAX; planecontext->rastertab[y].minx = INT32_MAX;
rastertab[y].maxx = INT32_MIN; planecontext->rastertab[y].maxx = INT32_MIN;
} }
if (pSplat->angle && !pSplat->slope) if (pSplat->angle && !pSplat->slope)
memset(cachedheight, 0, sizeof(cachedheight)); memset(planecontext->cachedheight, 0, sizeof(planecontext->cachedheight));
} }
static void prepare_rastertab(void) static void prepare_rastertab(planecontext_t *planecontext)
{ {
INT32 i; INT32 i;
prastertab = rastertab; planecontext->prastertab = planecontext->rastertab;
for (i = 0; i < vid.height; i++) for (i = 0; i < vid.height; i++)
{ {
rastertab[i].minx = INT32_MAX; planecontext->rastertab[i].minx = INT32_MAX;
rastertab[i].maxx = INT32_MIN; planecontext->rastertab[i].maxx = INT32_MIN;
} }
} }

View file

@ -26,7 +26,6 @@ struct rastery_s
fixed_t tx1, ty1; // start points in texture at this line fixed_t tx1, ty1; // start points in texture at this line
fixed_t tx2, ty2; // end points in texture at this line fixed_t tx2, ty2; // end points in texture at this line
}; };
extern struct rastery_s *prastertab; // for ASM code
typedef struct floorsplat_s typedef struct floorsplat_s
{ {
@ -41,6 +40,8 @@ typedef struct floorsplat_s
mobj_t *mobj; // Mobj it is tied to mobj_t *mobj; // Mobj it is tied to
} floorsplat_t; } floorsplat_t;
void R_DrawFloorSplat(vissprite_t *spr); struct rendercontext_s;
void R_DrawFloorSplat(struct rendercontext_s *context, vissprite_t *spr);
#endif /*__R_SPLATS_H__*/ #endif /*__R_SPLATS_H__*/

View file

@ -90,6 +90,8 @@ extern sector_t *viewsector;
extern player_t *viewplayer; extern player_t *viewplayer;
extern mobj_t *r_viewmobj; extern mobj_t *r_viewmobj;
extern consvar_t cv_numthreads;
extern consvar_t cv_allowmlook; extern consvar_t cv_allowmlook;
extern consvar_t cv_maxportals; extern consvar_t cv_maxportals;
@ -99,10 +101,4 @@ extern angle_t doubleclipangle;
extern INT32 viewangletox[FINEANGLES/2]; extern INT32 viewangletox[FINEANGLES/2];
extern angle_t xtoviewangle[MAXVIDWIDTH+1]; extern angle_t xtoviewangle[MAXVIDWIDTH+1];
extern fixed_t rw_distance;
extern angle_t rw_normalangle;
// angle to line origin
extern angle_t rw_angle1;
#endif #endif

View file

@ -34,6 +34,15 @@
#include <errno.h> #include <errno.h>
#ifdef HAVE_THREADS
static I_mutex r_texture_mutex;
# define Lock_state() I_lock_mutex(&r_texture_mutex)
# define Unlock_state() I_unlock_mutex(r_texture_mutex)
#else
# define Lock_state()
# define Unlock_state()
#endif
// //
// TEXTURE_T CACHING // TEXTURE_T CACHING
// When a texture is first needed, it counts the number of composite columns // When a texture is first needed, it counts the number of composite columns
@ -508,8 +517,10 @@ INT32 R_GetTextureNum(INT32 texnum)
// //
void R_CheckTextureCache(INT32 tex) void R_CheckTextureCache(INT32 tex)
{ {
Lock_state();
if (!texturecache[tex]) if (!texturecache[tex])
R_GenerateTexture(tex); R_GenerateTexture(tex);
Unlock_state();
} }
// //
@ -525,9 +536,11 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col)
else else
col &= (width - 1); col &= (width - 1);
Lock_state();
data = texturecache[tex]; data = texturecache[tex];
if (!data) if (!data)
data = R_GenerateTexture(tex); data = R_GenerateTexture(tex);
Unlock_state();
return data + LONG(texturecolumnofs[tex][col]); return data + LONG(texturecolumnofs[tex][col]);
} }
@ -542,7 +555,7 @@ void *R_GetFlat(lumpnum_t flatlumpnum)
// //
// If needed, convert a texture or patch to a flat. // If needed, convert a texture or patch to a flat.
// //
void *R_GetLevelFlat(levelflat_t *levelflat) void *R_GetLevelFlat(levelflat_t *levelflat, UINT16 *flatwidth, UINT16 *flatheight)
{ {
boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE); boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE);
texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL); texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL);
@ -555,8 +568,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
if (texture->flat) if (texture->flat)
{ {
flatdata = texture->flat; flatdata = texture->flat;
ds_flatwidth = texture->width; *flatwidth = texture->width;
ds_flatheight = texture->height; *flatheight = texture->height;
texturechanged = false; texturechanged = false;
} }
else else
@ -566,12 +579,14 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
// If the texture changed, or the flat wasn't generated, convert. // If the texture changed, or the flat wasn't generated, convert.
if (levelflat->picture == NULL || texturechanged) if (levelflat->picture == NULL || texturechanged)
{ {
Lock_state();
// Level texture // Level texture
if (isleveltexture) if (isleveltexture)
{ {
levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num); levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num);
ds_flatwidth = levelflat->width = texture->width; *flatwidth = levelflat->width = texture->width;
ds_flatheight = levelflat->height = texture->height; *flatheight = levelflat->height = texture->height;
} }
else else
{ {
@ -584,8 +599,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
levelflat->width = (UINT16)pngwidth; levelflat->width = (UINT16)pngwidth;
levelflat->height = (UINT16)pngheight; levelflat->height = (UINT16)pngheight;
ds_flatwidth = levelflat->width; *flatwidth = levelflat->width;
ds_flatheight = levelflat->height; *flatheight = levelflat->height;
} }
else else
#endif #endif
@ -595,8 +610,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
size_t size; size_t size;
softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = ds_flatwidth = SHORT(patch->width); levelflat->width = *flatwidth = SHORT(patch->width);
levelflat->height = ds_flatheight = SHORT(patch->height); levelflat->height = *flatheight = SHORT(patch->height);
levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL);
converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, SHORT(patch->topoffset), SHORT(patch->leftoffset), 0); converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, SHORT(patch->topoffset), SHORT(patch->leftoffset), 0);
@ -604,11 +619,13 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
Z_Free(converted); Z_Free(converted);
} }
} }
Unlock_state();
} }
else else
{ {
ds_flatwidth = levelflat->width; *flatwidth = levelflat->width;
ds_flatheight = levelflat->height; *flatheight = levelflat->height;
} }
levelflat->u.texture.lastnum = levelflat->u.texture.num; levelflat->u.texture.lastnum = levelflat->u.texture.num;
@ -621,23 +638,14 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
// //
// R_CheckPowersOfTwo // R_CheckPowersOfTwo
// //
// Sets ds_powersoftwo true if the flat's dimensions are powers of two, and returns that. // Checks if the flat's dimensions are powers of two.
// //
boolean R_CheckPowersOfTwo(void) boolean R_CheckPowersOfTwo(UINT16 flatwidth, UINT16 flatheight)
{ {
boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1))); boolean wpow2 = (!(flatwidth & (flatwidth - 1)));
boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1))); boolean hpow2 = (!(flatheight & (flatheight - 1)));
// Initially, the flat isn't powers-of-two-sized. return ((flatwidth == flatheight) && (wpow2 && hpow2));
ds_powersoftwo = false;
// But if the width and height are powers of two,
// and are EQUAL, then it's okay :]
if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2))
ds_powersoftwo = true;
// Just return ds_powersoftwo.
return ds_powersoftwo;
} }
// //
@ -645,58 +653,58 @@ boolean R_CheckPowersOfTwo(void)
// //
// Determine the flat's dimensions from its lump length. // Determine the flat's dimensions from its lump length.
// //
void R_CheckFlatLength(size_t size) void R_CheckFlatLength(spancontext_t *ds, size_t size)
{ {
switch (size) switch (size)
{ {
case 4194304: // 2048x2048 lump case 4194304: // 2048x2048 lump
nflatmask = 0x3FF800; ds->nflatmask = 0x3FF800;
nflatxshift = 21; ds->nflatxshift = 21;
nflatyshift = 10; ds->nflatyshift = 10;
nflatshiftup = 5; ds->nflatshiftup = 5;
ds_flatwidth = ds_flatheight = 2048; ds->flatwidth = ds->flatheight = 2048;
break; break;
case 1048576: // 1024x1024 lump case 1048576: // 1024x1024 lump
nflatmask = 0xFFC00; ds->nflatmask = 0xFFC00;
nflatxshift = 22; ds->nflatxshift = 22;
nflatyshift = 12; ds->nflatyshift = 12;
nflatshiftup = 6; ds->nflatshiftup = 6;
ds_flatwidth = ds_flatheight = 1024; ds->flatwidth = ds->flatheight = 1024;
break; break;
case 262144:// 512x512 lump case 262144:// 512x512 lump
nflatmask = 0x3FE00; ds->nflatmask = 0x3FE00;
nflatxshift = 23; ds->nflatxshift = 23;
nflatyshift = 14; ds->nflatyshift = 14;
nflatshiftup = 7; ds->nflatshiftup = 7;
ds_flatwidth = ds_flatheight = 512; ds->flatwidth = ds->flatheight = 512;
break; break;
case 65536: // 256x256 lump case 65536: // 256x256 lump
nflatmask = 0xFF00; ds->nflatmask = 0xFF00;
nflatxshift = 24; ds->nflatxshift = 24;
nflatyshift = 16; ds->nflatyshift = 16;
nflatshiftup = 8; ds->nflatshiftup = 8;
ds_flatwidth = ds_flatheight = 256; ds->flatwidth = ds->flatheight = 256;
break; break;
case 16384: // 128x128 lump case 16384: // 128x128 lump
nflatmask = 0x3F80; ds->nflatmask = 0x3F80;
nflatxshift = 25; ds->nflatxshift = 25;
nflatyshift = 18; ds->nflatyshift = 18;
nflatshiftup = 9; ds->nflatshiftup = 9;
ds_flatwidth = ds_flatheight = 128; ds->flatwidth = ds->flatheight = 128;
break; break;
case 1024: // 32x32 lump case 1024: // 32x32 lump
nflatmask = 0x3E0; ds->nflatmask = 0x3E0;
nflatxshift = 27; ds->nflatxshift = 27;
nflatyshift = 22; ds->nflatyshift = 22;
nflatshiftup = 11; ds->nflatshiftup = 11;
ds_flatwidth = ds_flatheight = 32; ds->flatwidth = ds->flatheight = 32;
break; break;
default: // 64x64 lump default: // 64x64 lump
nflatmask = 0xFC0; ds->nflatmask = 0xFC0;
nflatxshift = 26; ds->nflatxshift = 26;
nflatyshift = 20; ds->nflatyshift = 20;
nflatshiftup = 10; ds->nflatshiftup = 10;
ds_flatwidth = ds_flatheight = 64; ds->flatwidth = ds->flatheight = 64;
break; break;
} }
} }

View file

@ -18,6 +18,7 @@
#include "r_state.h" #include "r_state.h"
#include "p_setup.h" // levelflats #include "p_setup.h" // levelflats
#include "r_data.h" #include "r_data.h"
#include "r_draw.h"
#ifdef __GNUG__ #ifdef __GNUG__
#pragma interface #pragma interface
@ -86,12 +87,12 @@ void R_CheckTextureCache(INT32 tex);
void R_ClearTextureNumCache(boolean btell); void R_ClearTextureNumCache(boolean btell);
// Retrieve texture data. // Retrieve texture data.
void *R_GetLevelFlat(levelflat_t *levelflat); void *R_GetLevelFlat(levelflat_t *levelflat, UINT16 *flatwidth, UINT16 *flatheight);
UINT8 *R_GetColumn(fixed_t tex, INT32 col); UINT8 *R_GetColumn(fixed_t tex, INT32 col);
void *R_GetFlat(lumpnum_t flatnum); void *R_GetFlat(lumpnum_t flatnum);
boolean R_CheckPowersOfTwo(void); boolean R_CheckPowersOfTwo(UINT16 flatwidth, UINT16 flatheight);
void R_CheckFlatLength(size_t size); void R_CheckFlatLength(spancontext_t *ds, size_t size);
// Returns the texture number for the texture name. // Returns the texture number for the texture name.
INT32 R_TextureNumForName(const char *name); INT32 R_TextureNumForName(const char *name);

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
#define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef #define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef
void R_InitSprites(void);
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump); boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
//faB: find sprites in wadfile, replace existing, add new ones //faB: find sprites in wadfile, replace existing, add new ones
@ -37,23 +38,16 @@ void R_AddSpriteDefs(UINT16 wadnum);
// MASKED COLUMN DRAWING // MASKED COLUMN DRAWING
// --------------------- // ---------------------
// vars for R_DrawMaskedColumn void R_DrawMaskedColumn(colcontext_t *dc, column_t *column);
extern INT16 *mfloorclip; void R_DrawFlippedMaskedColumn(colcontext_t *dc, column_t *column);
extern INT16 *mceilingclip;
extern fixed_t spryscale;
extern fixed_t sprtopscreen;
extern fixed_t sprbotscreen;
extern fixed_t windowtop;
extern fixed_t windowbottom;
extern INT32 lengthcol;
void R_DrawMaskedColumn(column_t *column);
void R_DrawFlippedMaskedColumn(column_t *column);
// ---------------- // ----------------
// SPRITE RENDERING // SPRITE RENDERING
// ---------------- // ----------------
struct rendercontext_s;
struct spritecontext_s;
// Constant arrays used for psprite clipping // Constant arrays used for psprite clipping
// and initializing clipping. // and initializing clipping.
extern INT16 negonearray[MAXVIDWIDTH]; extern INT16 negonearray[MAXVIDWIDTH];
@ -62,17 +56,18 @@ extern INT16 screenheightarray[MAXVIDWIDTH];
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
//SoM: 6/5/2000: Light sprites correctly! //SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddSprites(struct rendercontext_s *context, sector_t *sec, INT32 lightlevel);
void R_InitSprites(void); void R_ClearSprites(struct spritecontext_s *spritecontext);
void R_ClearSprites(void);
boolean R_ThingVisible (mobj_t *thing); boolean R_ThingVisible (mobj_t *thing, mobj_t *viewmobj);
boolean R_ThingVisibleWithinDist (mobj_t *thing, boolean R_ThingVisibleWithinDist (fixed_t viewpos_x, fixed_t viewpos_y,
mobj_t *thing, mobj_t *viewmobj,
fixed_t draw_dist, fixed_t draw_dist,
fixed_t nights_draw_dist); fixed_t nights_draw_dist);
boolean R_PrecipThingVisible (precipmobj_t *precipthing, boolean R_PrecipThingVisible (fixed_t viewpos_x, fixed_t viewpos_y,
precipmobj_t *precipthing,
fixed_t precip_draw_dist); fixed_t precip_draw_dist);
boolean R_ThingHorizontallyFlipped (mobj_t *thing); boolean R_ThingHorizontallyFlipped (mobj_t *thing);
@ -99,7 +94,7 @@ typedef struct
sector_t* viewsector; sector_t* viewsector;
} maskcount_t; } maskcount_t;
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks); void R_DrawMasked(struct rendercontext_s *context, maskcount_t *masks, UINT8 nummasks);
// ---------- // ----------
// VISSPRITES // VISSPRITES
@ -210,10 +205,7 @@ typedef struct vissprite_s
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} vissprite_t; } vissprite_t;
extern UINT32 visspritecount; void R_ClipSprites(struct rendercontext_s *context, drawseg_t* dsstart, portal_t* portal);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal);
boolean R_SpriteIsFlashing(vissprite_t *vis); boolean R_SpriteIsFlashing(vissprite_t *vis);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis); UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
@ -236,7 +228,7 @@ typedef struct drawnode_s
struct drawnode_s *prev; struct drawnode_s *prev;
} drawnode_t; } drawnode_t;
void R_InitDrawNodes(void); void R_InitDrawNodes(drawnode_t *nodebankhead);
// ----------------------- // -----------------------
// SPRITE FRAME CHARACTERS // SPRITE FRAME CHARACTERS

View file

@ -39,20 +39,13 @@
#include "hardware/hw_model.h" #include "hardware/hw_model.h"
#endif #endif
#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
#define RUSEASM //MSC.NET can't patch itself
#endif
// -------------------------------------------- // --------------------------------------------
// assembly or c drawer routines for 8bpp/16bpp // assembly or c drawer routines for 8bpp/16bpp
// -------------------------------------------- // --------------------------------------------
void (*colfunc)(void); colfunc_t colfuncs[COLDRAWFUNC_MAX];
void (*colfuncs[COLDRAWFUNC_MAX])(void);
void (*spanfunc)(void); spanfunc_t spanfuncs[SPANDRAWFUNC_MAX];
void (*spanfuncs[SPANDRAWFUNC_MAX])(void); spanfunc_t spanfuncs_npo2[SPANDRAWFUNC_MAX];
void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
// ------------------ // ------------------
// global video state // global video state
@ -106,17 +99,10 @@ boolean R_SSE2 = false;
void SCR_SetDrawFuncs(void) void SCR_SetDrawFuncs(void)
{ {
// // Always run in 8bpp. todo: remove all 16bpp code?
// setup the right draw routines for either 8bpp or 16bpp
//
if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code?
{
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8; colfuncs[BASEDRAWFUNC] = R_DrawColumn_8;
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8; spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8;
colfunc = colfuncs[BASEDRAWFUNC];
spanfunc = spanfuncs[BASEDRAWFUNC];
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8; colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8; colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8;
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
@ -154,47 +140,6 @@ void SCR_SetDrawFuncs(void)
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed
#ifdef RUSEASM
if (R_ASM)
{
if (R_MMX)
{
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_MMX;
//colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
//colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX;
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8_MMX;
}
else
{
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_ASM;
//colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
//colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM;
}
}
#endif
}
/* else if (vid.bpp > 1)
{
I_OutputMsg("using highcolor mode\n");
spanfunc = basespanfunc = R_DrawSpan_16;
transcolfunc = R_DrawTranslatedColumn_16;
transtransfunc = R_DrawTranslucentColumn_16; // No 16bit operation for this function
colfunc = basecolfunc = R_DrawColumn_16;
shadecolfunc = NULL; // detect error if used somewhere..
fuzzcolfunc = R_DrawTranslucentColumn_16;
walldrawerfunc = R_DrawWallColumn_16;
}*/
else
I_Error("unknown bytes per pixel mode %d\n", vid.bpp);
/*
if (SCR_IsAspectCorrect(vid.width, vid.height))
CONS_Alert(CONS_WARNING, M_GetText("Resolution is not aspect-correct!\nUse a multiple of %dx%d\n"), BASEVIDWIDTH, BASEVIDHEIGHT);
*/
} }
void SCR_SetMode(void) void SCR_SetMode(void)

View file

@ -112,58 +112,6 @@ typedef struct vmode_s
#define NUMSPECIALMODES 4 #define NUMSPECIALMODES 4
extern vmode_t specialmodes[NUMSPECIALMODES]; extern vmode_t specialmodes[NUMSPECIALMODES];
// ---------------------------------------------
// color mode dependent drawer function pointers
// ---------------------------------------------
#define BASEDRAWFUNC 0
enum
{
COLDRAWFUNC_BASE = BASEDRAWFUNC,
COLDRAWFUNC_FUZZY,
COLDRAWFUNC_TRANS,
COLDRAWFUNC_SHADE,
COLDRAWFUNC_SHADOWED,
COLDRAWFUNC_TRANSTRANS,
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG,
COLDRAWFUNC_MAX
};
extern void (*colfunc)(void);
extern void (*colfuncs[COLDRAWFUNC_MAX])(void);
enum
{
SPANDRAWFUNC_BASE = BASEDRAWFUNC,
SPANDRAWFUNC_TRANS,
SPANDRAWFUNC_TILTED,
SPANDRAWFUNC_TILTEDTRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_TILTEDSPLAT,
SPANDRAWFUNC_SPRITE,
SPANDRAWFUNC_TRANSSPRITE,
SPANDRAWFUNC_TILTEDSPRITE,
SPANDRAWFUNC_TILTEDTRANSSPRITE,
SPANDRAWFUNC_WATER,
SPANDRAWFUNC_TILTEDWATER,
SPANDRAWFUNC_FOG,
SPANDRAWFUNC_MAX
};
extern void (*spanfunc)(void);
extern void (*spanfuncs[SPANDRAWFUNC_MAX])(void);
extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
// ----- // -----
// CPUID // CPUID
// ----- // -----

View file

@ -128,11 +128,9 @@ if(${SDL2_FOUND})
if(${SRB2_CONFIG_YASM}) if(${SRB2_CONFIG_YASM})
set(ASM_ASSEMBLER_TEMP ${CMAKE_ASM_YASM_COMPILER}) set(ASM_ASSEMBLER_TEMP ${CMAKE_ASM_YASM_COMPILER})
set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_YASM_OBJECT_FORMAT}) set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_YASM_OBJECT_FORMAT})
set_source_files_properties(${SRB2_NASM_SOURCES} LANGUAGE ASM_YASM)
else() else()
set(ASM_ASSEMBLER_TEMP ${CMAKE_ASM_NASM_COMPILER}) set(ASM_ASSEMBLER_TEMP ${CMAKE_ASM_NASM_COMPILER})
set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_NASM_OBJECT_FORMAT}) set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_NASM_OBJECT_FORMAT})
set_source_files_properties(${SRB2_NASM_SOURCES} LANGUAGE ASM_NASM)
endif() endif()
endif() endif()

View file

@ -177,6 +177,7 @@ static char returnWadPath[256];
#include "../screen.h" //vid.WndParent #include "../screen.h" //vid.WndParent
#include "../d_net.h" #include "../d_net.h"
#include "../g_game.h" #include "../g_game.h"
#include "../r_main.h"
#include "../filesrch.h" #include "../filesrch.h"
#include "endtxt.h" #include "endtxt.h"
#include "sdlmain.h" #include "sdlmain.h"
@ -2272,6 +2273,7 @@ INT32 I_StartupSystem(void)
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_start_threads(); I_start_threads();
I_AddExitFunc(I_stop_threads); I_AddExitFunc(I_stop_threads);
I_AddExitFunc(R_StopThreads);
#endif #endif
I_StartupConsole(); I_StartupConsole();
#ifdef NEWSIGNALHANDLER #ifdef NEWSIGNALHANDLER

View file

@ -155,7 +155,7 @@ Worker (
return 0; return 0;
} }
void I_thread_handle
I_spawn_thread ( I_spawn_thread (
const char * name, const char * name,
I_thread_fn entry, I_thread_fn entry,
@ -189,6 +189,7 @@ I_spawn_thread (
} }
} }
I_unlock_mutex(i_thread_pool_mutex); I_unlock_mutex(i_thread_pool_mutex);
return (I_thread_handle)th;
} }
int int
@ -354,3 +355,18 @@ I_wake_all_cond (
if (SDL_CondBroadcast(cond) == -1) if (SDL_CondBroadcast(cond) == -1)
abort(); abort();
} }
INT32
I_atomic_load (
I_Atomicptr_t atomic
){
return SDL_AtomicGet(atomic);
}
INT32
I_atomic_exchange (
I_Atomicptr_t atomic,
INT32 val
){
return SDL_AtomicSet(atomic, val);
}

View file

@ -1,957 +0,0 @@
;; SONIC ROBO BLAST 2
;;-----------------------------------------------------------------------------
;; Copyright (C) 1998-2000 by DooM Legacy Team.
;; Copyright (C) 1999-2021 by Sonic Team Junior.
;;
;; This program is free software distributed under the
;; terms of the GNU General Public License, version 2.
;; See the 'LICENSE' file for more details.
;;-----------------------------------------------------------------------------
;; FILE:
;; tmap.nas
;; DESCRIPTION:
;; Assembler optimised rendering code for software mode.
;; Draw wall columns.
[BITS 32]
%define FRACBITS 16
%define TRANSPARENTPIXEL 255
%ifdef LINUX
%macro cextern 1
[extern %1]
%endmacro
%macro cglobal 1
[global %1]
%endmacro
%else
%macro cextern 1
%define %1 _%1
[extern %1]
%endmacro
%macro cglobal 1
%define %1 _%1
[global %1]
%endmacro
%endif
; The viddef_s structure. We only need the width field.
struc viddef_s
resb 12
.width: resb 4
resb 44
endstruc
;; externs
;; columns
cextern dc_x
cextern dc_yl
cextern dc_yh
cextern ylookup
cextern columnofs
cextern dc_source
cextern dc_texturemid
cextern dc_texheight
cextern dc_iscale
cextern dc_hires
cextern centery
cextern centeryfrac
cextern dc_colormap
cextern dc_transmap
cextern colormaps
cextern vid
cextern topleft
; DELME
cextern R_DrawColumn_8
; polygon edge rasterizer
cextern prastertab
[SECTION .data]
;;.align 4
loopcount dd 0
pixelcount dd 0
tystep dd 0
[SECTION .text]
;;----------------------------------------------------------------------
;;
;; R_DrawColumn : 8bpp column drawer
;;
;; New optimised version 10-01-1998 by D.Fabrice and P.Boris
;; Revised by G. Dick July 2010 to support the intervening twelve years'
;; worth of changes to the renderer. Since I only vaguely know what I'm
;; doing, this is probably rather suboptimal. Help appreciated!
;;
;;----------------------------------------------------------------------
;; fracstep, vid.width in memory
;; eax = accumulator
;; ebx = colormap
;; ecx = count
;; edx = heightmask
;; esi = source
;; edi = dest
;; ebp = frac
;;----------------------------------------------------------------------
cglobal R_DrawColumn_8_ASM
; align 16
R_DrawColumn_8_ASM:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov ebp,[dc_yl]
mov edi,[ylookup+ebp*4]
mov ebx,[dc_x]
add edi,[columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov ecx,[dc_yh]
add ecx,1
sub ecx,ebp ;; pixel count
jle near .done ;; nothing to scale
;;
;; fracstep = dc_iscale; // But we just use [dc_iscale]
;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
;;
mov eax,ebp ;; dc_yl
shl eax,FRACBITS
sub eax,[centeryfrac]
imul dword [dc_iscale]
shrd eax,edx,FRACBITS
add eax,[dc_texturemid]
mov ebp,eax ;; ebp = frac
mov ebx,[dc_colormap]
mov esi,[dc_source]
;;
;; if (dc_hires) frac = 0;
;;
test byte [dc_hires],0x01
jz .texheightcheck
xor ebp,ebp
;;
;; Check for power of two
;;
.texheightcheck:
mov edx,[dc_texheight]
sub edx,1 ;; edx = heightmask
test edx,[dc_texheight]
jnz .notpowertwo
test ecx,0x01 ;; Test for odd no. pixels
jnz .odd
;;
;; Texture height is a power of two, so we get modular arithmetic by
;; masking
;;
.powertwo:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part
and eax,edx ;; eax &= heightmask
movzx eax,byte [esi + eax] ;; eax = texel
add ebp,[dc_iscale] ;; frac += fracstep
movzx eax,byte [ebx+eax] ;; Map through colormap
mov [edi],al ;; Write pixel
;; dest += vid.width
add edi,[vid + viddef_s.width]
.odd:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part
and eax,edx ;; eax &= heightmask
movzx eax,byte [esi + eax] ;; eax = texel
add ebp,[dc_iscale] ;; frac += fracstep
movzx eax,byte [ebx+eax] ;; Map through colormap
mov [edi],al ;; Write pixel
;; dest += vid.width
add edi,[vid + viddef_s.width]
sub ecx,2 ;; count -= 2
jg .powertwo
jmp .done
.notpowertwo:
add edx,1
shl edx,FRACBITS
test ebp,ebp
jns .notpowtwoloop
.makefracpos:
add ebp,edx ;; frac is negative; make it positive
js .makefracpos
.notpowtwoloop:
cmp ebp,edx ;; Reduce mod height
jl .writenonpowtwo
sub ebp,edx
jmp .notpowtwoloop
.writenonpowtwo:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part.
mov bl,[esi + eax] ;; ebx = colormap + texel
add ebp,[dc_iscale] ;; frac += fracstep
movzx eax,byte [ebx] ;; Map through colormap
mov [edi],al ;; Write pixel
;; dest += vid.width
add edi,[vid + viddef_s.width]
sub ecx,1
jnz .notpowtwoloop
;;
.done:
pop ebx ;; restore register variables
pop edi
pop esi
pop ebp ;; restore caller's stack frame pointer
ret
;;----------------------------------------------------------------------
;;
;; R_Draw2sMultiPatchColumn : Like R_DrawColumn, but omits transparent
;; pixels.
;;
;; New optimised version 10-01-1998 by D.Fabrice and P.Boris
;; Revised by G. Dick July 2010 to support the intervening twelve years'
;; worth of changes to the renderer. Since I only vaguely know what I'm
;; doing, this is probably rather suboptimal. Help appreciated!
;;
;;----------------------------------------------------------------------
;; fracstep, vid.width in memory
;; eax = accumulator
;; ebx = colormap
;; ecx = count
;; edx = heightmask
;; esi = source
;; edi = dest
;; ebp = frac
;;----------------------------------------------------------------------
cglobal R_Draw2sMultiPatchColumn_8_ASM
; align 16
R_Draw2sMultiPatchColumn_8_ASM:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov ebp,[dc_yl]
mov edi,[ylookup+ebp*4]
mov ebx,[dc_x]
add edi,[columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov ecx,[dc_yh]
add ecx,1
sub ecx,ebp ;; pixel count
jle near .done ;; nothing to scale
;;
;; fracstep = dc_iscale; // But we just use [dc_iscale]
;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
;;
mov eax,ebp ;; dc_yl
shl eax,FRACBITS
sub eax,[centeryfrac]
imul dword [dc_iscale]
shrd eax,edx,FRACBITS
add eax,[dc_texturemid]
mov ebp,eax ;; ebp = frac
mov ebx,[dc_colormap]
mov esi,[dc_source]
;;
;; if (dc_hires) frac = 0;
;;
test byte [dc_hires],0x01
jz .texheightcheck
xor ebp,ebp
;;
;; Check for power of two
;;
.texheightcheck:
mov edx,[dc_texheight]
sub edx,1 ;; edx = heightmask
test edx,[dc_texheight]
jnz .notpowertwo
test ecx,0x01 ;; Test for odd no. pixels
jnz .odd
;;
;; Texture height is a power of two, so we get modular arithmetic by
;; masking
;;
.powertwo:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part
and eax,edx ;; eax &= heightmask
movzx eax,byte [esi + eax] ;; eax = texel
add ebp,[dc_iscale] ;; frac += fracstep
cmp al,TRANSPARENTPIXEL ;; Is pixel transparent?
je .nextpowtwoeven ;; If so, advance.
movzx eax,byte [ebx+eax] ;; Map through colormap
mov [edi],al ;; Write pixel
.nextpowtwoeven:
;; dest += vid.width
add edi,[vid + viddef_s.width]
.odd:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part
and eax,edx ;; eax &= heightmask
movzx eax,byte [esi + eax] ;; eax = texel
add ebp,[dc_iscale] ;; frac += fracstep
cmp al,TRANSPARENTPIXEL ;; Is pixel transparent?
je .nextpowtwoodd ;; If so, advance.
movzx eax,byte [ebx+eax] ;; Map through colormap
mov [edi],al ;; Write pixel
.nextpowtwoodd:
;; dest += vid.width
add edi,[vid + viddef_s.width]
sub ecx,2 ;; count -= 2
jg .powertwo
jmp .done
.notpowertwo:
add edx,1
shl edx,FRACBITS
test ebp,ebp
jns .notpowtwoloop
.makefracpos:
add ebp,edx ;; frac is negative; make it positive
js .makefracpos
.notpowtwoloop:
cmp ebp,edx ;; Reduce mod height
jl .writenonpowtwo
sub ebp,edx
jmp .notpowtwoloop
.writenonpowtwo:
mov eax,ebp ;; eax = frac
sar eax,FRACBITS ;; Integer part.
mov bl,[esi + eax] ;; ebx = colormap + texel
add ebp,[dc_iscale] ;; frac += fracstep
cmp bl,TRANSPARENTPIXEL ;; Is pixel transparent?
je .nextnonpowtwo ;; If so, advance.
movzx eax,byte [ebx] ;; Map through colormap
mov [edi],al ;; Write pixel
.nextnonpowtwo:
;; dest += vid.width
add edi,[vid + viddef_s.width]
sub ecx,1
jnz .notpowtwoloop
;;
.done:
pop ebx ;; restore register variables
pop edi
pop esi
pop ebp ;; restore caller's stack frame pointer
ret
;;----------------------------------------------------------------------
;; R_DrawTranslucentColumnA_8
;;
;; Vertical column texture drawer, with transparency. Replaces Doom2's
;; 'fuzz' effect, which was not so beautiful.
;; Transparency is always impressive in some way, don't know why...
;;----------------------------------------------------------------------
cglobal R_DrawTranslucentColumn_8_ASM
R_DrawTranslucentColumn_8_ASM:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov ebp,[dc_yl]
mov ebx,ebp
mov edi,[ylookup+ebx*4]
mov ebx,[dc_x]
add edi,[columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov eax,[dc_yh]
inc eax
sub eax,ebp ;; pixel count
mov [pixelcount],eax ;; save for final pixel
jle near vtdone ;; nothing to scale
;;
;; frac = dc_texturemid - (centery-dc_yl)*fracstep;
;;
mov ecx,[dc_iscale] ;; fracstep
mov eax,[centery]
sub eax,ebp
imul eax,ecx
mov edx,[dc_texturemid]
sub edx,eax
mov ebx,edx
shr ebx,16 ;; frac int.
and ebx,0x7f
shl edx,16 ;; y frac up
mov ebp,ecx
shl ebp,16 ;; fracstep f. up
shr ecx,16 ;; fracstep i. ->cl
and cl,0x7f
push cx
mov ecx,edx
pop cx
mov edx,[dc_colormap]
mov esi,[dc_source]
;;
;; lets rock :) !
;;
mov eax,[pixelcount]
shr eax,0x2
test byte [pixelcount],0x3
mov ch,al ;; quad count
mov eax,[dc_transmap]
je vt4quadloop
;;
;; do un-even pixel
;;
test byte [pixelcount],0x1
je trf2
mov ah,[esi+ebx] ;; fetch texel : colormap number
add ecx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov dl,[edx]
mov [edi],dl
pf: add edi,0x12345678
;;
;; do two non-quad-aligned pixels
;;
trf2: test byte [pixelcount],0x2
je trf3
mov ah,[esi+ebx] ;; fetch texel : colormap number
add ecx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov dl,[edx]
mov [edi],dl
pg: add edi,0x12345678
mov ah,[esi+ebx] ;; fetch texel : colormap number
add ecx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov dl,[edx]
mov [edi],dl
ph: add edi,0x12345678
;;
;; test if there was at least 4 pixels
;;
trf3: test ch,0xff ;; test quad count
je near vtdone
;;
;; ebp : ystep frac. upper 24 bits
;; edx : y frac. upper 24 bits
;; ebx : y i. lower 7 bits, masked for index
;; ecx : ch = counter, cl = y step i.
;; eax : colormap aligned 256
;; esi : source texture column
;; edi : dest screen
;;
vt4quadloop:
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [tystep],ebp
pi: add edi,0x12345678
mov al,[edi] ;; fetch dest : index into colormap
pj: sub edi,0x12345678
mov ebp,edi
pk: sub edi,0x12345678
jmp short inloop
align 4
vtquadloop:
add ecx,[tystep]
adc bl,cl
q1: add ebp,0x23456789
and bl,0x7f
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov dl,[edx]
mov [edi],dl
mov al,[ebp] ;; fetch dest : index into colormap
inloop:
add ecx,[tystep]
adc bl,cl
q2: add edi,0x23456789
and bl,0x7f
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov dl,[edx]
mov [ebp+0x0],dl
mov al,[edi] ;; fetch dest : index into colormap
add ecx,[tystep]
adc bl,cl
q3: add ebp,0x23456789
and bl,0x7f
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov dl,[edx]
mov [edi],dl
mov al,[ebp] ;; fetch dest : index into colormap
add ecx,[tystep]
adc bl,cl
q4: add edi,0x23456789
and bl,0x7f
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov dl,[edx]
mov [ebp],dl
mov al,[edi] ;; fetch dest : index into colormap
dec ch
jne vtquadloop
vtdone:
pop ebx
pop edi
pop esi
pop ebp
ret
;;----------------------------------------------------------------------
;; R_DrawShadeColumn
;;
;; for smoke..etc.. test.
;;----------------------------------------------------------------------
cglobal R_DrawShadeColumn_8_ASM
R_DrawShadeColumn_8_ASM:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov ebp,[dc_yl]
mov ebx,ebp
mov edi,[ylookup+ebx*4]
mov ebx,[dc_x]
add edi,[columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov eax,[dc_yh]
inc eax
sub eax,ebp ;; pixel count
mov [pixelcount],eax ;; save for final pixel
jle near shdone ;; nothing to scale
;;
;; frac = dc_texturemid - (centery-dc_yl)*fracstep;
;;
mov ecx,[dc_iscale] ;; fracstep
mov eax,[centery]
sub eax,ebp
imul eax,ecx
mov edx,[dc_texturemid]
sub edx,eax
mov ebx,edx
shr ebx,16 ;; frac int.
and ebx,byte +0x7f
shl edx,16 ;; y frac up
mov ebp,ecx
shl ebp,16 ;; fracstep f. up
shr ecx,16 ;; fracstep i. ->cl
and cl,0x7f
mov esi,[dc_source]
;;
;; lets rock :) !
;;
mov eax,[pixelcount]
mov dh,al
shr eax,2
mov ch,al ;; quad count
mov eax,[colormaps]
test dh,3
je sh4quadloop
;;
;; do un-even pixel
;;
test dh,0x1
je shf2
mov ah,[esi+ebx] ;; fetch texel : colormap number
add edx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov [edi],dl
pl: add edi,0x12345678
;;
;; do two non-quad-aligned pixels
;;
shf2:
test dh,0x2
je shf3
mov ah,[esi+ebx] ;; fetch texel : colormap number
add edx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov [edi],dl
pm: add edi,0x12345678
mov ah,[esi+ebx] ;; fetch texel : colormap number
add edx,ebp
adc bl,cl
mov al,[edi] ;; fetch dest : index into colormap
and bl,0x7f
mov dl,[eax]
mov [edi],dl
pn: add edi,0x12345678
;;
;; test if there was at least 4 pixels
;;
shf3:
test ch,0xff ;; test quad count
je near shdone
;;
;; ebp : ystep frac. upper 24 bits
;; edx : y frac. upper 24 bits
;; ebx : y i. lower 7 bits, masked for index
;; ecx : ch = counter, cl = y step i.
;; eax : colormap aligned 256
;; esi : source texture column
;; edi : dest screen
;;
sh4quadloop:
mov dh,0x7f ;; prep mask
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [tystep],ebp
po: add edi,0x12345678
mov al,[edi] ;; fetch dest : index into colormap
pp: sub edi,0x12345678
mov ebp,edi
pq: sub edi,0x12345678
jmp short shinloop
align 4
shquadloop:
add edx,[tystep]
adc bl,cl
and bl,dh
q5: add ebp,0x12345678
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [edi],dl
mov al,[ebp] ;; fetch dest : index into colormap
shinloop:
add edx,[tystep]
adc bl,cl
and bl,dh
q6: add edi,0x12345678
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [ebp],dl
mov al,[edi] ;; fetch dest : index into colormap
add edx,[tystep]
adc bl,cl
and bl,dh
q7: add ebp,0x12345678
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [edi],dl
mov al,[ebp] ;; fetch dest : index into colormap
add edx,[tystep]
adc bl,cl
and bl,dh
q8: add edi,0x12345678
mov dl,[eax]
mov ah,[esi+ebx] ;; fetch texel : colormap number
mov [ebp],dl
mov al,[edi] ;; fetch dest : index into colormap
dec ch
jne shquadloop
shdone:
pop ebx ;; restore register variables
pop edi
pop esi
pop ebp ;; restore caller's stack frame pointer
ret
;; ========================================================================
;; Rasterization of the segments of a LINEAR polygne textur of manire.
;; It is thus a question of interpolating coordinate them at the edges of texture in
;; the time that the X-coordinates minx/maxx for each line.
;; the argument ' dir' indicates which edges of texture are Interpol?:
;; 0: segments associs at edge TOP? and BOTTOM? (constant TY)
;; 1: segments associs at the LEFT and RIGHT edge (constant TX)
;; ========================================================================
;;
;; void rasterize_segment_tex( LONG x1, LONG y1, LONG x2, LONG y2, LONG tv1, LONG tv2, LONG tc, LONG dir );
;; ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8
;;
;; Pour dir = 0, (tv1,tv2) = (tX1,tX2), tc = tY, en effet TY est constant.
;;
;; Pour dir = 1, (tv1,tv2) = (tY1,tY2), tc = tX, en effet TX est constant.
;;
;;
;; Uses: extern struct rastery *_rastertab;
;;
MINX EQU 0
MAXX EQU 4
TX1 EQU 8
TY1 EQU 12
TX2 EQU 16
TY2 EQU 20
RASTERY_SIZEOF EQU 24
cglobal rasterize_segment_tex_asm
rasterize_segment_tex_asm:
push ebp
mov ebp,esp
sub esp,byte +0x8 ;; allocate the local variables
push ebx
push esi
push edi
o16 mov ax,es
push eax
;; #define DX [ebp-4]
;; #define TD [ebp-8]
mov eax,[ebp+0xc] ;; y1
mov ebx,[ebp+0x14] ;; y2
cmp ebx,eax
je near .L_finished ;; special (y1==y2) segment horizontal, exit!
jg near .L_rasterize_right
;;rasterize_left: ;; one rasterize a segment LEFT of the polygne
mov ecx,eax
sub ecx,ebx
inc ecx ;; y1-y2+1
mov eax,RASTERY_SIZEOF
mul ebx ;; * y2
mov esi,[prastertab]
add esi,eax ;; point into rastertab[y2]
mov eax,[ebp+0x8] ;; ARG1
sub eax,[ebp+0x10] ;; ARG3
shl eax,0x10 ;; ((x1-x2)<<PRE) ...
cdq
idiv ecx ;; dx = ... / (y1-y2+1)
mov [ebp-0x4],eax ;; DX
mov eax,[ebp+0x18] ;; ARG5
sub eax,[ebp+0x1c] ;; ARG6
shl eax,0x10
cdq
idiv ecx ;; tdx =((tx1-tx2)<<PRE) / (y1-y2+1)
mov [ebp-0x8],eax ;; idem tdy =((ty1-ty2)<<PRE) / (y1-y2+1)
mov eax,[ebp+0x10] ;; ARG3
shl eax,0x10 ;; x = x2<<PRE
mov ebx,[ebp+0x1c] ;; ARG6
shl ebx,0x10 ;; tx = tx2<<PRE d0
;; ty = ty2<<PRE d1
mov edx,[ebp+0x20] ;; ARG7
shl edx,0x10 ;; ty = ty<<PRE d0
;; tx = tx<<PRE d1
push ebp
mov edi,[ebp-0x4] ;; DX
cmp dword [ebp+0x24],byte +0x0 ;; ARG8 direction ?
mov ebp,[ebp-0x8] ;; TD
je .L_rleft_h_loop
;;
;; TY varies, TX is constant
;;
.L_rleft_v_loop:
mov [esi+MINX],eax ;; rastertab[y].minx = x
add ebx,ebp
mov [esi+TX1],edx ;; .tx1 = tx
add eax,edi
mov [esi+TY1],ebx ;; .ty1 = ty
;;addl DX, %eax // x += dx
;;addl TD, %ebx // ty += tdy
add esi,RASTERY_SIZEOF ;; next raster line into rastertab[]
dec ecx
jne .L_rleft_v_loop
pop ebp
jmp .L_finished
;;
;; TX varies, TY is constant
;;
.L_rleft_h_loop:
mov [esi+MINX],eax ;; rastertab[y].minx = x
add eax,edi
mov [esi+TX1],ebx ;; .tx1 = tx
add ebx,ebp
mov [esi+TY1],edx ;; .ty1 = ty
;;addl DX, %eax // x += dx
;;addl TD, %ebx // tx += tdx
add esi,RASTERY_SIZEOF ;; next raster line into rastertab[]
dec ecx
jne .L_rleft_h_loop
pop ebp
jmp .L_finished
;;
;; one rasterize a segment LINE of the polygne
;;
.L_rasterize_right:
mov ecx,ebx
sub ecx,eax
inc ecx ;; y2-y1+1
mov ebx,RASTERY_SIZEOF
mul ebx ;; * y1
mov esi,[prastertab]
add esi,eax ;; point into rastertab[y1]
mov eax,[ebp+0x10] ;; ARG3
sub eax,[ebp+0x8] ;; ARG1
shl eax,0x10 ;; ((x2-x1)<<PRE) ...
cdq
idiv ecx ;; dx = ... / (y2-y1+1)
mov [ebp-0x4],eax ;; DX
mov eax,[ebp+0x1c] ;; ARG6
sub eax,[ebp+0x18] ;; ARG5
shl eax,0x10
cdq
idiv ecx ;; tdx =((tx2-tx1)<<PRE) / (y2-y1+1)
mov [ebp-0x8],eax ;; idem tdy =((ty2-ty1)<<PRE) / (y2-y1+1)
mov eax,[ebp+0x8] ;; ARG1
shl eax,0x10 ;; x = x1<<PRE
mov ebx,[ebp+0x18] ;; ARG5
shl ebx,0x10 ;; tx = tx1<<PRE d0
;; ty = ty1<<PRE d1
mov edx,[ebp+0x20] ;; ARG7
shl edx,0x10 ;; ty = ty<<PRE d0
;; tx = tx<<PRE d1
push ebp
mov edi,[ebp-0x4] ;; DX
cmp dword [ebp+0x24], 0 ;; direction ?
mov ebp,[ebp-0x8] ;; TD
je .L_rright_h_loop
;;
;; TY varies, TX is constant
;;
.L_rright_v_loop:
mov [esi+MAXX],eax ;; rastertab[y].maxx = x
add ebx,ebp
mov [esi+TX2],edx ;; .tx2 = tx
add eax,edi
mov [esi+TY2],ebx ;; .ty2 = ty
;;addl DX, %eax // x += dx
;;addl TD, %ebx // ty += tdy
add esi,RASTERY_SIZEOF
dec ecx
jne .L_rright_v_loop
pop ebp
jmp short .L_finished
;;
;; TX varies, TY is constant
;;
.L_rright_h_loop:
mov [esi+MAXX],eax ;; rastertab[y].maxx = x
add eax,edi
mov [esi+TX2],ebx ;; .tx2 = tx
add ebx,ebp
mov [esi+TY2],edx ;; .ty2 = ty
;;addl DX, %eax // x += dx
;;addl TD, %ebx // tx += tdx
add esi,RASTERY_SIZEOF
dec ecx
jne .L_rright_h_loop
pop ebp
.L_finished:
pop eax
o16 mov es,ax
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret

1587
src/tmap.s

File diff suppressed because it is too large Load diff

View file

@ -1,322 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file tmap_asm.s
/// \brief ???
//.comm _dc_colormap,4
//.comm _dc_x,4
//.comm _dc_yl,4
//.comm _dc_yh,4
//.comm _dc_iscale,4
//.comm _dc_texturemid,4
//.comm _dc_source,4
//.comm _ylookup,4
//.comm _columnofs,4
//.comm _loopcount,4
//.comm _pixelcount,4
.data
_pixelcount:
.long 0x00000000
_loopcount:
.long 0x00000000
.align 8
_mmxcomm:
.long 0x00000000
.text
.align 4
.globl _R_DrawColumn8_NOMMX
_R_DrawColumn8_NOMMX:
pushl %ebp
pushl %esi
pushl %edi
pushl %ebx
movl _dc_yl,%edx
movl _dc_yh,%eax
subl %edx,%eax
leal 1(%eax),%ebx
testl %ebx,%ebx
jle rdc8ndone
movl _dc_x,%eax
movl _ylookup, %edi
movl (%edi,%edx,4),%esi
movl _columnofs, %edi
addl (%edi,%eax,4),%esi
movl _dc_iscale,%edi
movl %edx,%eax
imull %edi,%eax
movl _dc_texturemid,%ecx
addl %eax,%ecx
movl _dc_source,%ebp
xorl %edx, %edx
subl $0x12345678, %esi
.globl rdc8nwidth1
rdc8nwidth1:
.align 4,0x90
rdc8nloop:
movl %ecx,%eax
shrl $16,%eax
addl %edi,%ecx
andl $127,%eax
addl $0x12345678,%esi
.globl rdc8nwidth2
rdc8nwidth2:
movb (%eax,%ebp),%dl
movl _dc_colormap,%eax
movb (%eax,%edx),%al
movb %al,(%esi)
decl %ebx
jne rdc8nloop
rdc8ndone:
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
//
// Optimised specifically for P54C/P55C (aka Pentium with/without MMX)
// By ES 1998/08/01
//
.globl _R_DrawColumn_8_Pentium
_R_DrawColumn_8_Pentium:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl _dc_yl,%eax // Top pixel
movl _dc_yh,%ebx // Bottom pixel
movl _ylookup, %edi
movl (%edi,%ebx,4),%ecx
subl %eax,%ebx // ebx=number of pixels-1
jl rdc8pdone // no pixel to draw, done
jnz rdc8pmany
movl _dc_x,%edx // Special case: only one pixel
movl _columnofs, %edi
addl (%edi,%edx,4),%ecx // dest pixel at (%ecx)
movl _dc_iscale,%esi
imull %esi,%eax
movl _dc_texturemid,%edi
addl %eax,%edi // texture index in edi
movl _dc_colormap,%edx
shrl $16, %edi
movl _dc_source,%ebp
andl $127,%edi
movb (%edi,%ebp),%dl // read texture pixel
movb (%edx),%al // lookup for light
movb %al,0(%ecx) // write it
jmp rdc8pdone // done!
.align 4, 0x90
rdc8pmany: // draw >1 pixel
movl _dc_x,%edx
movl _columnofs, %edi
movl (%edi,%edx,4),%edx
leal 0x12345678(%edx, %ecx), %edi // edi = two pixels above bottom
.globl rdc8pwidth5
rdc8pwidth5: // DeadBeef = -2*SCREENWIDTH
movl _dc_iscale,%edx // edx = fracstep
imull %edx,%eax
shll $9, %edx // fixme: Should get 7.25 fix as input
movl _dc_texturemid,%ecx
addl %eax,%ecx // ecx = frac
movl _dc_colormap,%eax // eax = lighting/special effects LUT
shll $9, %ecx
movl _dc_source,%esi // esi = source ptr
imull $0x12345678, %ebx // ebx = negative offset to pixel
.globl rdc8pwidth6
rdc8pwidth6: // DeadBeef = -SCREENWIDTH
// Begin the calculation of the two first pixels
leal (%ecx, %edx), %ebp
shrl $25, %ecx
movb (%esi, %ecx), %al
leal (%edx, %ebp), %ecx
shrl $25, %ebp
movb (%eax), %dl
// The main loop
rdc8ploop:
movb (%esi,%ebp), %al // load 1
leal (%ecx, %edx), %ebp // calc frac 3
shrl $25, %ecx // shift frac 2
movb %dl, 0x12345678(%edi, %ebx)// store 0
.globl rdc8pwidth1
rdc8pwidth1: // DeadBeef = 2*SCREENWIDTH
movb (%eax), %al // lookup 1
movb %al, 0x12345678(%edi, %ebx)// store 1
.globl rdc8pwidth2
rdc8pwidth2: // DeadBeef = 3*SCREENWIDTH
movb (%esi, %ecx), %al // load 2
leal (%ebp, %edx), %ecx // calc frac 4
shrl $25, %ebp // shift frac 3
movb (%eax), %dl // lookup 2
addl $0x12345678, %ebx // counter
.globl rdc8pwidth3
rdc8pwidth3: // DeadBeef = 2*SCREENWIDTH
jl rdc8ploop // loop
// End of loop. Write extra pixel or just exit.
jnz rdc8pdone
movb %dl, 0x12345678(%edi, %ebx)// Write odd pixel
.globl rdc8pwidth4
rdc8pwidth4: // DeadBeef = 2*SCREENWIDTH
rdc8pdone:
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
//
// MMX asm version, optimised for K6
// By ES 1998/07/05
//
.globl _R_DrawColumn_8_K6_MMX
_R_DrawColumn_8_K6_MMX:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl %esp, %eax // Push 8 or 12, so that (%esp) gets aligned by 8
andl $7,%eax
addl $8,%eax
movl %eax, _mmxcomm // Temp storage in mmxcomm: (%esp) is used instead
subl %eax,%esp
movl _dc_yl,%edx // Top pixel
movl _dc_yh,%ebx // Bottom pixel
movl _ylookup, %edi
movl (%edi,%ebx,4),%ecx
subl %edx,%ebx // ebx=number of pixels-1
jl 0x12345678 // no pixel to draw, done
.globl rdc8moffs1
rdc8moffs1:
jnz rdc8mmany
movl _dc_x,%eax // Special case: only one pixel
movl _columnofs, %edi
addl (%edi,%eax,4),%ecx // dest pixel at (%ecx)
movl _dc_iscale,%esi
imull %esi,%edx
movl _dc_texturemid,%edi
addl %edx,%edi // texture index in edi
movl _dc_colormap,%edx
shrl $16, %edi
movl _dc_source,%ebp
andl $127,%edi
movb (%edi,%ebp),%dl // read texture pixel
movb (%edx),%al // lookup for light
movb %al,0(%ecx) // write it
jmp rdc8mdone // done!
.globl rdc8moffs2
rdc8moffs2:
.align 4, 0x90
rdc8mmany: // draw >1 pixel
movl _dc_x,%eax
movl _columnofs, %edi
movl (%edi,%eax,4),%eax
leal 0x12345678(%eax, %ecx), %esi // esi = two pixels above bottom
.globl rdc8mwidth3
rdc8mwidth3: // DeadBeef = -2*SCREENWIDTH
movl _dc_iscale,%ecx // ecx = fracstep
imull %ecx,%edx
shll $9, %ecx // fixme: Should get 7.25 fix as input
movl _dc_texturemid,%eax
addl %edx,%eax // eax = frac
movl _dc_colormap,%edx // edx = lighting/special effects LUT
shll $9, %eax
leal (%ecx, %ecx), %edi
movl _dc_source,%ebp // ebp = source ptr
movl %edi, 0(%esp) // Start moving frac and fracstep to MMX regs
imull $0x12345678, %ebx // ebx = negative offset to pixel
.globl rdc8mwidth5
rdc8mwidth5: // DeadBeef = -SCREENWIDTH
movl %edi, 4(%esp)
leal (%eax, %ecx), %edi
movq 0(%esp), %mm1 // fracstep:fracstep in mm1
movl %eax, 0(%esp)
shrl $25, %eax
movl %edi, 4(%esp)
movzbl (%ebp, %eax), %eax
movq 0(%esp), %mm0 // frac:frac in mm0
paddd %mm1, %mm0
shrl $25, %edi
movq %mm0, %mm2
psrld $25, %mm2 // texture index in mm2
paddd %mm1, %mm0
movq %mm2, 0(%esp)
.globl rdc8mloop
rdc8mloop: // The main loop
movq %mm0, %mm2 // move 4-5 to temp reg
movzbl (%ebp, %edi), %edi // read 1
psrld $25, %mm2 // shift 4-5
movb (%edx,%eax), %cl // lookup 0
movl 0(%esp), %eax // load 2
addl $0x12345678, %ebx // counter
.globl rdc8mwidth2
rdc8mwidth2: // DeadBeef = 2*SCREENWIDTH
movb %cl, (%esi, %ebx) // write 0
movb (%edx,%edi), %ch // lookup 1
movb %ch, 0x12345678(%esi, %ebx) // write 1
.globl rdc8mwidth1
rdc8mwidth1: // DeadBeef = SCREENWIDTH
movl 4(%esp), %edi // load 3
paddd %mm1, %mm0 // frac 6-7
movzbl (%ebp, %eax), %eax // lookup 2
movq %mm2, 0(%esp) // store texture index 4-5
jl rdc8mloop
jnz rdc8mno_odd
movb (%edx,%eax), %cl // write the last odd pixel
movb %cl, 0x12345678(%esi)
.globl rdc8mwidth4
rdc8mwidth4: // DeadBeef = 2*SCREENWIDTH
rdc8mno_odd:
.globl rdc8mdone
rdc8mdone:
emms
addl _mmxcomm, %esp
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
// Need some extra space to align run-time
.globl R_DrawColumn_8_K6_MMX_end
R_DrawColumn_8_K6_MMX_end:
nop;nop;nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;nop;

View file

@ -1,674 +0,0 @@
;; SONIC ROBO BLAST 2
;;-----------------------------------------------------------------------------
;; Copyright (C) 1998-2000 by DOSDOOM.
;; Copyright (C) 2010-2021 by Sonic Team Junior.
;;
;; This program is free software distributed under the
;; terms of the GNU General Public License, version 2.
;; See the 'LICENSE' file for more details.
;;-----------------------------------------------------------------------------
;; FILE:
;; tmap_mmx.nas
;; DESCRIPTION:
;; Assembler optimised rendering code for software mode, using SIMD
;; instructions.
;; Draw wall columns.
[BITS 32]
%define FRACBITS 16
%define TRANSPARENTPIXEL 255
%ifdef LINUX
%macro cextern 1
[extern %1]
%endmacro
%macro cglobal 1
[global %1]
%endmacro
%else
%macro cextern 1
%define %1 _%1
[extern %1]
%endmacro
%macro cglobal 1
%define %1 _%1
[global %1]
%endmacro
%endif
; The viddef_s structure. We only need the width field.
struc viddef_s
resb 12
.width: resb 4
resb 44
endstruc
;; externs
;; columns
cextern dc_colormap
cextern dc_x
cextern dc_yl
cextern dc_yh
cextern dc_iscale
cextern dc_texturemid
cextern dc_texheight
cextern dc_source
cextern dc_hires
cextern centery
cextern centeryfrac
cextern dc_transmap
cextern R_DrawColumn_8_ASM
cextern R_Draw2sMultiPatchColumn_8_ASM
;; spans
cextern nflatshiftup
cextern nflatxshift
cextern nflatyshift
cextern nflatmask
cextern ds_xfrac
cextern ds_yfrac
cextern ds_xstep
cextern ds_ystep
cextern ds_x1
cextern ds_x2
cextern ds_y
cextern ds_source
cextern ds_colormap
cextern ylookup
cextern columnofs
cextern vid
[SECTION .data]
nflatmask64 dq 0
[SECTION .text]
;;----------------------------------------------------------------------
;;
;; R_DrawColumn : 8bpp column drawer
;;
;; MMX column drawer.
;;
;;----------------------------------------------------------------------
;; eax = accumulator
;; ebx = colormap
;; ecx = count
;; edx = accumulator
;; esi = source
;; edi = dest
;; ebp = vid.width
;; mm0 = accumulator
;; mm1 = heightmask, twice
;; mm2 = 2 * fracstep, twice
;; mm3 = pair of consecutive fracs
;;----------------------------------------------------------------------
cglobal R_DrawColumn_8_MMX
R_DrawColumn_8_MMX:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; Our algorithm requires that the texture height be a power of two.
;; If not, fall back to the non-MMX drawer.
;;
.texheightcheck:
mov edx, [dc_texheight]
sub edx, 1 ;; edx = heightmask
test edx, [dc_texheight]
jnz near .usenonMMX
mov ebp, edx ;; Keep a copy of heightmask in a
;; GPR for the time being.
;;
;; Fill mm1 with heightmask
;;
movd mm1, edx ;; low dword = heightmask
punpckldq mm1, mm1 ;; copy low dword to high dword
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov eax, [dc_yl]
mov edi, [ylookup+eax*4]
mov ebx, [dc_x]
add edi, [columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov ecx, [dc_yh]
add ecx, 1
sub ecx, eax ;; pixel count
jle near .done ;; nothing to scale
;;
;; fracstep = dc_iscale;
;;
movd mm2, [dc_iscale] ;; fracstep in low dword
punpckldq mm2, mm2 ;; copy to high dword
mov ebx, [dc_colormap]
mov esi, [dc_source]
;;
;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
;;
;; eax == dc_yl already
shl eax, FRACBITS
sub eax, [centeryfrac]
imul dword [dc_iscale]
shrd eax, edx, FRACBITS
add eax, [dc_texturemid]
;;
;; if (dc_hires) frac = 0;
;;
test byte [dc_hires], 0x01
jz .mod2
xor eax, eax
;;
;; Do mod-2 pixel.
;;
.mod2:
test ecx, 1
jz .pairprepare
mov edx, eax ;; edx = frac
add eax, [dc_iscale] ;; eax += fracstep
sar edx, FRACBITS
and edx, ebp ;; edx &= heightmask
movzx edx, byte [esi + edx]
movzx edx, byte [ebx + edx]
mov [edi], dl
add edi, [vid + viddef_s.width]
sub ecx, 1
jz .done
.pairprepare:
;;
;; Prepare for the main loop.
;;
movd mm3, eax ;; Low dword = frac
movq mm4, mm3 ;; Copy to intermediate register
paddd mm4, mm2 ;; dwords of mm4 += fracstep
punpckldq mm3, mm4 ;; Low dword = first frac, high = second
pslld mm2, 1 ;; fracstep *= 2
;;
;; ebp = vid.width
;;
mov ebp, [vid + viddef_s.width]
align 16
.pairloop:
movq mm0, mm3 ;; 3B 1u.
psrad mm0, FRACBITS ;; 4B 1u.
pand mm0, mm1 ;; 3B 1u. frac &= heightmask
paddd mm3, mm2 ;; 3B 1u. frac += fracstep
movd eax, mm0 ;; 3B 1u. Get first frac
;; IFETCH boundary
movzx eax, byte [esi + eax] ;; 4B 1u. Texture map
movzx eax, byte [ebx + eax] ;; 4B 1u. Colormap
punpckhdq mm0, mm0 ;; 3B 1(2)u. low dword = high dword
movd edx, mm0 ;; 3B 1u. Get second frac
mov [edi], al ;; 2B 1(2)u. First pixel
;; IFETCH boundary
movzx edx, byte [esi + edx] ;; 4B 1u. Texture map
movzx edx, byte [ebx + edx] ;; 4B 1u. Colormap
mov [edi + 1*ebp], dl ;; 3B 1(2)u. Second pixel
lea edi, [edi + 2*ebp] ;; 3B 1u. edi += 2 * vid.width
;; IFETCH boundary
sub ecx, 2 ;; 3B 1u. count -= 2
jnz .pairloop ;; 2B 1u. if(count != 0) goto .pairloop
.done:
;;
;; Clear MMX state, or else FPU operations will go badly awry.
;;
emms
pop ebx
pop edi
pop esi
pop ebp
ret
.usenonMMX:
call R_DrawColumn_8_ASM
jmp .done
;;----------------------------------------------------------------------
;;
;; R_Draw2sMultiPatchColumn : Like R_DrawColumn, but omits transparent
;; pixels.
;;
;; MMX column drawer.
;;
;;----------------------------------------------------------------------
;; eax = accumulator
;; ebx = colormap
;; ecx = count
;; edx = accumulator
;; esi = source
;; edi = dest
;; ebp = vid.width
;; mm0 = accumulator
;; mm1 = heightmask, twice
;; mm2 = 2 * fracstep, twice
;; mm3 = pair of consecutive fracs
;;----------------------------------------------------------------------
cglobal R_Draw2sMultiPatchColumn_8_MMX
R_Draw2sMultiPatchColumn_8_MMX:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; Our algorithm requires that the texture height be a power of two.
;; If not, fall back to the non-MMX drawer.
;;
.texheightcheck:
mov edx, [dc_texheight]
sub edx, 1 ;; edx = heightmask
test edx, [dc_texheight]
jnz near .usenonMMX
mov ebp, edx ;; Keep a copy of heightmask in a
;; GPR for the time being.
;;
;; Fill mm1 with heightmask
;;
movd mm1, edx ;; low dword = heightmask
punpckldq mm1, mm1 ;; copy low dword to high dword
;;
;; dest = ylookup[dc_yl] + columnofs[dc_x];
;;
mov eax, [dc_yl]
mov edi, [ylookup+eax*4]
mov ebx, [dc_x]
add edi, [columnofs+ebx*4] ;; edi = dest
;;
;; pixelcount = yh - yl + 1
;;
mov ecx, [dc_yh]
add ecx, 1
sub ecx, eax ;; pixel count
jle near .done ;; nothing to scale
;;
;; fracstep = dc_iscale;
;;
movd mm2, [dc_iscale] ;; fracstep in low dword
punpckldq mm2, mm2 ;; copy to high dword
mov ebx, [dc_colormap]
mov esi, [dc_source]
;;
;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
;;
;; eax == dc_yl already
shl eax, FRACBITS
sub eax, [centeryfrac]
imul dword [dc_iscale]
shrd eax, edx, FRACBITS
add eax, [dc_texturemid]
;;
;; if (dc_hires) frac = 0;
;;
test byte [dc_hires], 0x01
jz .mod2
xor eax, eax
;;
;; Do mod-2 pixel.
;;
.mod2:
test ecx, 1
jz .pairprepare
mov edx, eax ;; edx = frac
add eax, [dc_iscale] ;; eax += fracstep
sar edx, FRACBITS
and edx, ebp ;; edx &= heightmask
movzx edx, byte [esi + edx]
cmp dl, TRANSPARENTPIXEL
je .nextmod2
movzx edx, byte [ebx + edx]
mov [edi], dl
.nextmod2:
add edi, [vid + viddef_s.width]
sub ecx, 1
jz .done
.pairprepare:
;;
;; Prepare for the main loop.
;;
movd mm3, eax ;; Low dword = frac
movq mm4, mm3 ;; Copy to intermediate register
paddd mm4, mm2 ;; dwords of mm4 += fracstep
punpckldq mm3, mm4 ;; Low dword = first frac, high = second
pslld mm2, 1 ;; fracstep *= 2
;;
;; ebp = vid.width
;;
mov ebp, [vid + viddef_s.width]
align 16
.pairloop:
movq mm0, mm3 ;; 3B 1u.
psrad mm0, FRACBITS ;; 4B 1u.
pand mm0, mm1 ;; 3B 1u. frac &= heightmask
paddd mm3, mm2 ;; 3B 1u. frac += fracstep
movd eax, mm0 ;; 3B 1u. Get first frac
;; IFETCH boundary
movzx eax, byte [esi + eax] ;; 4B 1u. Texture map
punpckhdq mm0, mm0 ;; 3B 1(2)u. low dword = high dword
movd edx, mm0 ;; 3B 1u. Get second frac
cmp al, TRANSPARENTPIXEL ;; 2B 1u.
je .secondinpair ;; 2B 1u.
;; IFETCH boundary
movzx eax, byte [ebx + eax] ;; 4B 1u. Colormap
mov [edi], al ;; 2B 1(2)u. First pixel
.secondinpair:
movzx edx, byte [esi + edx] ;; 4B 1u. Texture map
cmp dl, TRANSPARENTPIXEL ;; 2B 1u.
je .nextpair ;; 2B 1u.
;; IFETCH boundary
movzx edx, byte [ebx + edx] ;; 4B 1u. Colormap
mov [edi + 1*ebp], dl ;; 3B 1(2)u. Second pixel
.nextpair:
lea edi, [edi + 2*ebp] ;; 3B 1u. edi += 2 * vid.width
sub ecx, 2 ;; 3B 1u. count -= 2
jnz .pairloop ;; 2B 1u. if(count != 0) goto .pairloop
.done:
;;
;; Clear MMX state, or else FPU operations will go badly awry.
;;
emms
pop ebx
pop edi
pop esi
pop ebp
ret
.usenonMMX:
call R_Draw2sMultiPatchColumn_8_ASM
jmp .done
;;----------------------------------------------------------------------
;;
;; R_DrawSpan : 8bpp span drawer
;;
;; MMX span drawer.
;;
;;----------------------------------------------------------------------
;; eax = accumulator
;; ebx = colormap
;; ecx = count
;; edx = accumulator
;; esi = source
;; edi = dest
;; ebp = two pixels
;; mm0 = accumulator
;; mm1 = xposition
;; mm2 = yposition
;; mm3 = 2 * xstep
;; mm4 = 2 * ystep
;; mm5 = nflatxshift
;; mm6 = nflatyshift
;; mm7 = accumulator
;;----------------------------------------------------------------------
cglobal R_DrawSpan_8_MMX
R_DrawSpan_8_MMX:
push ebp ;; preserve caller's stack frame pointer
push esi ;; preserve register variables
push edi
push ebx
;;
;; esi = ds_source
;; ebx = ds_colormap
;;
mov esi, [ds_source]
mov ebx, [ds_colormap]
;;
;; edi = ylookup[ds_y] + columnofs[ds_x1]
;;
mov eax, [ds_y]
mov edi, [ylookup + eax*4]
mov edx, [ds_x1]
add edi, [columnofs + edx*4]
;;
;; ecx = ds_x2 - ds_x1 + 1
;;
mov ecx, [ds_x2]
sub ecx, edx
add ecx, 1
;;
;; Needed for fracs and steps
;;
movd mm7, [nflatshiftup]
;;
;; mm3 = xstep
;;
movd mm3, [ds_xstep]
pslld mm3, mm7
punpckldq mm3, mm3
;;
;; mm4 = ystep
;;
movd mm4, [ds_ystep]
pslld mm4, mm7
punpckldq mm4, mm4
;;
;; mm1 = pair of consecutive xpositions
;;
movd mm1, [ds_xfrac]
pslld mm1, mm7
movq mm6, mm1
paddd mm6, mm3
punpckldq mm1, mm6
;;
;; mm2 = pair of consecutive ypositions
;;
movd mm2, [ds_yfrac]
pslld mm2, mm7
movq mm6, mm2
paddd mm6, mm4
punpckldq mm2, mm6
;;
;; mm5 = nflatxshift
;; mm6 = nflatyshift
;;
movd mm5, [nflatxshift]
movd mm6, [nflatyshift]
;;
;; Mask is in memory due to lack of registers.
;;
mov eax, [nflatmask]
mov [nflatmask64], eax
mov [nflatmask64 + 4], eax
;;
;; Go until we reach a dword boundary.
;;
.unaligned:
test edi, 3
jz .alignedprep
.stragglers:
cmp ecx, 0
je .done ;; If ecx == 0, we're finished.
;;
;; eax = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)
;;
movq mm0, mm1 ;; mm0 = xposition
movq mm7, mm2 ;; mm7 = yposition
paddd mm1, mm3 ;; xposition += xstep (once!)
paddd mm2, mm4 ;; yposition += ystep (once!)
psrld mm0, mm5 ;; shift
psrld mm7, mm6 ;; shift
pand mm7, [nflatmask64] ;; mask
por mm0, mm7 ;; or x and y together
movd eax, mm0 ;; eax = index of first pixel
movzx eax, byte [esi + eax] ;; al = source[eax]
movzx eax, byte [ebx + eax] ;; al = colormap[al]
mov [edi], al
add edi, 1
sub ecx, 1
jmp .unaligned
.alignedprep:
;;
;; We can double the steps now.
;;
pslld mm3, 1
pslld mm4, 1
;;
;; Generate chunks of four pixels.
;;
.alignedloop:
;;
;; Make sure we have at least four pixels.
;;
cmp ecx, 4
jl .prestragglers
;;
;; First two pixels.
;;
movq mm0, mm1 ;; mm0 = xposition
movq mm7, mm2 ;; mm7 = yposition
paddd mm1, mm3 ;; xposition += xstep
paddd mm2, mm4 ;; yposition += ystep
psrld mm0, mm5 ;; shift
psrld mm7, mm6 ;; shift
pand mm7, [nflatmask64] ;; mask
por mm0, mm7 ;; or x and y together
movd eax, mm0 ;; eax = index of first pixel
movzx eax, byte [esi + eax] ;; al = source[eax]
movzx ebp, byte [ebx + eax] ;; ebp = colormap[al]
punpckhdq mm0, mm0 ;; both dwords = high dword
movd eax, mm0 ;; eax = index of second pixel
movzx eax, byte [esi + eax] ;; al = source[eax]
movzx eax, byte [ebx + eax] ;; al = colormap[al]
shl eax, 8 ;; get pixel in right byte
or ebp, eax ;; put pixel in ebp
;;
;; Next two pixels.
;;
movq mm0, mm1 ;; mm0 = xposition
movq mm7, mm2 ;; mm7 = yposition
paddd mm1, mm3 ;; xposition += xstep
paddd mm2, mm4 ;; yposition += ystep
psrld mm0, mm5 ;; shift
psrld mm7, mm6 ;; shift
pand mm7, [nflatmask64] ;; mask
por mm0, mm7 ;; or x and y together
movd eax, mm0 ;; eax = index of third pixel
movzx eax, byte [esi + eax] ;; al = source[eax]
movzx eax, byte [ebx + eax] ;; al = colormap[al]
shl eax, 16 ;; get pixel in right byte
or ebp, eax ;; put pixel in ebp
punpckhdq mm0, mm0 ;; both dwords = high dword
movd eax, mm0 ;; eax = index of second pixel
movzx eax, byte [esi + eax] ;; al = source[eax]
movzx eax, byte [ebx + eax] ;; al = colormap[al]
shl eax, 24 ;; get pixel in right byte
or ebp, eax ;; put pixel in ebp
;;
;; Write pixels.
;;
mov [edi], ebp
add edi, 4
sub ecx, 4
jmp .alignedloop
.prestragglers:
;;
;; Back to one step at a time.
;;
psrad mm3, 1
psrad mm4, 1
jmp .stragglers
.done:
;;
;; Clear MMX state, or else FPU operations will go badly awry.
;;
emms
pop ebx
pop edi
pop esi
pop ebp
ret

View file

@ -1,48 +0,0 @@
;; SONIC ROBO BLAST 2
;;-----------------------------------------------------------------------------
;; Copyright (C) 1998-2000 by DooM Legacy Team.
;; Copyright (C) 1999-2021 by Sonic Team Junior.
;;
;; This program is free software distributed under the
;; terms of the GNU General Public License, version 2.
;; See the 'LICENSE' file for more details.
;;-----------------------------------------------------------------------------
;; FILE:
;; tmap_vc.nas
;; DESCRIPTION:
;; Assembler optimised math code for Visual C++.
[BITS 32]
%macro cglobal 1
%define %1 _%1
[global %1]
%endmacro
[SECTION .text write]
;----------------------------------------------------------------------------
;fixed_t FixedMul (fixed_t a, fixed_t b)
;----------------------------------------------------------------------------
cglobal FixedMul
; align 16
FixedMul:
mov eax,[esp+4]
imul dword [esp+8]
shrd eax,edx,16
ret
;----------------------------------------------------------------------------
;fixed_t FixedDiv2 (fixed_t a, fixed_t b);
;----------------------------------------------------------------------------
cglobal FixedDiv2
; align 16
FixedDiv2:
mov eax,[esp+4]
mov edx,eax ;; these two instructions allow the next
sar edx,31 ;; two to pair, on the Pentium processor.
shld edx,eax,16
sal eax,16
idiv dword [esp+8]
ret

View file

@ -82,6 +82,14 @@
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
#ifdef HAVE_THREADS
static I_mutex wad_mutex;
# define Lock_state() I_lock_mutex(&wad_mutex)
# define Unlock_state() I_unlock_mutex(wad_mutex)
#else
# define Lock_state()
# define Unlock_state()
#endif
typedef struct typedef struct
{ {
@ -1922,6 +1930,8 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
if (!TestValidLump(wad,lump)) if (!TestValidLump(wad,lump))
return NULL; return NULL;
Lock_state();
lumpcache = wadfiles[wad]->lumpcache; lumpcache = wadfiles[wad]->lumpcache;
if (!lumpcache[lump]) if (!lumpcache[lump])
{ {
@ -1931,6 +1941,8 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
else else
Z_ChangeTag(lumpcache[lump], tag); Z_ChangeTag(lumpcache[lump], tag);
Unlock_state();
return lumpcache[lump]; return lumpcache[lump];
} }
@ -1955,9 +1967,13 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag)
if (!TestValidLump(wad,lump)) if (!TestValidLump(wad,lump))
return NULL; return NULL;
Lock_state();
ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, NULL); ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, NULL);
W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full
Unlock_state();
return ptr; return ptr;
} }
@ -1975,15 +1991,23 @@ static inline boolean W_IsLumpCachedPWAD(UINT16 wad, UINT16 lump, void *ptr)
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return false; return false;
Lock_state();
lcache = wadfiles[wad]->lumpcache[lump]; lcache = wadfiles[wad]->lumpcache[lump];
if (ptr) if (ptr)
{ {
if (ptr == lcache) if (ptr == lcache) {
Unlock_state();
return true; return true;
} }
else if (lcache) }
else if (lcache) {
Unlock_state();
return true; return true;
}
Unlock_state();
return false; return false;
} }
@ -2007,15 +2031,23 @@ static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr)
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return false; return false;
Lock_state();
lcache = wadfiles[wad]->patchcache[lump]; lcache = wadfiles[wad]->patchcache[lump];
if (ptr) if (ptr)
{ {
if (ptr == lcache) if (ptr == lcache) {
Unlock_state();
return true; return true;
} }
else if (lcache) }
else if (lcache) {
Unlock_state();
return true; return true;
}
Unlock_state();
return false; return false;
} }
@ -2048,7 +2080,7 @@ void *W_CacheLumpName(const char *name, INT32 tag)
// Cache a patch into heap memory, convert the patch format as necessary // Cache a patch into heap memory, convert the patch format as necessary
// //
void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) static void *W_CacheSoftwarePatch(UINT16 wad, UINT16 lump, INT32 tag)
{ {
lumpcache_t *lumpcache = NULL; lumpcache_t *lumpcache = NULL;
@ -2082,11 +2114,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
return lumpcache[lump]; return lumpcache[lump];
} }
void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag)
{
return W_CacheSoftwarePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag);
}
void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
{ {
patch_t *patch; patch_t *patch;
@ -2094,16 +2121,23 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return NULL; return NULL;
patch = W_CacheSoftwarePatchNumPwad(wad, lump, tag); Lock_state();
patch = W_CacheSoftwarePatch(wad, lump, tag);
#ifdef HWRENDER #ifdef HWRENDER
// Software-only compile cache the data without conversion // Software-only compile cache the data without conversion
if (rendermode == render_soft || rendermode == render_none) if (rendermode == render_soft || rendermode == render_none)
#endif #endif
{
Unlock_state();
return (void *)patch; return (void *)patch;
}
#ifdef HWRENDER #ifdef HWRENDER
Patch_CreateGL(patch); Patch_CreateGL(patch);
Unlock_state();
return (void *)patch; return (void *)patch;
#endif #endif
} }
@ -2118,6 +2152,8 @@ void W_UnlockCachedPatch(void *patch)
if (!patch) if (!patch)
return; return;
Lock_state();
// The hardware code does its own memory management, as its patches // The hardware code does its own memory management, as its patches
// have different lifetimes from software's. // have different lifetimes from software's.
#ifdef HWRENDER #ifdef HWRENDER
@ -2126,6 +2162,8 @@ void W_UnlockCachedPatch(void *patch)
else else
#endif #endif
Z_Unlock(patch); Z_Unlock(patch);
Unlock_state();
} }
void *W_CachePatchName(const char *name, INT32 tag) void *W_CachePatchName(const char *name, INT32 tag)

View file

@ -207,11 +207,6 @@ void *W_CachePatchLongName(const char *name, INT32 tag);
void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag);
void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag);
// Returns a Software patch.
// Performs any necessary conversions from PNG images.
void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag);
void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag);
void W_UnlockCachedPatch(void *patch); void W_UnlockCachedPatch(void *patch);
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);

View file

@ -39,6 +39,15 @@
#include "hardware/hw_main.h" // For hardware memory info #include "hardware/hw_main.h" // For hardware memory info
#endif #endif
#ifdef HAVE_THREADS
static I_mutex Z_mutex;
# define Lock_state() I_lock_mutex(&Z_mutex)
# define Unlock_state() I_unlock_mutex(Z_mutex)
#else
# define Lock_state()
# define Unlock_state()
#endif
#ifdef HAVE_VALGRIND #ifdef HAVE_VALGRIND
#include "valgrind.h" #include "valgrind.h"
static boolean Z_calloc = false; static boolean Z_calloc = false;
@ -203,6 +212,8 @@ void Z_Free(void *ptr)
if (ptr == NULL) if (ptr == NULL)
return; return;
Lock_state();
#ifdef ZDEBUG2 #ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line); CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
#endif #endif
@ -237,6 +248,8 @@ void Z_Free(void *ptr)
block->prev->next = block->next; block->prev->next = block->next;
block->next->prev = block->prev; block->next->prev = block->prev;
free(block); free(block);
Unlock_state();
} }
/** malloc() that doesn't accept failure. /** malloc() that doesn't accept failure.
@ -295,6 +308,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
void *given; void *given;
size_t blocksize = extrabytes + sizeof *hdr + size; size_t blocksize = extrabytes + sizeof *hdr + size;
Lock_state();
#ifdef ZDEBUG2 #ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line); CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line);
#endif #endif
@ -359,6 +374,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
I_Error("Z_Malloc: attempted to allocate purgable block " I_Error("Z_Malloc: attempted to allocate purgable block "
"(size %s) with no user", sizeu1(size)); "(size %s) with no user", sizeu1(size));
Unlock_state();
return given; return given;
} }
@ -381,14 +398,19 @@ void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char
void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
#endif #endif
{ {
void *mem;
Lock_state();
#ifdef VALGRIND_MEMPOOL_ALLOC #ifdef VALGRIND_MEMPOOL_ALLOC
Z_calloc = true; Z_calloc = true;
#endif #endif
#ifdef ZDEBUG #ifdef ZDEBUG
return memset(Z_Malloc2 (size, tag, user, alignbits, file, line), 0, size); mem = Z_Malloc2 (size, tag, user, alignbits, file, line);
#else #else
return memset(Z_MallocAlign(size, tag, user, alignbits ), 0, size); mem = Z_MallocAlign(size, tag, user, alignbits );
#endif #endif
memset(mem, 0, size);
Unlock_state();
return mem;
} }
/** The Z_ReallocAlign function. /** The Z_ReallocAlign function.