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_NASM_SOURCES tmap_mmx.nas tmap.nas)
### Configuration
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.")
@ -213,8 +211,7 @@ if(${SRB2_CONFIG_USEASM})
target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse")
target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES}
${SRB2_NASM_SOURCES})
target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES})
else()
set(SRB2_USEASM OFF)
target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM)

View file

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

View file

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

View file

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

View file

@ -537,6 +537,9 @@ INT32 I_GetKey(void);
// Max gamepad/joysticks that can be detected/used.
#define MAX_JOYSTICKS 4
// Software multithreading
#define MAX_RENDER_THREADS 8
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
@ -608,13 +611,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls.
//#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
#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_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void);
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);

View file

@ -15,25 +15,39 @@
#define I_THREADS_H
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_cond;
void I_start_threads (void);
void I_stop_threads (void);
void I_start_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 */
int I_thread_is_stopped (void);
int I_thread_is_stopped (void);
void I_lock_mutex (I_mutex *);
void I_unlock_mutex (I_mutex);
void I_lock_mutex (I_mutex *);
void I_unlock_mutex (I_mutex);
void I_hold_cond (I_cond *, I_mutex);
void I_hold_cond (I_cond *, I_mutex);
void I_wake_one_cond (I_cond *);
void I_wake_all_cond (I_cond *);
void I_wake_one_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/*HAVE_THREADS*/

View file

@ -100,7 +100,30 @@ enum {
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();
@ -122,15 +145,19 @@ static void M_DrawPerfString(perfstatcol_t *col, int type)
if (hires)
{
V_DrawSmallString(col->hires_x, draw_row, draw_flags,
va("%s %d", row->hires_label, value));
const char *string = 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;
}
else
{
V_DrawThinString(col->lores_x, draw_row, draw_flags,
va("%s %d", row->lores_label, value));
const char *string = 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;
}
@ -139,12 +166,12 @@ static void M_DrawPerfString(perfstatcol_t *col, int type)
static void M_DrawPerfTiming(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_TIME);
M_DrawPerfMeasurement(col, PERF_TIME);
}
static void M_DrawPerfCount(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_COUNT);
M_DrawPerfMeasurement(col, PERF_COUNT);
}
static void M_DrawRenderStats(void)
@ -161,7 +188,7 @@ static void M_DrawRenderStats(void)
};
perfstatrow_t rendercalltime_row[] = {
{"drwtime", "3d rendering: ", &ps_rendercalltime},
{"drwtime", "3D rendering: ", &ps_rendercalltime},
{0}
};
@ -176,16 +203,6 @@ static void M_DrawRenderStats(void)
{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[] = {
{"ui ", "UI render: ", &ps_uitime},
{"finupdt", "I_FinishUpdate:", &ps_swaptime},
@ -197,14 +214,6 @@ static void M_DrawRenderStats(void)
{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[] = {
{"batsort", "Batch sort: ", &ps_hw_batchsorttime},
{"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 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 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 batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row};
@ -256,12 +262,13 @@ static void M_DrawRenderStats(void)
M_DrawPerfTiming(&rendercalltime_col);
// Remember to update this calculation when adding more 3d rendering stats!
extrarendertime = ps_rendercalltime - ps_bsptime;
extrarendertime = ps_rendercalltime;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
extrarendertime -=
extrarendertime =
ps_bsptime[0] +
ps_hw_skyboxtime +
ps_hw_nodesorttime +
ps_hw_nodedrawtime +
@ -280,13 +287,32 @@ static void M_DrawRenderStats(void)
else
#endif
{
extrarendertime -=
ps_sw_spritecliptime +
ps_sw_portaltime +
ps_sw_planetime +
ps_sw_maskedtime;
INT32 i = 0;
M_DrawPerfTiming(&softwaretime_col);
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(&other_col);
}
}
@ -298,7 +324,40 @@ static void M_DrawRenderStats(void)
if (rendering)
{
draw_row = 10;
M_DrawPerfCount(&rendercalls_col);
#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);
} 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
if (rendermode == render_opengl && cv_glbatching.value)

View file

@ -23,50 +23,37 @@
#include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
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 = 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;
#ifdef HAVE_THREADS
static I_mutex R_BSP_mutex;
# define Lock_state() I_lock_mutex(&R_BSP_mutex)
# define Unlock_state() I_unlock_mutex(R_BSP_mutex)
#else
# define Lock_state()
# define Unlock_state()
#endif
//
// 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
// Does handle solid walls,
// e.g. single sided LineDefs (middle texture)
// 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 *start;
// Find the first range that touches the range (adjacent pixels are touching).
start = solidsegs;
start = bspcontext->solidsegs;
while (start->last < first - 1)
start++;
@ -75,11 +62,11 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
if (last < start->first - 1)
{
// Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange(first, last);
next = newend;
newend++;
R_StoreWallRange(context, wallcontext, first, last);
next = bspcontext->newend;
bspcontext->newend++;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
if (bspcontext->newend - bspcontext->solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
while (next != start)
@ -93,7 +80,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
}
// 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.
start->first = first;
}
@ -106,7 +93,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
while (last >= (next+1)->first - 1)
{
// 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++;
if (last <= next->last)
@ -119,7 +106,7 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
}
// There is a fragment after *next.
R_StoreWallRange(next->last + 1, last);
R_StoreWallRange(context, wallcontext, next->last + 1, last);
// Adjust the clip size.
start->last = last;
@ -128,13 +115,13 @@ crunch:
if (next == start)
return; // Post just extended past the bottom of one post.
while (next++ != newend)
while (next++ != bspcontext->newend)
*++start = *next; // Remove a post.
newend = start + 1;
bspcontext->newend = start + 1;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
if (bspcontext->newend - bspcontext->solidsegs > MAXSEGS)
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.
// 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;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
start = context->bspcontext.solidsegs;
while (start->last < first - 1)
start++;
@ -158,12 +145,12 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
if (last < start->first - 1)
{
// Post is entirely visible (above start).
R_StoreWallRange(first, last);
R_StoreWallRange(context, wallcontext, first, last);
return;
}
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
R_StoreWallRange(context, wallcontext, first, start->first - 1);
}
// Bottom contained in start?
@ -173,7 +160,7 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
while (last >= (start+1)->first - 1)
{
// 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++;
if (last <= start->last)
@ -181,27 +168,19 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
}
// There is a fragment after *next.
R_StoreWallRange(start->last + 1, last);
R_StoreWallRange(context, wallcontext, start->last + 1, last);
}
//
// R_ClearClipSegs
//
void R_ClearClipSegs(void)
void R_ClearClipSegs(bspcontext_t *context, INT32 start, INT32 end)
{
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = -1;
solidsegs[1].first = viewwidth;
solidsegs[1].last = 0x7fffffff;
newend = 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;
context->solidsegs[0].first = -0x7fffffff;
context->solidsegs[0].last = start-1;
context->solidsegs[1].first = end;
context->solidsegs[1].last = 0x7fffffff;
context->newend = context->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
// 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
// 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:
&& (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.
//
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back)
sector_t *R_FakeFlat(viewcontext_t *viewcontext, sector_t *sec, sector_t *tempsec,
INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back)
{
if (floorlightlevel)
*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)
{
const sector_t *s = &sectors[sec->heightsec];
mobj_t *viewmobj = viewplayer->mo;
mobj_t *viewmobj = viewcontext->player->mo;
INT32 heightsec;
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;
else if (camera.chase && viewplayer == &players[displayplayer])
else if (camera.chase && viewcontext->player == &players[displayplayer])
heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec;
else if (viewmobj)
heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec;
else
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
*tempsec = *sec;
@ -272,7 +251,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->ceilingheight = s->ceilingheight;
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
tempsec->floorpic = s->floorpic;
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
: 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)
{ // Above-ceiling hack
tempsec->ceilingheight = s->ceilingheight;
@ -382,22 +361,25 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// R_AddLine
// 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;
angle_t angle1, angle2, span, tspan;
static sector_t tempsec;
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))
return;
// big room fix
angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y);
angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y);
curline = line;
angle1 = R_PointToAngleEx(viewcontext->x, viewcontext->y, line->v1->x, line->v1->y);
angle2 = R_PointToAngleEx(viewcontext->x, viewcontext->y, line->v2->x, line->v2->y);
bspcontext->curline = line;
// Clip to view edges.
span = angle1 - angle2;
@ -407,9 +389,9 @@ static void R_AddLine(seg_t *line)
return;
// Global angle needed by segcalc.
rw_angle1 = angle1;
angle1 -= viewangle;
angle2 -= viewangle;
wallcontext.angle1 = angle1;
angle1 -= viewcontext->angle;
angle2 -= viewcontext->angle;
tspan = angle1 + clipangle;
if (tspan > doubleclipangle)
@ -440,18 +422,21 @@ static void R_AddLine(seg_t *line)
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
x1 = max(rendercontext->begincolumn, x1);
x2 = min(rendercontext->endcolumn, x2);
// Does not cross a pixel?
if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
return;
backsector = line->backsector;
bspcontext->backsector = line->backsector;
// Portal line
if (line->linedef->special == 40 && line->side == 0)
{
// Render portal if recursiveness limit hasn't been reached.
// Otherwise, render the wall normally.
if (portalrender < cv_maxportals.value)
if (bspcontext->portalrender < cv_maxportals.value)
{
size_t p;
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))
continue;
Portal_Add2Lines(li1, li2, x1, x2);
Portal_Add2Lines(rendercontext, li1, li2, x1, x2);
goto clipsolid;
}
}
}
// Single sided line?
if (!backsector)
if (!bspcontext->backsector)
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;
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum)
if (bspcontext->backsector->floorpic == skyflatnum && bspcontext->frontsector->floorpic == skyflatnum)
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
{
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors)
|| Tag_Compare(&frontsector->tags, &backsector->tags)))
&& ((!bspcontext->frontsector->ffloors && !bspcontext->backsector->ffloors)
|| Tag_Compare(&bspcontext->frontsector->tags, &bspcontext->backsector->tags)))
return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead
}
// 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 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); \
end2 = P_GetZAt(slope, line->v2->x, line->v2->y, normalheight);
SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector-> floorheight)
SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight)
SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector-> floorheight)
SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight)
SLOPEPARAMS(bspcontext->frontsector->f_slope, frontf1, frontf2, bspcontext->frontsector-> floorheight)
SLOPEPARAMS(bspcontext->frontsector->c_slope, frontc1, frontc2, bspcontext->frontsector->ceilingheight)
SLOPEPARAMS( bspcontext->backsector->f_slope, backf1, backf2, bspcontext->backsector-> floorheight)
SLOPEPARAMS( bspcontext->backsector->c_slope, backc1, backc2, bspcontext->backsector->ceilingheight)
#undef SLOPEPARAMS
// if both ceilings are skies, consider it always "open"
// 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
doorclosed = (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture));
bspcontext->doorclosed = (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || bspcontext->curline->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || bspcontext->curline->sidedef->bottomtexture));
if (doorclosed)
if (bspcontext->doorclosed)
goto clipsolid;
}
@ -541,40 +528,39 @@ static void R_AddLine(seg_t *line)
// same for floors
if (!bothceilingssky && !bothfloorssky)
{
if (backsector->ceilingheight <= frontsector->floorheight
|| backsector->floorheight >= frontsector->ceilingheight)
if (bspcontext->backsector->ceilingheight <= bspcontext->frontsector->floorheight
|| bspcontext->backsector->floorheight >= bspcontext->frontsector->ceilingheight)
{
goto clipsolid;
}
// Check for automap fix. Store in doorclosed for r_segs.c
doorclosed = R_DoorClosed();
if (doorclosed)
bspcontext->doorclosed = R_DoorClosed(bspcontext);
if (bspcontext->doorclosed)
goto clipsolid;
}
// Window.
if (!bothceilingssky) // ceilings are always the "same" when sky
if (backsector->ceilingheight != frontsector->ceilingheight)
if (bspcontext->backsector->ceilingheight != bspcontext->frontsector->ceilingheight)
goto clippass;
if (!bothfloorssky) // floors are always the "same" when sky
if (backsector->floorheight != frontsector->floorheight)
if (bspcontext->backsector->floorheight != bspcontext->frontsector->floorheight)
goto clippass;
}
// Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides, identical light levels on both sides,
// and no middle texture.
if (R_IsEmptyLine(line, frontsector, backsector))
if (R_IsEmptyLine(line, bspcontext->frontsector, bspcontext->backsector))
return;
clippass:
R_ClipPassWallSegment(x1, x2 - 1);
R_ClipPassWallSegment(rendercontext, &wallcontext, x1, x2 - 1);
return;
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}
};
static boolean R_CheckBBox(const fixed_t *bspcoord)
static boolean R_CheckBBox(rendercontext_t *context, const fixed_t *bspcoord)
{
angle_t angle1, angle2;
INT32 sx1, sx2, boxpos;
const INT32* check;
cliprange_t *start;
viewcontext_t *viewcontext = &context->viewcontext;
// 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;
check = checkcoord[boxpos];
// big room fix
angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
angle1 = R_PointToAngleEx(viewcontext->x, viewcontext->y, bspcoord[check[0]], bspcoord[check[1]]) - viewcontext->angle;
angle2 = R_PointToAngleEx(viewcontext->x, viewcontext->y, bspcoord[check[2]], bspcoord[check[3]]) - viewcontext->angle;
if ((signed)angle1 < (signed)angle2)
{
@ -641,7 +629,7 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
// Does not cross a pixel.
if (sx1 >= sx2) return false;
start = solidsegs;
start = context->bspcontext.solidsegs;
while (start->last < sx2)
start++;
@ -789,7 +777,7 @@ static int R_PolysegCompare(const void *p1, const void *p2)
// haleyjd 02/19/06
// 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;
size_t i, j;
@ -804,7 +792,7 @@ static void R_AddPolyObjects(subsector_t *sub)
}
// for render stats
ps_numpolyobjects += numpolys;
ps_numpolyobjects[context->num] += numpolys;
// sort polyobjects
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);
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.
//
drawseg_t *firstseg;
static void R_Subsector(size_t num)
static void R_Subsector(rendercontext_t *context, size_t num)
{
INT32 count, floorlightlevel, ceilinglightlevel, light;
seg_t *line;
subsector_t *sub;
static sector_t tempsec; // Deep water hack
extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap;
fixed_t floorcenterz, ceilingcenterz;
sector_t *frontsector;
bspcontext_t *bspcontext = &context->bspcontext;
planecontext_t *planecontext = &context->planecontext;
viewcontext_t *viewcontext = &context->viewcontext;
#ifdef RANGECHECK
if (num >= numsubsectors)
@ -847,12 +837,11 @@ static void R_Subsector(size_t num)
return;
sub = &subsectors[num];
frontsector = sub->sector;
count = sub->numlines;
line = &segs[sub->firstline];
// 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;
@ -866,9 +855,12 @@ static void R_Subsector(size_t num)
{
frontsector->numlights = sub->sector->numlights = 0;
R_Prep3DFloors(frontsector);
Lock_state();
sub->sector->lightlist = frontsector->lightlist;
sub->sector->numlights = frontsector->numlights;
sub->sector->moved = frontsector->moved = false;
Unlock_state();
}
light = R_GetPlaneLight(frontsector, floorcenterz, false);
@ -883,106 +875,109 @@ static void R_Subsector(size_t num)
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->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);
}
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->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,
ceilingcolormap, NULL, NULL, frontsector->c_slope);
}
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)
{
ffloor_t *rover;
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))
continue;
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;
continue;
}
}
ffloor[numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL;
planecontext->ffloor[planecontext->numffloors].plane = 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);
if (planecenterz <= ceilingcenterz
&& planecenterz >= floorcenterz
&& ((viewz < 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)))
|| (viewcontext->z > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
{
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,
*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.
if (ffloor[numffloors].slope)
if (planecontext->ffloor[planecontext->numffloors].slope)
frontsector->hasslope = true;
ffloor[numffloors].height = heightcheck;
ffloor[numffloors].ffloor = rover;
numffloors++;
planecontext->ffloor[planecontext->numffloors].height = heightcheck;
planecontext->ffloor[planecontext->numffloors].ffloor = rover;
planecontext->numffloors++;
}
if (numffloors >= MAXFFLOORS)
if (planecontext->numffloors >= MAXFFLOORS)
break;
ffloor[numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL;
planecontext->ffloor[planecontext->numffloors].plane = 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);
if (planecenterz >= floorcenterz
&& planecenterz <= ceilingcenterz
&& ((viewz > 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)))
|| (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].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.
if (ffloor[numffloors].slope)
if (planecontext->ffloor[planecontext->numffloors].slope)
frontsector->hasslope = true;
ffloor[numffloors].height = heightcheck;
ffloor[numffloors].ffloor = rover;
numffloors++;
planecontext->ffloor[planecontext->numffloors].height = heightcheck;
planecontext->ffloor[planecontext->numffloors].ffloor = rover;
planecontext->numffloors++;
}
}
}
@ -995,7 +990,7 @@ static void R_Subsector(size_t num)
while (po)
{
if (numffloors >= MAXFFLOORS)
if (planecontext->numffloors >= MAXFFLOORS)
break;
if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes
@ -1005,81 +1000,84 @@ static void R_Subsector(size_t num)
}
polysec = po->lines[0]->backsector;
ffloor[numffloors].plane = NULL;
planecontext->ffloor[planecontext->numffloors].plane = NULL;
if (polysec->floorheight <= ceilingcenterz
&& polysec->floorheight >= floorcenterz
&& (viewz < polysec->floorheight))
&& (viewcontext->z < polysec->floorheight))
{
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewcontext->z < polysec->floorheight);
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,
polysec->floorpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually?
ffloor[numffloors].height = polysec->floorheight;
ffloor[numffloors].polyobj = po;
ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++;
planecontext->ffloor[planecontext->numffloors].height = polysec->floorheight;
planecontext->ffloor[planecontext->numffloors].polyobj = po;
planecontext->ffloor[planecontext->numffloors].slope = NULL;
//planecontext->ffloor[planecontext->numffloors].ffloor = rover;
po->visplane = planecontext->ffloor[planecontext->numffloors].plane;
planecontext->numffloors++;
}
if (numffloors >= MAXFFLOORS)
if (planecontext->numffloors >= MAXFFLOORS)
break;
ffloor[numffloors].plane = NULL;
planecontext->ffloor[planecontext->numffloors].plane = NULL;
if (polysec->ceilingheight >= floorcenterz
&& polysec->ceilingheight <= ceilingcenterz
&& (viewz > polysec->ceilingheight))
&& (viewcontext->z > polysec->ceilingheight))
{
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewcontext->z < polysec->floorheight);
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->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually?
ffloor[numffloors].polyobj = po;
ffloor[numffloors].height = polysec->ceilingheight;
ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++;
planecontext->ffloor[planecontext->numffloors].polyobj = po;
planecontext->ffloor[planecontext->numffloors].height = polysec->ceilingheight;
planecontext->ffloor[planecontext->numffloors].slope = NULL;
//planecontext->ffloor[planecontext->numffloors].ffloor = rover;
po->visplane = planecontext->ffloor[planecontext->numffloors].plane;
planecontext->numffloors++;
}
po = (polyobj_t *)(po->link.next);
}
}
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.
//
// 10/98 killough:
//
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!!
// 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,
// like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2);
bspcontext->frontsector = frontsector;
firstseg = NULL;
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.
//
// 10/98 killough:
//
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!!
// 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,
// like passing it as an argument.
R_AddSprites(context, sub->sector, (floorlightlevel+ceilinglightlevel)/2);
bspcontext->firstseg = NULL;
// haleyjd 02/19/06: draw polyobjects before static lines
if (sub->polyList)
R_AddPolyObjects(sub);
R_AddPolyObjects(context, sub);
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
R_AddLine(line);
R_AddLine(context, 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
void R_RenderBSPNode(INT32 bspnum)
void R_RenderBSPNode(rendercontext_t *context, INT32 bspnum)
{
node_t *bsp;
INT32 side;
ps_numbspcalls++;
ps_numbspcalls[context->num]++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{
bsp = &nodes[bspnum];
// 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.
R_RenderBSPNode(bsp->children[side]);
R_RenderBSPNode(context, bsp->children[side]);
// Possibly divide back space.
if (!R_CheckBBox(bsp->bbox[side^1]))
if (!R_CheckBBox(context, bsp->bbox[side^1]))
return;
bspnum = bsp->children[side^1];
}
// PORTAL CULLING
if (portalcullsector) {
if (context->bspcontext.portalcullsector) {
sector_t *sect = subsectors[bspnum & ~NF_SUBSECTOR].sector;
if (sect != portalcullsector)
if (sect != context->bspcontext.portalcullsector)
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
#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 drawseg_t *curdrawsegs;
extern drawseg_t *drawsegs;
extern drawseg_t *ds_p;
extern INT32 doorclosed;
struct bspcontext_s;
struct rendercontext_s;
struct viewcontext_s;
// BSP?
void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum);
void R_ClearClipSegs(struct bspcontext_s *context, INT32 start, INT32 end);
void R_ClearDrawSegs(struct bspcontext_s *context);
void R_RenderBSPNode(struct rendercontext_s *context, INT32 bspnum);
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 polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back);
sector_t *R_FakeFlat(struct viewcontext_s *viewcontext, sector_t *sec, sector_t *tempsec,
INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back);
boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
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;
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()
if (rendermode != render_soft)
return;
// if (rendermode != render_soft)
// return;
// Precache flats.
flatmemory = P_PrecacheLevelFlats();

View file

@ -22,7 +22,7 @@
// SECTORS do store MObjs anyway.
#include "p_mobj.h"
#include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT
#include "screen.h"
#ifdef HWRENDER
#include "m_aatree.h"
@ -41,6 +41,9 @@ typedef struct
INT32 last;
} cliprange_t;
// Fix from boom.
#define MAXSEGS (MAXVIDWIDTH/2+1)
// Silhouette, needed for clipping segs (mainly) and sprites representing things.
#define SIL_NONE 0
#define SIL_BOTTOM 1
@ -56,6 +59,15 @@ typedef UINT8 lighttable_t;
#define CMF_FADEFULLBRIGHTSPRITES 1
#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.
typedef struct extracolormap_s
{

View file

@ -62,14 +62,6 @@ UINT8 *topleft;
// 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
// -----------------------
@ -78,48 +70,11 @@ UINT8 *dc_source;
UINT8 *transtables; // translucency tables
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
// =========================================================================
INT32 ds_y, ds_x1, ds_x2;
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;
float focallengthf;
// =========================================================================
// 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];
}
#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.
@ -589,13 +553,16 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
if (flags & GTC_CACHE)
{
Lock_state();
// Allocate table for skin if necessary
if (!translationtablecache[skintableindex])
translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL);
Unlock_state();
// Get colormap
ret = translationtablecache[skintableindex][color];
Lock_state();
// Rebuild the cache if necessary
if (skincolor_modified[color])
{
@ -605,18 +572,21 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
skincolor_modified[color] = false;
}
Unlock_state();
}
else ret = NULL;
// Generate the colormap if necessary
if (!ret)
{
Lock_state();
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8);
R_GenerateTranslationColormap(ret, skinnum, color);
// Cache the colormap if desired
if (flags & GTC_CACHE)
translationtablecache[skintableindex][color] = ret;
Unlock_state();
}
return ret;
@ -887,13 +857,37 @@ void R_DrawViewBorder(void)
// 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_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 UINT8 *topleft;
// -------------------------
// 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;
extern float focallengthf;
/// \brief Top border
#define BRDR_T 0
@ -163,85 +109,180 @@ void R_DrawViewBorder(void);
#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
// -----------------
void R_DrawColumn_8(void);
void R_DrawShadeColumn_8(void);
void R_DrawTranslucentColumn_8(void);
void R_DrawTranslatedColumn_8(void);
void R_DrawTranslatedTranslucentColumn_8(void);
void R_Draw2sMultiPatchColumn_8(void);
void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawFogColumn_8(void);
void R_DrawColumnShadowed_8(void);
void R_DrawColumn_8(colcontext_t *dc);
void R_DrawShadeColumn_8(colcontext_t *dc);
void R_DrawTranslucentColumn_8(colcontext_t *dc);
void R_DrawTranslatedColumn_8(colcontext_t *dc);
void R_DrawTranslatedTranslucentColumn_8(colcontext_t *dc);
void R_Draw2sMultiPatchColumn_8(colcontext_t *dc);
void R_Draw2sMultiPatchTranslucentColumn_8(colcontext_t *dc);
void R_DrawFogColumn_8(colcontext_t *dc);
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_DrawTranslucentSpan_8(void);
void R_DrawTiltedSpan_8(void);
void R_DrawTiltedTranslucentSpan_8(void);
void R_DrawSplat_8(spancontext_t *ds);
void R_DrawTranslucentSplat_8(spancontext_t *ds);
void R_DrawTiltedSplat_8(spancontext_t *ds);
void R_DrawSplat_8(void);
void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSplat_8(void);
void R_DrawFloorSprite_8(spancontext_t *ds);
void R_DrawTranslucentFloorSprite_8(spancontext_t *ds);
void R_DrawTiltedFloorSprite_8(spancontext_t *ds);
void R_DrawTiltedTranslucentFloorSprite_8(spancontext_t *ds);
void R_DrawFloorSprite_8(void);
void R_DrawTranslucentFloorSprite_8(void);
void R_DrawTiltedFloorSprite_8(void);
void R_DrawTiltedTranslucentFloorSprite_8(void);
void R_DrawTranslucentWaterSpan_8(spancontext_t *ds);
void R_DrawTiltedTranslucentWaterSpan_8(spancontext_t *ds);
void R_CalcTiltedLighting(fixed_t start, fixed_t end);
extern INT32 tiltlighting[MAXVIDWIDTH];
void R_DrawTranslucentWaterSpan_8(void);
void R_DrawTiltedTranslucentWaterSpan_8(void);
void R_DrawFogSpan_8(void);
void R_DrawFogSpan_8(spancontext_t *ds);
// Lactozilla: Non-powers-of-two
void R_DrawSpan_NPO2_8(void);
void R_DrawTranslucentSpan_NPO2_8(void);
void R_DrawTiltedSpan_NPO2_8(void);
void R_DrawTiltedTranslucentSpan_NPO2_8(void);
void R_DrawSpan_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentSpan_NPO2_8(spancontext_t *ds);
void R_DrawSplat_NPO2_8(void);
void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSplat_NPO2_8(void);
void R_DrawSplat_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentSplat_NPO2_8(spancontext_t *ds);
void R_DrawTiltedSplat_NPO2_8(spancontext_t *ds);
void R_DrawFloorSprite_NPO2_8(void);
void R_DrawTranslucentFloorSprite_NPO2_8(void);
void R_DrawTiltedFloorSprite_NPO2_8(void);
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void);
void R_DrawFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTiltedFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(spancontext_t *ds);
void R_DrawTranslucentWaterSpan_NPO2_8(void);
void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
#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
void R_DrawTranslucentWaterSpan_NPO2_8(spancontext_t *ds);
void R_DrawTiltedTranslucentWaterSpan_NPO2_8(spancontext_t *ds);
// =========================================================================
#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_things.h"
#include "r_draw.h"
extern drawseg_t *firstseg;
#include "r_context.h"
void SplitScreen_OnChange(void);

View file

@ -53,6 +53,22 @@ INT64 mytotal = 0;
// Fineangles in the SCREENWIDTH wide window.
#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
size_t validcount = 1;
@ -102,20 +118,21 @@ extracolormap_t *extra_colormaps = NULL;
// Render stats
precise_t ps_prevframetime = 0;
precise_t ps_rendercalltime = 0;
precise_t ps_postprocesstime = 0;
precise_t ps_uitime = 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_portaltime = 0;
precise_t ps_sw_planetime = 0;
precise_t ps_sw_maskedtime = 0;
precise_t ps_sw_spritecliptime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_portaltime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_planetime[MAX_RENDER_THREADS] = {0};
precise_t ps_sw_maskedtime[MAX_RENDER_THREADS] = {0};
int ps_numbspcalls = 0;
int ps_numsprites = 0;
int ps_numdrawnodes = 0;
int ps_numpolyobjects = 0;
int ps_numbspcalls[MAX_RENDER_THREADS] = {0};
int ps_numsprites[MAX_RENDER_THREADS] = {0};
int ps_numdrawnodes[MAX_RENDER_THREADS] = {0};
int ps_numpolyobjects[MAX_RENDER_THREADS] = {0};
static CV_PossibleValue_t drawdist_cons_t[] = {
{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 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 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_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);
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_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;
}
//
// 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
// 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);
}
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
@ -960,7 +1229,7 @@ void R_ExecuteSetViewSize(void)
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
if (ds_su)
/*if (ds_su)
Z_Free(ds_su);
if (ds_sv)
Z_Free(ds_sv);
@ -968,7 +1237,7 @@ void R_ExecuteSetViewSize(void)
Z_Free(ds_sz);
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));
@ -1024,7 +1293,7 @@ void R_Init(void)
//I_OutputMsg("\nR_InitTranslucencyTables\n");
R_InitTranslucencyTables();
R_InitDrawNodes();
R_InitContexts();
framecount = 0;
}
@ -1394,63 +1663,57 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
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
// ================
// FAB NOTE FOR WIN32 PORT !! I'm not finished already,
// 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..
// I mean, there is a win16lock() or something that lasts all the rendering,
// so maybe we should release screen lock before each netupdate below..?
static void R_PrepareViewContext(viewcontext_t *context)
{
context->x = viewx;
context->y = viewy;
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)
{
UINT8 nummasks = 1;
maskcount_t* masks = malloc(sizeof(maskcount_t));
INT32 currcontext;
INT32 finishedcontexts = 0;
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);
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.
NetUpdate();
// The head node is the last node output.
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)
#ifdef HAVE_THREADS
if (cv_numthreads.value != numusablerendercontexts)
{
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++)
{
#ifdef HAVE_THREADS
if (renderthreaded)
I_atomic_exchange(&renderdatas[currcontext].framewaiting, 1);
else
#endif
{
portalrender = portal->pass; // Recursiveness depth.
R_ClearFFloorClips();
// Apply the viewpoint stored for the portal.
R_PortalFrame(portal);
// Hack in the clipsegs to delimit the starting
// 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);
R_RenderViewContext(&renderdatas[currcontext].context);
finishedcontexts++;
}
}
ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime;
ps_sw_planetime = I_GetPreciseTime();
R_DrawPlanes();
ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime;
// draw mid texture and sprite
// And now 3D floors/sides!
ps_sw_maskedtime = I_GetPreciseTime();
R_DrawMasked(masks, nummasks);
ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime;
free(masks);
#ifdef HAVE_THREADS
while (renderthreaded && finishedcontexts != numusablerendercontexts)
{
for (currcontext = 0; currcontext < numusablerendercontexts; currcontext++)
finishedcontexts += I_atomic_exchange(&renderdatas[currcontext].framefinished, 0);
}
#endif
}
// =========================================================================
@ -1639,6 +1834,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_translucenthud);
CV_RegisterVar(&cv_maxportals);
CV_RegisterVar(&cv_numthreads);
CV_RegisterVar(&cv_movebob);
}

View file

@ -29,6 +29,10 @@ extern fixed_t centerxfrac, centeryfrac;
extern fixed_t projection, projectiony;
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!
#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_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_PointInSubsectorOrNull(fixed_t x, fixed_t y);
@ -78,22 +81,23 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
// Render stats
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_postprocesstime;
extern precise_t ps_uitime;
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_portaltime;
extern precise_t ps_sw_planetime;
extern precise_t ps_sw_maskedtime;
extern precise_t ps_sw_spritecliptime[MAX_RENDER_THREADS];
extern precise_t ps_sw_portaltime[MAX_RENDER_THREADS];
extern precise_t ps_sw_planetime[MAX_RENDER_THREADS];
extern precise_t ps_sw_maskedtime[MAX_RENDER_THREADS];
extern int ps_numbspcalls;
extern int ps_numsprites;
extern int ps_numdrawnodes;
extern int ps_numpolyobjects;
extern int ps_numbspcalls[MAX_RENDER_THREADS];
extern int ps_numsprites[MAX_RENDER_THREADS];
extern int ps_numdrawnodes[MAX_RENDER_THREADS];
extern int ps_numpolyobjects[MAX_RENDER_THREADS];
//
// REFRESH - the actual rendering functions.
@ -131,6 +135,8 @@ void R_SkyboxFrame(player_t *player);
boolean R_ViewpointHasChasecam(player_t *player);
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox);
void R_StopThreads(void);
// Called by D_Display.
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;
} 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
{
visplane_t *plane;
struct visplane_s *plane;
fixed_t height;
fixed_t f_pos; // F for Front sector
fixed_t b_pos; // B for Back sector
@ -117,10 +74,36 @@ typedef struct planemgr_s
struct ffloor_s *ffloor;
polyobj_t *polyobj;
} visffloor_t;
} planemgr_t;
extern visffloor_t ffloor[MAXFFLOORS];
extern INT32 numffloors;
// Visplane related.
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

View file

@ -14,27 +14,17 @@
#include "r_portal.h"
#include "r_plane.h"
#include "r_main.h"
#include "r_context.h"
#include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints
#include "z_zone.h"
#include "r_things.h"
#include "r_sky.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */
// 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)
void Portal_InitList (bspcontext_t *bspcontext)
{
portalrender = 0;
portal_base = portal_cap = NULL;
bspcontext->portalrender = 0;
bspcontext->portal_base = bspcontext->portal_cap = NULL;
}
/** 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
* lines into portals.
*/
void Portal_ClipRange (portal_t* portal)
void Portal_ClipRange (planecontext_t *planecontext, portal_t* portal)
{
INT32 start = portal->start;
INT32 end = portal->end;
@ -54,18 +44,18 @@ void Portal_ClipRange (portal_t* portal)
INT32 i;
for (i = 0; i < end-start; i++)
{
*ceil = ceilingclip[start+i];
*ceil = planecontext->ceilingclip[start+i];
ceil++;
*floor = floorclip[start+i];
*floor = planecontext->floorclip[start+i];
floor++;
*scale = frontscale[start+i];
*scale = planecontext->frontscale[start+i];
scale++;
}
}
/** 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 start = portal->start;
@ -76,28 +66,28 @@ void Portal_ClipApply (const portal_t* portal)
for (i = 0; i < end-start; i++)
{
ceilingclip[start+i] = *ceil;
planecontext->ceilingclip[start+i] = *ceil;
ceil++;
floorclip[start+i] = *floor;
planecontext->floorclip[start+i] = *floor;
floor++;
frontscale[start+i] = *scale;
planecontext->frontscale[start+i] = *scale;
scale++;
}
// HACKS FOLLOW
for (i = 0; i < start; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
planecontext->floorclip[i] = -1;
planecontext->ceilingclip[i] = (INT16)viewheight;
}
for (i = end; i < vid.width; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
planecontext->floorclip[i] = -1;
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);
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);
// Linked list.
if (!portal_base)
if (!context->portal_base)
{
portal_base = portal;
portal_cap = portal;
context->portal_base = portal;
context->portal_cap = portal;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
context->portal_cap->next = portal;
context->portal_cap = portal;
}
portal->next = NULL;
@ -125,14 +115,14 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
portal->end = x2;
// Increase recursion level.
portal->pass = portalrender+1;
portal->pass = context->portalrender+1;
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->floorclip);
Z_Free(portal->frontscale);
@ -149,9 +139,10 @@ void Portal_Remove (portal_t* portal)
* When the portal renders, it will create the illusion of
* 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
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.y = (dest->v1->y + dest->v2->y) / 2;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2(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, context->viewcontext.x, context->viewcontext.y);
angtopoint += dangle;
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
portal->viewz = context->viewcontext.z + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = context->viewcontext.angle + dangle;
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.
@ -256,7 +247,7 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16*
* Applies the necessary offsets and rotation to give
* 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;
mapheader_t *mh;
@ -265,14 +256,14 @@ void Portal_AddSkybox (const visplane_t* plane)
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal = Portal_Add(start, end);
portal = Portal_Add(bspcontext, start, end);
Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y;
portal->viewz = skyboxmo[0]->z;
portal->viewangle = viewangle + skyboxmo[0]->angle;
portal->viewangle = viewcontext->angle + skyboxmo[0]->angle;
mh = mapheaderinfo[gamemap-1];
@ -283,14 +274,14 @@ void Portal_AddSkybox (const visplane_t* plane)
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
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)
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex;
x = (viewcontext->x - skyboxmo[1]->x) * -mh->skybox_scalex;
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)
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.
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)
portal->viewz += viewz / mh->skybox_scalez;
portal->viewz += viewcontext->z / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
portal->viewz += viewz * -mh->skybox_scalez;
portal->viewz += viewcontext->z * -mh->skybox_scalez;
portal->clipline = -1;
}
@ -308,7 +299,7 @@ void Portal_AddSkybox (const visplane_t* plane)
/** Creates portals for the currently existing sky visplanes.
* The visplanes are also removed and cleared from the list.
*/
void Portal_AddSkyboxPortals (void)
void Portal_AddSkyboxPortals (rendercontext_t *context)
{
visplane_t *pl;
INT32 i;
@ -316,11 +307,11 @@ void Portal_AddSkyboxPortals (void)
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)
{
Portal_AddSkybox(pl);
Portal_AddSkybox(&context->bspcontext, &context->viewcontext, pl);
pl->minx = 0;
pl->maxx = -1;

View file

@ -41,21 +41,19 @@ typedef struct portal_s
fixed_t *frontscale;/**< Temporary screen bottom clipping array. */
} portal_t;
extern portal_t* portal_base;
extern portal_t* portal_cap;
extern UINT8 portalrender;
struct bspcontext_s;
struct planecontext_s;
struct rendercontext_s;
struct viewcontext_s;
extern line_t *portalclipline;
extern sector_t *portalcullsector;
extern INT32 portalclipstart, portalclipend;
void Portal_InitList (struct bspcontext_s *bspcontext);
void Portal_Remove (struct bspcontext_s *context, portal_t* portal);
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_Remove (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 (struct planecontext_s *planecontext, portal_t* portal);
void Portal_ClipApply (struct planecontext_s *planecontext, const portal_t* portal);
void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
void Portal_AddSkyboxPortals (struct rendercontext_s *context);
#endif

File diff suppressed because it is too large Load diff

View file

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

View file

@ -54,9 +54,6 @@ INT32 globallevelskynum;
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
*/
void R_SetupSkyDraw(void)

View file

@ -13,132 +13,116 @@
#include "r_draw.h"
#include "r_main.h"
#include "r_splats.h"
#include "r_context.h"
#include "r_bsp.h"
#include "p_local.h"
#include "p_slopes.h"
#include "w_wad.h"
#include "z_zone.h"
struct rastery_s *prastertab; // for ASM code
static struct rastery_s rastertab[MAXVIDHEIGHT];
static void prepare_rastertab(void);
static void prepare_rastertab(planecontext_t *planecontext);
// ==========================================================================
// 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
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)
static void rasterize_segment_tex(planecontext_t *planecontext, 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);
fixed_t xs, xe, count;
fixed_t dx0, dx1;
if (y1 == y2)
return;
}
else
#endif
if (y2 > y1)
{
fixed_t xs, xe, count;
fixed_t dx0, dx1;
count = (y2-y1)+1;
if (y1 == y2)
return;
dx0 = FixedDiv((x2-x1)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv2-tv1)<<FRACBITS, count<<FRACBITS);
if (y2 > y1)
xs = x1 << FRACBITS;
xe = tv1 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
{
count = (y2-y1)+1;
dx0 = FixedDiv((x2-x1)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv2-tv1)<<FRACBITS, count<<FRACBITS);
xs = x1 << FRACBITS;
xe = tv1 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
for (;;)
{
for (;;)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = xe;
rastertab[y1].ty2 = tc;
planecontext->rastertab[y1].maxx = xs;
planecontext->rastertab[y1].tx2 = xe;
planecontext->rastertab[y1].ty2 = tc;
xs += dx0;
xe += dx1;
y1++;
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
}
else
{
for (;;)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = tc;
rastertab[y1].ty2 = xe;
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
if (count-- < 1) break;
}
}
else
{
count = (y1-y2)+1;
dx0 = FixedDiv((x1-x2)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv1-tv2)<<FRACBITS, count<<FRACBITS);
xs = x2 << FRACBITS;
xe = tv2 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
for (;;)
{
for (;;)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = xe;
rastertab[y2].ty1 = tc;
planecontext->rastertab[y1].maxx = xs;
planecontext->rastertab[y1].tx2 = tc;
planecontext->rastertab[y1].ty2 = xe;
xs += dx0;
xe += dx1;
y2++;
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
if (count-- < 1) break;
}
else
}
}
else
{
count = (y1-y2)+1;
dx0 = FixedDiv((x1-x2)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv1-tv2)<<FRACBITS, count<<FRACBITS);
xs = x2 << FRACBITS;
xe = tv2 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
{
for (;;)
{
for (;;)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = tc;
rastertab[y2].ty1 = xe;
planecontext->rastertab[y2].minx = xs;
planecontext->rastertab[y2].tx1 = xe;
planecontext->rastertab[y2].ty1 = tc;
xs += dx0;
xe += dx1;
y2++;
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
if (count-- < 1) break;
}
}
else
{
for (;;)
{
planecontext->rastertab[y2].minx = xs;
planecontext->rastertab[y2].tx1 = tc;
planecontext->rastertab[y2].ty1 = xe;
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
}
}
}
void R_DrawFloorSplat(vissprite_t *spr)
void R_DrawFloorSplat(rendercontext_t *context, vissprite_t *spr)
{
floorsplat_t splat;
mobj_t *mobj = spr->mobj;
@ -308,7 +292,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
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
// 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
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 step;
planecontext_t *planecontext = &context->planecontext;
colcontext_t *dc = &context->colcontext;
spancontext_t *ds = &context->spancontext;
int spanfunctype = SPANDRAWFUNC_SPRITE;
prepare_rastertab();
prepare_rastertab(planecontext);
#define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \
x1 = verts[vnum1].x; \
@ -372,7 +360,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
} \
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) \
miny = ry1; \
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
RASTERPARAMS(0,3,pSplat->width-1,0,0,1);
ds_source = (UINT8 *)pSplat->pic;
ds_flatwidth = pSplat->width;
ds_flatheight = pSplat->height;
ds->source = (UINT8 *)pSplat->pic;
ds->flatwidth = pSplat->width;
ds->flatheight = pSplat->height;
if (R_CheckPowersOfTwo())
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
if (R_CheckPowersOfTwo(ds->flatwidth, ds->flatheight))
R_CheckFlatLength(ds, ds->flatwidth * ds->flatheight);
if (pSplat->slope)
{
R_SetTiltedSpan(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_CalculateSlopeVectors();
R_SetTiltedSpan(ds, 0);
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(ds);
spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
}
else
{
planeheight = abs(pSplat->z - vis->viewpoint.z);
planecontext->planeheight = abs(pSplat->z - vis->viewpoint.z);
if (pSplat->angle)
{
memset(cachedheight, 0, sizeof(cachedheight));
memset(planecontext->cachedheight, 0, sizeof(planecontext->cachedheight));
// Add the view offset, rotated by the plane angle.
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_translation = R_GetSpriteTranslation(vis);
if (ds_translation == NULL)
ds_translation = colormaps;
ds->colormap = vis->colormap;
ds->translation = R_GetSpriteTranslation(vis);
if (ds->translation == NULL)
ds->translation = colormaps;
if (vis->extra_colormap)
{
if (!ds_colormap)
ds_colormap = vis->extra_colormap->colormap;
if (!ds->colormap)
ds->colormap = vis->extra_colormap->colormap;
else
ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps];
ds->colormap = &vis->extra_colormap->colormap[ds->colormap - colormaps];
}
if (vis->transmap)
{
ds_transmap = vis->transmap;
ds->transmap = vis->transmap;
if (pSplat->slope)
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
@ -446,12 +434,12 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
}
else
ds_transmap = NULL;
ds->transmap = NULL;
if (ds_powersoftwo)
spanfunc = spanfuncs[spanfunctype];
if (ds->powersoftwo)
ds->func = spanfuncs[spanfunctype];
else
spanfunc = spanfuncs_npo2[spanfunctype];
ds->func = spanfuncs_npo2[spanfunctype];
if (maxy >= vid.height)
maxy = vid.height-1;
@ -460,8 +448,8 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
{
boolean cliptab[MAXVIDWIDTH+1];
x1 = rastertab[y].minx>>FRACBITS;
x2 = rastertab[y].maxx>>FRACBITS;
x1 = planecontext->rastertab[y].minx>>FRACBITS;
x2 = planecontext->rastertab[y].maxx>>FRACBITS;
if (x1 > x2)
{
@ -482,7 +470,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
continue;
for (i = x1; i <= x2; i++)
cliptab[i] = (y >= mfloorclip[i]);
cliptab[i] = (y >= dc->mfloorclip[i]);
// clip left
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 planesin = FINESINE(angle);
if (planeheight != cachedheight[y])
if (planecontext->planeheight != planecontext->cachedheight[y])
{
cachedheight[y] = planeheight;
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
planecontext->cachedheight[y] = planeheight;
distance = planecontext->cacheddistance[y] = FixedMul(planeheight, yslope[y]);
span = abs(centery - y);
if (span) // Don't divide by zero
@ -530,43 +518,43 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
else
xstep = ystep = FRACUNIT;
cachedxstep[y] = xstep;
cachedystep[y] = ystep;
planecontext->cachedxstep[y] = xstep;
planecontext->cachedystep[y] = ystep;
}
else
{
distance = cacheddistance[y];
xstep = cachedxstep[y];
ystep = cachedystep[y];
distance = planecontext->cacheddistance[y];
xstep = planecontext->cachedxstep[y];
ystep = planecontext->cachedystep[y];
}
ds_xstep = FixedDiv(xstep, pSplat->xscale);
ds_ystep = FixedDiv(ystep, pSplat->yscale);
ds->xstep = FixedDiv(xstep, pSplat->xscale);
ds->ystep = FixedDiv(ystep, pSplat->yscale);
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->xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale);
ds->yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale);
}
ds_y = y;
ds_x1 = x1;
ds_x2 = x2;
spanfunc();
ds->y = y;
ds->x1 = x1;
ds->x2 = x2;
ds->func(ds);
rastertab[y].minx = INT32_MAX;
rastertab[y].maxx = INT32_MIN;
planecontext->rastertab[y].minx = INT32_MAX;
planecontext->rastertab[y].maxx = INT32_MIN;
}
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;
prastertab = rastertab;
planecontext->prastertab = planecontext->rastertab;
for (i = 0; i < vid.height; i++)
{
rastertab[i].minx = INT32_MAX;
rastertab[i].maxx = INT32_MIN;
planecontext->rastertab[i].minx = INT32_MAX;
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 tx2, ty2; // end points in texture at this line
};
extern struct rastery_s *prastertab; // for ASM code
typedef struct floorsplat_s
{
@ -41,6 +40,8 @@ typedef struct floorsplat_s
mobj_t *mobj; // Mobj it is tied to
} 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__*/

View file

@ -90,6 +90,8 @@ extern sector_t *viewsector;
extern player_t *viewplayer;
extern mobj_t *r_viewmobj;
extern consvar_t cv_numthreads;
extern consvar_t cv_allowmlook;
extern consvar_t cv_maxportals;
@ -99,10 +101,4 @@ extern angle_t doubleclipangle;
extern INT32 viewangletox[FINEANGLES/2];
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

View file

@ -34,6 +34,15 @@
#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
// 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)
{
Lock_state();
if (!texturecache[tex])
R_GenerateTexture(tex);
Unlock_state();
}
//
@ -525,9 +536,11 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col)
else
col &= (width - 1);
Lock_state();
data = texturecache[tex];
if (!data)
data = R_GenerateTexture(tex);
Unlock_state();
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.
//
void *R_GetLevelFlat(levelflat_t *levelflat)
void *R_GetLevelFlat(levelflat_t *levelflat, UINT16 *flatwidth, UINT16 *flatheight)
{
boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE);
texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL);
@ -555,8 +568,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
if (texture->flat)
{
flatdata = texture->flat;
ds_flatwidth = texture->width;
ds_flatheight = texture->height;
*flatwidth = texture->width;
*flatheight = texture->height;
texturechanged = false;
}
else
@ -566,12 +579,14 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
// If the texture changed, or the flat wasn't generated, convert.
if (levelflat->picture == NULL || texturechanged)
{
Lock_state();
// Level texture
if (isleveltexture)
{
levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num);
ds_flatwidth = levelflat->width = texture->width;
ds_flatheight = levelflat->height = texture->height;
*flatwidth = levelflat->width = texture->width;
*flatheight = levelflat->height = texture->height;
}
else
{
@ -584,8 +599,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
levelflat->width = (UINT16)pngwidth;
levelflat->height = (UINT16)pngheight;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
*flatwidth = levelflat->width;
*flatheight = levelflat->height;
}
else
#endif
@ -595,8 +610,8 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
size_t size;
softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = ds_flatwidth = SHORT(patch->width);
levelflat->height = ds_flatheight = SHORT(patch->height);
levelflat->width = *flatwidth = SHORT(patch->width);
levelflat->height = *flatheight = SHORT(patch->height);
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);
@ -604,11 +619,13 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
Z_Free(converted);
}
}
Unlock_state();
}
else
{
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
*flatwidth = levelflat->width;
*flatheight = levelflat->height;
}
levelflat->u.texture.lastnum = levelflat->u.texture.num;
@ -621,23 +638,14 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
//
// 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 hpow2 = (!(ds_flatheight & (ds_flatheight - 1)));
boolean wpow2 = (!(flatwidth & (flatwidth - 1)));
boolean hpow2 = (!(flatheight & (flatheight - 1)));
// Initially, the flat isn't powers-of-two-sized.
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;
return ((flatwidth == flatheight) && (wpow2 && hpow2));
}
//
@ -645,58 +653,58 @@ boolean R_CheckPowersOfTwo(void)
//
// 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)
{
case 4194304: // 2048x2048 lump
nflatmask = 0x3FF800;
nflatxshift = 21;
nflatyshift = 10;
nflatshiftup = 5;
ds_flatwidth = ds_flatheight = 2048;
ds->nflatmask = 0x3FF800;
ds->nflatxshift = 21;
ds->nflatyshift = 10;
ds->nflatshiftup = 5;
ds->flatwidth = ds->flatheight = 2048;
break;
case 1048576: // 1024x1024 lump
nflatmask = 0xFFC00;
nflatxshift = 22;
nflatyshift = 12;
nflatshiftup = 6;
ds_flatwidth = ds_flatheight = 1024;
ds->nflatmask = 0xFFC00;
ds->nflatxshift = 22;
ds->nflatyshift = 12;
ds->nflatshiftup = 6;
ds->flatwidth = ds->flatheight = 1024;
break;
case 262144:// 512x512 lump
nflatmask = 0x3FE00;
nflatxshift = 23;
nflatyshift = 14;
nflatshiftup = 7;
ds_flatwidth = ds_flatheight = 512;
ds->nflatmask = 0x3FE00;
ds->nflatxshift = 23;
ds->nflatyshift = 14;
ds->nflatshiftup = 7;
ds->flatwidth = ds->flatheight = 512;
break;
case 65536: // 256x256 lump
nflatmask = 0xFF00;
nflatxshift = 24;
nflatyshift = 16;
nflatshiftup = 8;
ds_flatwidth = ds_flatheight = 256;
ds->nflatmask = 0xFF00;
ds->nflatxshift = 24;
ds->nflatyshift = 16;
ds->nflatshiftup = 8;
ds->flatwidth = ds->flatheight = 256;
break;
case 16384: // 128x128 lump
nflatmask = 0x3F80;
nflatxshift = 25;
nflatyshift = 18;
nflatshiftup = 9;
ds_flatwidth = ds_flatheight = 128;
ds->nflatmask = 0x3F80;
ds->nflatxshift = 25;
ds->nflatyshift = 18;
ds->nflatshiftup = 9;
ds->flatwidth = ds->flatheight = 128;
break;
case 1024: // 32x32 lump
nflatmask = 0x3E0;
nflatxshift = 27;
nflatyshift = 22;
nflatshiftup = 11;
ds_flatwidth = ds_flatheight = 32;
ds->nflatmask = 0x3E0;
ds->nflatxshift = 27;
ds->nflatyshift = 22;
ds->nflatshiftup = 11;
ds->flatwidth = ds->flatheight = 32;
break;
default: // 64x64 lump
nflatmask = 0xFC0;
nflatxshift = 26;
nflatyshift = 20;
nflatshiftup = 10;
ds_flatwidth = ds_flatheight = 64;
ds->nflatmask = 0xFC0;
ds->nflatxshift = 26;
ds->nflatyshift = 20;
ds->nflatshiftup = 10;
ds->flatwidth = ds->flatheight = 64;
break;
}
}

View file

@ -18,6 +18,7 @@
#include "r_state.h"
#include "p_setup.h" // levelflats
#include "r_data.h"
#include "r_draw.h"
#ifdef __GNUG__
#pragma interface
@ -86,12 +87,12 @@ void R_CheckTextureCache(INT32 tex);
void R_ClearTextureNumCache(boolean btell);
// 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);
void *R_GetFlat(lumpnum_t flatnum);
boolean R_CheckPowersOfTwo(void);
void R_CheckFlatLength(size_t size);
boolean R_CheckPowersOfTwo(UINT16 flatwidth, UINT16 flatheight);
void R_CheckFlatLength(spancontext_t *ds, size_t size);
// Returns the texture number for the texture 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
void R_InitSprites(void);
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
@ -37,23 +38,16 @@ void R_AddSpriteDefs(UINT16 wadnum);
// MASKED COLUMN DRAWING
// ---------------------
// vars for R_DrawMaskedColumn
extern INT16 *mfloorclip;
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);
void R_DrawMaskedColumn(colcontext_t *dc, column_t *column);
void R_DrawFlippedMaskedColumn(colcontext_t *dc, column_t *column);
// ----------------
// SPRITE RENDERING
// ----------------
struct rendercontext_s;
struct spritecontext_s;
// Constant arrays used for psprite clipping
// and initializing clipping.
extern INT16 negonearray[MAXVIDWIDTH];
@ -62,17 +56,18 @@ extern INT16 screenheightarray[MAXVIDWIDTH];
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
//SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void);
void R_ClearSprites(void);
void R_AddSprites(struct rendercontext_s *context, sector_t *sec, INT32 lightlevel);
void R_ClearSprites(struct spritecontext_s *spritecontext);
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 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);
boolean R_ThingHorizontallyFlipped (mobj_t *thing);
@ -99,7 +94,7 @@ typedef struct
sector_t* viewsector;
} maskcount_t;
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
void R_DrawMasked(struct rendercontext_s *context, maskcount_t *masks, UINT8 nummasks);
// ----------
// VISSPRITES
@ -210,10 +205,7 @@ typedef struct vissprite_s
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} vissprite_t;
extern UINT32 visspritecount;
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);
void R_ClipSprites(struct rendercontext_s *context, drawseg_t* dsstart, portal_t* portal);
boolean R_SpriteIsFlashing(vissprite_t *vis);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
@ -236,7 +228,7 @@ typedef struct drawnode_s
struct drawnode_s *prev;
} drawnode_t;
void R_InitDrawNodes(void);
void R_InitDrawNodes(drawnode_t *nodebankhead);
// -----------------------
// SPRITE FRAME CHARACTERS

View file

@ -39,20 +39,13 @@
#include "hardware/hw_model.h"
#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
// --------------------------------------------
void (*colfunc)(void);
void (*colfuncs[COLDRAWFUNC_MAX])(void);
colfunc_t colfuncs[COLDRAWFUNC_MAX];
void (*spanfunc)(void);
void (*spanfuncs[SPANDRAWFUNC_MAX])(void);
void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
spanfunc_t spanfuncs[SPANDRAWFUNC_MAX];
spanfunc_t spanfuncs_npo2[SPANDRAWFUNC_MAX];
// ------------------
// global video state
@ -106,95 +99,47 @@ boolean R_SSE2 = false;
void SCR_SetDrawFuncs(void)
{
//
// 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;
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8;
// Always run in 8bpp. todo: remove all 16bpp code?
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8;
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8;
colfunc = colfuncs[BASEDRAWFUNC];
spanfunc = spanfuncs[BASEDRAWFUNC];
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8;
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8;
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
// Lactozilla: Non-powers-of-two
spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_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);
*/
// Lactozilla: Non-powers-of-two
spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
}
void SCR_SetMode(void)

View file

@ -112,58 +112,6 @@ typedef struct vmode_s
#define NUMSPECIALMODES 4
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
// -----

View file

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

View file

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

View file

@ -155,7 +155,7 @@ Worker (
return 0;
}
void
I_thread_handle
I_spawn_thread (
const char * name,
I_thread_fn entry,
@ -189,6 +189,7 @@ I_spawn_thread (
}
}
I_unlock_mutex(i_thread_pool_mutex);
return (I_thread_handle)th;
}
int
@ -354,3 +355,18 @@ I_wake_all_cond (
if (SDL_CondBroadcast(cond) == -1)
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
#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
{
@ -1922,6 +1930,8 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
if (!TestValidLump(wad,lump))
return NULL;
Lock_state();
lumpcache = wadfiles[wad]->lumpcache;
if (!lumpcache[lump])
{
@ -1931,6 +1941,8 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
else
Z_ChangeTag(lumpcache[lump], tag);
Unlock_state();
return lumpcache[lump];
}
@ -1955,9 +1967,13 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag)
if (!TestValidLump(wad,lump))
return NULL;
Lock_state();
ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, NULL);
W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full
Unlock_state();
return ptr;
}
@ -1975,15 +1991,23 @@ static inline boolean W_IsLumpCachedPWAD(UINT16 wad, UINT16 lump, void *ptr)
if (!TestValidLump(wad, lump))
return false;
Lock_state();
lcache = wadfiles[wad]->lumpcache[lump];
if (ptr)
{
if (ptr == lcache)
if (ptr == lcache) {
Unlock_state();
return true;
}
}
else if (lcache)
else if (lcache) {
Unlock_state();
return true;
}
Unlock_state();
return false;
}
@ -2007,15 +2031,23 @@ static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr)
if (!TestValidLump(wad, lump))
return false;
Lock_state();
lcache = wadfiles[wad]->patchcache[lump];
if (ptr)
{
if (ptr == lcache)
if (ptr == lcache) {
Unlock_state();
return true;
}
}
else if (lcache)
else if (lcache) {
Unlock_state();
return true;
}
Unlock_state();
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
//
void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
static void *W_CacheSoftwarePatch(UINT16 wad, UINT16 lump, INT32 tag)
{
lumpcache_t *lumpcache = NULL;
@ -2082,11 +2114,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
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)
{
patch_t *patch;
@ -2094,16 +2121,23 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
if (!TestValidLump(wad, lump))
return NULL;
patch = W_CacheSoftwarePatchNumPwad(wad, lump, tag);
Lock_state();
patch = W_CacheSoftwarePatch(wad, lump, tag);
#ifdef HWRENDER
// Software-only compile cache the data without conversion
if (rendermode == render_soft || rendermode == render_none)
#endif
{
Unlock_state();
return (void *)patch;
}
#ifdef HWRENDER
Patch_CreateGL(patch);
Unlock_state();
return (void *)patch;
#endif
}
@ -2118,6 +2152,8 @@ void W_UnlockCachedPatch(void *patch)
if (!patch)
return;
Lock_state();
// The hardware code does its own memory management, as its patches
// have different lifetimes from software's.
#ifdef HWRENDER
@ -2126,6 +2162,8 @@ void W_UnlockCachedPatch(void *patch)
else
#endif
Z_Unlock(patch);
Unlock_state();
}
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_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_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);

View file

@ -39,6 +39,15 @@
#include "hardware/hw_main.h" // For hardware memory info
#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
#include "valgrind.h"
static boolean Z_calloc = false;
@ -203,6 +212,8 @@ void Z_Free(void *ptr)
if (ptr == NULL)
return;
Lock_state();
#ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
#endif
@ -237,6 +248,8 @@ void Z_Free(void *ptr)
block->prev->next = block->next;
block->next->prev = block->prev;
free(block);
Unlock_state();
}
/** malloc() that doesn't accept failure.
@ -295,6 +308,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
void *given;
size_t blocksize = extrabytes + sizeof *hdr + size;
Lock_state();
#ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line);
#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 "
"(size %s) with no user", sizeu1(size));
Unlock_state();
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)
#endif
{
void *mem;
Lock_state();
#ifdef VALGRIND_MEMPOOL_ALLOC
Z_calloc = true;
#endif
#ifdef ZDEBUG
return memset(Z_Malloc2 (size, tag, user, alignbits, file, line), 0, size);
mem = Z_Malloc2 (size, tag, user, alignbits, file, line);
#else
return memset(Z_MallocAlign(size, tag, user, alignbits ), 0, size);
mem = Z_MallocAlign(size, tag, user, alignbits );
#endif
memset(mem, 0, size);
Unlock_state();
return mem;
}
/** The Z_ReallocAlign function.