FINALLY, the nq and qw renderers are merged. the view and particle subsystems

are not yet merged due to their dependence on the client, but that will come
soon.
This commit is contained in:
Bill Currie 2001-05-24 19:22:35 +00:00
parent 55ee68cf38
commit 73e6e1684f
131 changed files with 1434 additions and 25737 deletions

View file

@ -1536,6 +1536,9 @@ AC_OUTPUT(
libs/models/sprite/Makefile libs/models/sprite/Makefile
libs/util/Makefile libs/util/Makefile
libs/video/Makefile libs/video/Makefile
libs/video/renderer/Makefile
libs/video/renderer/gl/Makefile
libs/video/renderer/sw/Makefile
libs/video/targets/Makefile libs/video/targets/Makefile
qw/Makefile qw/Makefile

View file

@ -1,4 +1,4 @@
SUBDIRS= targets SUBDIRS= renderer targets
clean-local: clean-local:
rm -f *.a rm -f *.a

9
libs/video/renderer/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.la
*.lo
.deps
.libs
.vimrc
Makefile
Makefile.in
fbset_modes_y.[ch]
fbset_modes_l.c

View file

@ -0,0 +1,30 @@
SUBDIRS= gl sw
INCLUDES= -I$(top_srcdir)/include
if BUILD_GL
RENDERER_GL = libQFrenderer_gl.la
else
RENDERER_GL =
endif
if BUILD_SW
RENDERER_SW = libQFrenderer_sw.la
else
RENDERER_SW =
endif
lib_LTLIBRARIES = $(RENDERER_GL) $(RENDERER_SW)
common_SOURCES = r_cvar.c r_efrag.c r_ent.c r_graph.c r_main.c
libQFrenderer_gl_la_LDFLAGS = -version-info 1:0:0
libQFrenderer_gl_la_LIBADD = gl/libgl.la
libQFrenderer_gl_la_SOURCES = $(common_SOURCES)
libQFrenderer_gl_la_DEPENDENCIES = gl/libgl.la
libQFrenderer_sw_la_LDFLAGS = -version-info 1:0:0
libQFrenderer_sw_la_LIBADD = sw/libsw.la
libQFrenderer_sw_la_SOURCES = $(common_SOURCES)
libQFrenderer_sw_la_DEPENDENCIES = sw/libsw.la
LIBLIST = libQFrenderer_gl.la libQFrenderer_sw.la

9
libs/video/renderer/gl/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.la
*.lo
.deps
.libs
.vimrc
Makefile
Makefile.in
fbset_modes_y.[ch]
fbset_modes_l.c

View file

@ -0,0 +1,14 @@
INCLUDES= -I$(top_srcdir)/include
if BUILD_GL
GL = libgl.la
else
GL =
endif
noinst_LTLIBRARIES = $(GL)
libgl_la_LDFLAGS = -version-info 1:0:0
libgl_la_SOURCES = gl_draw.c gl_dyn_fires.c gl_dyn_textures.c gl_graph.c \
gl_rlight.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_skin.c \
gl_sky.c gl_sky_clip.c gl_textures.c gl_warp.c noisetextures.c

View file

@ -52,7 +52,6 @@
#include "QF/tga.h" #include "QF/tga.h"
#include "glquake.h" #include "glquake.h"
#include "host.h"
#include "r_cvar.h" #include "r_cvar.h"
#include "r_local.h" #include "r_local.h"
#include "sbar.h" #include "sbar.h"
@ -232,7 +231,7 @@ SCR_CheckDrawCenterString (int swap)
if (scr_center_lines > scr_erase_lines) if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines; scr_erase_lines = scr_center_lines;
scr_centertime_off -= host_frametime; scr_centertime_off -= r_frametime;
if (scr_centertime_off <= 0 && !r_force_fullscreen /*FIXME better test*/) if (scr_centertime_off <= 0 && !r_force_fullscreen /*FIXME better test*/)
return; return;
@ -400,7 +399,7 @@ SCR_DrawTurtle (int swap)
if (!scr_showturtle->int_val) if (!scr_showturtle->int_val)
return; return;
if (host_frametime < 0.1) { if (r_frametime < 0.1) {
count = 0; count = 0;
return; return;
} }
@ -523,12 +522,12 @@ SCR_SetUpToDrawConsole (void)
scr_conlines = 0; // none visible scr_conlines = 0; // none visible
if (scr_conlines < scr_con_current) { if (scr_conlines < scr_con_current) {
scr_con_current -= scr_conspeed->value * host_frametime; scr_con_current -= scr_conspeed->value * r_frametime;
if (scr_conlines > scr_con_current) if (scr_conlines > scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_conlines;
} else if (scr_conlines > scr_con_current) { } else if (scr_conlines > scr_con_current) {
scr_con_current += scr_conspeed->value * host_frametime; scr_con_current += scr_conspeed->value * r_frametime;
if (scr_conlines < scr_con_current) if (scr_conlines < scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_conlines;
} }

View file

@ -0,0 +1,130 @@
/*
noisetextures.c
Noise texture generators
noise_plasma
Copyright (C) 2001 Ragnvald `Despair` Maartmann-Moe IV.
noise_diamondsquare (originally fractalnoise)
Copyright (C) 2000 Forest `LordHavoc` Hale.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/mathlib.h"
void
noise_diamondsquare (unsigned char *noise, int size)
{
int x, y, g, g2, amplitude, min, max, size1 = size - 1;
int *noisebuf;
#define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
noisebuf = calloc (size * size, sizeof (int));
amplitude = 32767;
g2 = size;
n (0, 0) = 0;
for (; (g = g2 >> 1) >= 1; g2 >>= 1) {
// subdivide, diamond-square algorythm (really this has little
// to do with squares)
// diamond
for (y = 0; y < size; y += g2)
for (x = 0; x < size; x += g2)
n (x + g, y + g) =
(n (x, y) + n (x + g2, y) + n (x, y + g2) +
n (x + g2, y + g2)) >> 2;
// square
for (y = 0; y < size; y += g2)
for (x = 0; x < size; x += g2) {
n (x + g, y) =
(n (x, y) + n (x + g2, y) + n (x + g, y - g) +
n (x + g, y + g)) >> 2;
n (x, y + g) =
(n (x, y) + n (x, y + g2) + n (x - g, y + g) +
n (x + g, y + g)) >> 2;
}
// Brownian motion ( at every smaller level, random behavior )
amplitude >>= 1;
for (y = 0; y < size; y += g)
for (x = 0; x < size; x += g)
n (x, y) += (rand () & amplitude);
}
// find range of noise values
min = max = 0;
for (y = 0; y < size; y++)
for (x = 0; x < size; x++) {
if (n (x, y) < min)
min = n (x, y);
if (n (x, y) > max)
max = n (x, y);
}
max -= min;
// normalize noise and copy to output
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
*noise++ = (n (x, y) - min) * 255 / max;
free (noisebuf);
#undef n
}
void
noise_plasma (unsigned char *noise, int size)
{
int a, b, c, d, i, j, k;
if (128 >= size)
d = 64 / size;
else
d = -size / 64;
memset(noise, 128, sizeof (*noise));
for (i=size; i > 0; i/=2) {
for (j=0; j < size; j+=i) {
for (k=0; k < size; k+=i) {
if (d>=0)
c = i * d;
else
c = -i / d;
c=lhrandom(-c, c);
for (a=j; a < j+i; a++)
for (b=k; b < k+i; b++)
noise[a*size+b] += c;
}
}
}
}

View file

@ -7,6 +7,7 @@ qboolean r_inhibit_viewmodel;
qboolean r_force_fullscreen; qboolean r_force_fullscreen;
qboolean r_paused; qboolean r_paused;
double r_realtime; double r_realtime;
double r_frametime;
dlight_t r_dlights[MAX_DLIGHTS]; dlight_t r_dlights[MAX_DLIGHTS];
entity_t *r_view_model; entity_t *r_view_model;
entity_t *r_player_entity; entity_t *r_player_entity;

9
libs/video/renderer/sw/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.la
*.lo
.deps
.libs
.vimrc
Makefile
Makefile.in
fbset_modes_y.[ch]
fbset_modes_l.c

View file

@ -0,0 +1,19 @@
INCLUDES= -I$(top_srcdir)/include
if BUILD_SW
SW = libsw.la
else
SW =
endif
noinst_LTLIBRARIES = $(SW)
libsw_la_LDFLAGS = -version-info 1:0:0
libsw_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c \
d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c draw.c screen.c \
sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c sw_rdraw.c sw_redge.c \
sw_rlight.c sw_rmain.c sw_rmisc.c sw_rsky.c sw_rsprite.c sw_rsurf.c \
sw_skin.c \
d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S \
d_varsa.S surf16.S surf8.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S \
sw_redgea.S sw_rvarsa.S

View file

@ -32,11 +32,11 @@
#include "QF/compat.h" #include "QF/compat.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/render.h"
#include "QF/vid.h" #include "QF/vid.h"
#include "d_local.h" #include "d_local.h"
#include "r_cvar.h" #include "r_cvar.h"
#include "QF/render.h"
#define NUM_MIPS 4 #define NUM_MIPS 4

View file

@ -32,7 +32,7 @@
# include "config.h" # include "config.h"
#endif #endif
#include "host.h" #include "QF/qtypes.h"
// all global and static refresh variables are collected in a contiguous block // all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts. // to avoid cache conflicts.

View file

@ -42,7 +42,6 @@
#include "QF/sound.h" #include "QF/sound.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "client.h"
#include "d_iface.h" #include "d_iface.h"
#include "r_cvar.h" #include "r_cvar.h"

View file

@ -1,5 +1,5 @@
/* /*
gl_screen.c screen.c
master for refresh, status bar, console, chat, notify, etc master for refresh, status bar, console, chat, notify, etc
@ -44,15 +44,14 @@
#include "QF/draw.h" #include "QF/draw.h"
#include "QF/keys.h" #include "QF/keys.h"
#include "QF/pcx.h" #include "QF/pcx.h"
#include "QF/quakefs.h" // MAX_OSPATH #include "QF/quakefs.h"
#include "QF/render.h" // r_refdef #include "QF/render.h"
#include "QF/screen.h" #include "QF/screen.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/texture.h" #include "QF/texture.h"
#include "QF/tga.h" #include "QF/vid.h"
#include "glquake.h" #include "d_iface.h"
#include "host.h"
#include "r_cvar.h" #include "r_cvar.h"
#include "r_local.h" #include "r_local.h"
#include "sbar.h" #include "sbar.h"
@ -95,20 +94,16 @@ Con_Printf ();
net net
turn off messages option turn off messages option
the refresh is allways rendered, unless the console is full screen the refresh is always rendered, unless the console is full screen
console is: console is:
notify lines notify lines
half half
full full
*/ */
int glx, gly, glwidth, glheight;
// only the refresh window will be updated unless these variables are flagged // only the refresh window will be updated unless these variables are flagged
int scr_copytop; int scr_copytop;
int scr_copyeverything; int scr_copyeverything;
@ -134,10 +129,12 @@ extern int sb_lines;
viddef_t vid; // global video state viddef_t vid; // global video state
vrect_t *pconupdate;
vrect_t scr_vrect; vrect_t scr_vrect;
qboolean scr_disabled_for_loading; qboolean scr_disabled_for_loading;
float scr_disabled_time;
qboolean scr_skipupdate;
qboolean block_drawing; qboolean block_drawing;
@ -158,8 +155,8 @@ int scr_erase_center;
/* /*
SCR_CenterPrint SCR_CenterPrint
Called for important messages that should stay in the center of the screen Called for important messages that should stay in the center of the
for a few moments screen for a few moments
*/ */
void void
SCR_CenterPrint (char *str) SCR_CenterPrint (char *str)
@ -188,7 +185,7 @@ SCR_DrawCenterString (void)
int remaining; int remaining;
// the finale prints the characters one at a time // the finale prints the characters one at a time
if (r_force_fullscreen /*FIXME better test*/) if (r_force_fullscreen /*FIXME*/)
remaining = scr_printspeed->value * (r_realtime - scr_centertime_start); remaining = scr_printspeed->value * (r_realtime - scr_centertime_start);
else else
remaining = 9999; remaining = 9999;
@ -232,9 +229,9 @@ SCR_CheckDrawCenterString (int swap)
if (scr_center_lines > scr_erase_lines) if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines; scr_erase_lines = scr_center_lines;
scr_centertime_off -= host_frametime; scr_centertime_off -= r_frametime;
if (scr_centertime_off <= 0 && !r_force_fullscreen /*FIXME better test*/) if (scr_centertime_off <= 0 && !r_force_fullscreen /*FIXME*/)
return; return;
if (key_dest != key_game) if (key_dest != key_game)
return; return;
@ -243,6 +240,9 @@ SCR_CheckDrawCenterString (int swap)
} }
//=============================================================================
float float
CalcFov (float fov_x, float width, float height) CalcFov (float fov_x, float width, float height)
{ {
@ -271,6 +271,7 @@ CalcFov (float fov_x, float width, float height)
static void static void
SCR_CalcRefdef (void) SCR_CalcRefdef (void)
{ {
vrect_t vrect;
float size; float size;
int h; int h;
qboolean full = false; qboolean full = false;
@ -281,6 +282,8 @@ SCR_CalcRefdef (void)
// force the status bar to redraw // force the status bar to redraw
Sbar_Changed (); Sbar_Changed ();
//========================================
// bound viewsize // bound viewsize
Cvar_SetValue (scr_viewsize, bound (30, scr_viewsize->int_val, 120)); Cvar_SetValue (scr_viewsize, bound (30, scr_viewsize->int_val, 120));
@ -301,7 +304,7 @@ SCR_CalcRefdef (void)
size = scr_viewsize->int_val; size = scr_viewsize->int_val;
} }
// intermission is always full screen // intermission is always full screen
if (r_force_fullscreen /*FIXME better test*/) { if (r_force_fullscreen /*FIXME*/) {
full = true; full = true;
size = 100.0; size = 100.0;
sb_lines = 0; sb_lines = 0;
@ -330,6 +333,23 @@ SCR_CalcRefdef (void)
CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
scr_vrect = r_refdef.vrect; scr_vrect = r_refdef.vrect;
// these calculations mirror those in R_Init() for r_refdef, but take no
// account of water warping
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
R_SetVrect (&vrect, &scr_vrect, r_lineadj);
// guard against going from one mode to another that's less than half the
// vertical resolution
if (scr_con_current > vid.height)
scr_con_current = vid.height;
// notify the refresh of the change
R_ViewChanged (&vrect, r_lineadj, vid.aspect);
} }
@ -361,15 +381,18 @@ SCR_SizeDown_f (void)
} }
//============================================================================
void void
SCR_Init (void) SCR_Init (void)
{ {
// //
// register our commands // register our commands
// //
Cmd_AddCommand ("screenshot", SCR_ScreenShot_f, "Take a screenshot, saves as qfxxx.tga in the current directory"); Cmd_AddCommand ("screenshot", SCR_ScreenShot_f, "Take a screenshot and write it as qfxxx.tga in the current directory");
Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increases the screen size"); Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increase the size of the screen");
Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decreases the screen size"); Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decrease the size of the screen");
scr_ram = Draw_PicFromWad ("ram"); scr_ram = Draw_PicFromWad ("ram");
scr_net = Draw_PicFromWad ("net"); scr_net = Draw_PicFromWad ("net");
@ -400,7 +423,7 @@ SCR_DrawTurtle (int swap)
if (!scr_showturtle->int_val) if (!scr_showturtle->int_val)
return; return;
if (host_frametime < 0.1) { if (r_frametime < 0.1) {
count = 0; count = 0;
return; return;
} }
@ -413,8 +436,8 @@ SCR_DrawTurtle (int swap)
} }
extern cvar_t *show_time;
extern cvar_t *show_fps; extern cvar_t *show_fps;
extern cvar_t *show_time;
void void
SCR_DrawFPS (int swap) SCR_DrawFPS (int swap)
@ -436,9 +459,9 @@ SCR_DrawFPS (int swap)
lastframetime = t; lastframetime = t;
} }
snprintf (st, sizeof (st), "%3d FPS", lastfps); snprintf (st, sizeof (st), "%3d FPS", lastfps);
/* Misty: New trick! (for me) the ? makes this work like a if then else -
// FIXME! This is evil. -- Deek IE: if cl_hudswap->int_val is not null, do first case, else (else is a
// calculate the location of the clock : here) do second case. Deek taught me this trick */
if (show_time->int_val <= 0) { if (show_time->int_val <= 0) {
i = 8; i = 8;
} else if (show_time->int_val == 1) { } else if (show_time->int_val == 1) {
@ -446,9 +469,8 @@ SCR_DrawFPS (int swap)
} else { } else {
i = 80; i = 80;
} }
x = swap ? vid.width - ((strlen (st) * 8) + i) : i; x = swap ? vid.width - ((strlen (st) * 8) + i) : i;
y = vid.height - sb_lines - 8; y = vid.height - (sb_lines + 8);
Draw_String8 (x, y, st); Draw_String8 (x, y, st);
} }
@ -457,7 +479,7 @@ SCR_DrawFPS (int swap)
SCR_DrawTime SCR_DrawTime
Draw a clock on the screen Draw a clock on the screen
Written by Misty, rewritten by Deek. Written by Misty, rewritten by Deek
*/ */
void void
SCR_DrawTime (int swap) SCR_DrawTime (int swap)
@ -482,9 +504,9 @@ SCR_DrawTime (int swap)
} else if (show_time->int_val >= 2) { // US AM/PM display } else if (show_time->int_val >= 2) { // US AM/PM display
timefmt = "%l:%M %P"; timefmt = "%l:%M %P";
} }
strftime (st, sizeof (st), timefmt, local);
// Print it at far left/right of screen // Print it next to the fps meter
strftime (st, sizeof (st), timefmt, local);
x = swap ? (vid.width - ((strlen (st) * 8) + 8)) : 8; x = swap ? (vid.width - ((strlen (st) * 8) + 8)) : 8;
y = vid.height - (sb_lines + 8); y = vid.height - (sb_lines + 8);
Draw_String8 (x, y, st); Draw_String8 (x, y, st);
@ -508,6 +530,9 @@ SCR_DrawPause (int swap)
} }
//=============================================================================
void void
SCR_SetUpToDrawConsole (void) SCR_SetUpToDrawConsole (void)
{ {
@ -523,12 +548,12 @@ SCR_SetUpToDrawConsole (void)
scr_conlines = 0; // none visible scr_conlines = 0; // none visible
if (scr_conlines < scr_con_current) { if (scr_conlines < scr_con_current) {
scr_con_current -= scr_conspeed->value * host_frametime; scr_con_current -= scr_conspeed->value * r_frametime;
if (scr_conlines > scr_con_current) if (scr_conlines > scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_conlines;
} else if (scr_conlines > scr_con_current) { } else if (scr_conlines > scr_con_current) {
scr_con_current += scr_conspeed->value * host_frametime; scr_con_current += scr_conspeed->value * r_frametime;
if (scr_conlines < scr_con_current) if (scr_conlines < scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_conlines;
} }
@ -572,12 +597,8 @@ SCR_ScreenShot (int width, int height)
float fracw, frach; float fracw, frach;
tex_t *tex; tex_t *tex;
tex = Hunk_TempAlloc (sizeof (tex_t) + vid.width * vid.height * 3); // enable direct drawing of console to back buffer
if (!tex) D_EnableBackBufferAccess ();
return 0;
glReadPixels (glx, gly, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE,
tex->data + vid.width * vid.height);
w = (vid.width < width) ? vid.width : width; w = (vid.width < width) ? vid.width : width;
h = (vid.height < height) ? vid.height : height; h = (vid.height < height) ? vid.height : height;
@ -585,8 +606,12 @@ SCR_ScreenShot (int width, int height)
fracw = (float) vid.width / (float) w; fracw = (float) vid.width / (float) w;
frach = (float) vid.height / (float) h; frach = (float) vid.height / (float) h;
tex = Hunk_TempAlloc (sizeof (tex_t) + w * h);
if (!tex)
return 0;
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
dest = tex->data + (w * 3 * y); dest = tex->data + (w * y);
for (x = 0; x < w; x++) { for (x = 0; x < w; x++) {
r = g = b = 0; r = g = b = 0;
@ -602,33 +627,23 @@ SCR_ScreenShot (int width, int height)
count = 0; count = 0;
for ( /* */ ; dy < dey; dy++) { for ( /* */ ; dy < dey; dy++) {
src = tex->data + (vid.width * 3 * dy) + dx * 3; src = vid.buffer + (vid.rowbytes * dy) + dx;
for (nx = dx; nx < dex; nx++) { for (nx = dx; nx < dex; nx++) {
r += *src++; r += vid_basepal[*src * 3];
g += *src++; g += vid_basepal[*src * 3 + 1];
b += *src++; b += vid_basepal[*src * 3 + 2];
src++;
count++; count++;
} }
} }
r /= count; r /= count;
g /= count; g /= count;
b /= count; b /= count;
*dest++ = r; *dest++ = MipColor (r, g, b);
*dest++ = b;
*dest++ = g;
}
}
// convert to eight bit
for (y = 0; y < h; y++) {
src = tex->data + (w * 3 * y);
dest = tex->data + (w * y);
for (x = 0; x < w; x++) {
*dest++ = MipColor (src[0], src[1], src[2]);
src += 3;
} }
} }
// for adapters that can't stay mapped in for linear writes all the time
D_DisableBackBufferAccess ();
return tex; return tex;
} }
@ -636,21 +651,28 @@ SCR_ScreenShot (int width, int height)
void void
SCR_ScreenShot_f (void) SCR_ScreenShot_f (void)
{ {
byte *buffer;
char pcxname[MAX_OSPATH]; char pcxname[MAX_OSPATH];
pcx_t *pcx;
int pcx_len;
//
// find a file name to save it to // find a file name to save it to
// if (!COM_NextFilename (pcxname, "qf", ".pcx")) {
if (!COM_NextFilename (pcxname, "qf", ".tga")) { Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX");
Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
return; return;
} }
buffer = malloc (glwidth * glheight * 3);
glReadPixels (glx, gly, glwidth, glheight, GL_BGR_EXT, GL_UNSIGNED_BYTE, // enable direct drawing of console to back buffer
buffer); D_EnableBackBufferAccess ();
WriteTGAfile (pcxname, buffer, glwidth, glheight);
free (buffer); // save the pcx file
pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes,
vid_basepal, false, &pcx_len);
COM_WriteFile (pcxname, pcx, pcx_len);
// for adapters that can't stay mapped in for linear writes all the time
D_DisableBackBufferAccess ();
Con_Printf ("Wrote %s\n", pcxname); Con_Printf ("Wrote %s\n", pcxname);
} }
@ -692,7 +714,7 @@ MipColor (int r, int g, int b)
} }
// in gl_draw.c // in draw.c
extern byte *draw_chars; // 8*8 graphic characters extern byte *draw_chars; // 8*8 graphic characters
void void
@ -716,7 +738,7 @@ SCR_DrawCharToSnap (int num, byte * dest, int width)
else else
dest[x] = 98; dest[x] = 98;
source += 128; source += 128;
dest -= width; dest += width;
} }
} }
@ -740,6 +762,9 @@ SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y)
} }
//=============================================================================
char *scr_notifystring; char *scr_notifystring;
void void
@ -775,39 +800,9 @@ SCR_DrawNotifyString (void)
} }
void //=============================================================================
SCR_TileClear (void)
{
if (r_refdef.vrect.x > 0) {
// left
Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines);
// right
Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0,
vid.width - r_refdef.vrect.x + r_refdef.vrect.width,
vid.height - sb_lines);
}
if (r_refdef.vrect.y > 0) {
// top
Draw_TileClear (r_refdef.vrect.x, 0,
r_refdef.vrect.x + r_refdef.vrect.width,
r_refdef.vrect.y);
// bottom
Draw_TileClear (r_refdef.vrect.x,
r_refdef.vrect.y + r_refdef.vrect.height,
r_refdef.vrect.width,
vid.height - sb_lines -
(r_refdef.vrect.height + r_refdef.vrect.y));
}
}
extern void R_ForceLightUpdate (void);
int oldviewsize = 0;
unsigned char lighthalf_v[3];
qboolean lighthalf;
extern cvar_t *gl_lightmode;
/* /*
SCR_UpdateScreen SCR_UpdateScreen
@ -820,66 +815,84 @@ extern cvar_t *gl_lightmode;
void void
SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap)
{ {
double time1 = 0, time2; static int oldscr_viewsize;
float f; vrect_t vrect;
if (block_drawing) if (scr_skipupdate || block_drawing)
return; return;
r_realtime = realtime; if (scr_disabled_for_loading)
return;
vid.numpages = 2 + gl_triplebuffer->int_val; #ifdef _WIN32
{ // don't suck up any cpu if minimized
extern qboolean Minimized;
if (Minimized)
return;
}
#endif
r_realtime = realtime;
scr_copytop = 0; scr_copytop = 0;
scr_copyeverything = 0; scr_copyeverything = 0;
if (scr_disabled_for_loading) { if (!scr_initialized || !con_initialized)
if (r_realtime - scr_disabled_time > 60) { return; // not initialized yet
scr_disabled_for_loading = false;
Con_Printf ("load failed.\n");
} else {
return;
}
}
if (!scr_initialized || !con_initialized) // not initialized yet if (scr_viewsize->int_val != oldscr_viewsize) {
return; oldscr_viewsize = scr_viewsize->int_val;
vid.recalc_refdef = 1;
if (oldviewsize != scr_viewsize->int_val) { }
oldviewsize = scr_viewsize->int_val; //
// check for vid changes
//
if (oldfov != scr_fov->int_val) {
oldfov = scr_fov->int_val;
vid.recalc_refdef = true; vid.recalc_refdef = true;
} }
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); if (oldscreensize != scr_viewsize->int_val) {
oldscreensize = scr_viewsize->int_val;
if (r_speeds->int_val) {
time1 = Sys_DoubleTime ();
c_brush_polys = 0;
c_alias_polys = 0;
}
if (oldfov != scr_fov->value) { // determine size of refresh window
oldfov = scr_fov->value;
vid.recalc_refdef = true; vid.recalc_refdef = true;
} }
if (vid.recalc_refdef) if (vid.recalc_refdef) {
// something changed, so reorder the screen
SCR_CalcRefdef (); SCR_CalcRefdef ();
}
//
// do 3D refresh drawing, and then update the screen // do 3D refresh drawing, and then update the screen
//
D_EnableBackBufferAccess (); // of all overlay stuff if drawing
// directly
if (scr_fullupdate++ < vid.numpages) { // clear the entire screen
scr_copyeverything = 1;
Draw_TileClear (0, 0, vid.width, vid.height);
Sbar_Changed ();
}
pconupdate = NULL;
SCR_SetUpToDrawConsole (); SCR_SetUpToDrawConsole ();
D_DisableBackBufferAccess (); // for adapters that can't stay
// mapped in
// for linear writes all the time
VID_LockBuffer ();
V_RenderView (); V_RenderView ();
VID_UnlockBuffer ();
GL_Set2D (); D_EnableBackBufferAccess (); // of all overlay stuff if drawing
// directly
// draw any areas not covered by the refresh if (r_force_fullscreen /*FIXME*/ == 1 && key_dest == key_game) {
SCR_TileClear ();
if (r_force_fullscreen /*FIXME better test*/ == 1 && key_dest == key_game) {
Sbar_IntermissionOverlay (); Sbar_IntermissionOverlay ();
} else if (r_force_fullscreen /*FIXME better test*/ == 2 && key_dest == key_game) { } else if (r_force_fullscreen /*FIXME*/ == 2 && key_dest == key_game) {
Sbar_FinaleOverlay (); Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString (swap); SCR_CheckDrawCenterString (swap);
} else { } else {
@ -889,59 +902,42 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap)
} }
} }
// also makes polyblend apply to whole screen
glDisable (GL_TEXTURE_2D);
if (lighthalf) { // LordHavoc: render was done at half brightness D_DisableBackBufferAccess (); // for adapters that can't stay
f = 2; // mapped in
} else { // for linear writes all the time
f = 1; if (pconupdate) {
D_UpdateRects (pconupdate);
} }
if (f >= 1.002) { // Make sure we don't get bit by roundoff errors
glBlendFunc (GL_DST_COLOR, GL_ONE);
glBegin (GL_QUADS);
while (f >= 1.002) { // precision
if (f >= 2)
glColor3f (1, 1, 1);
else
glColor3f (f - 1, f - 1, f - 1);
glVertex2f (0, 0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
f *= 0.5;
}
glEnd ();
glColor3ubv (lighthalf_v);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
if (v_blend[3]) {
glBegin (GL_QUADS);
glColor4fv (v_blend);
glVertex2f (0, 0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
glEnd ();
glColor3ubv (lighthalf_v);
}
glEnable (GL_TEXTURE_2D);
V_UpdatePalette (); V_UpdatePalette ();
if (r_speeds->int_val) { //
// glFinish (); // update one of three areas
time2 = Sys_DoubleTime (); //
Con_Printf ("%3i ms %4i wpoly %4i epoly\n", if (scr_copyeverything) {
(int) ((time2 - time1) * 1000), c_brush_polys, vrect.x = 0;
c_alias_polys); vrect.y = 0;
} vrect.width = vid.width;
vrect.height = vid.height;
vrect.pnext = 0;
glFinish (); VID_Update (&vrect);
GL_EndRendering (); } else if (scr_copytop) {
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height - sb_lines;
vrect.pnext = 0;
VID_Update (&vrect);
} else {
vrect.x = scr_vrect.x;
vrect.y = scr_vrect.y;
vrect.width = scr_vrect.width;
vrect.height = scr_vrect.height;
vrect.pnext = 0;
VID_Update (&vrect);
}
} }

View file

@ -0,0 +1,179 @@
/*
surf16.S
x86 assembly-language 16 bpp surface block drawing code.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
//----------------------------------------------------------------------
// Surface block drawer
//----------------------------------------------------------------------
.data
k: .long 0
loopentry: .long 0
.align 4
blockjumptable16:
.long LEnter2_16
.long LEnter4_16
.long 0, LEnter8_16
.long 0, 0, 0, LEnter16_16
.text
.align 4
.globl C(R_Surf16Start)
C(R_Surf16Start):
.align 4
.globl C(R_DrawSurfaceBlock16)
C(R_DrawSurfaceBlock16):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
movl C(blocksize),%eax
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(sourcesstep),%ebx
movl blockjumptable16-4(,%eax,2),%ecx
movl %eax,k
movl %ecx,loopentry
movl C(lightleft),%edx
movl C(lightright),%ebp
Lblockloop16:
subl %edx,%ebp
movb C(blockdivshift),%cl
sarl %cl,%ebp
jns Lp1_16
testl C(blockdivmask),%ebp
jz Lp1_16
incl %ebp
Lp1_16:
subl %eax,%eax
subl %ecx,%ecx // high words must be 0 in loop for addressing
jmp *loopentry
.align 4
#include "block16.h"
movl C(pbasesource),%esi
movl C(lightleft),%edx
movl C(lightright),%ebp
movl C(sourcetstep),%eax
movl C(lightrightstep),%ecx
movl C(prowdestbase),%edi
addl %eax,%esi
addl %ecx,%ebp
movl C(lightleftstep),%eax
movl C(surfrowbytes),%ecx
addl %eax,%edx
addl %ecx,%edi
movl %esi,C(pbasesource)
movl %ebp,C(lightright)
movl k,%eax
movl %edx,C(lightleft)
decl %eax
movl %edi,C(prowdestbase)
movl %eax,k
jnz Lblockloop16
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
.globl C(R_Surf16End)
C(R_Surf16End):
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
.align 4
LPatchTable16:
.long LBPatch0-4
.long LBPatch1-4
.long LBPatch2-4
.long LBPatch3-4
.long LBPatch4-4
.long LBPatch5-4
.long LBPatch6-4
.long LBPatch7-4
.long LBPatch8-4
.long LBPatch9-4
.long LBPatch10-4
.long LBPatch11-4
.long LBPatch12-4
.long LBPatch13-4
.long LBPatch14-4
.long LBPatch15-4
.text
.align 4
.globl C(R_Surf16Patch)
C(R_Surf16Patch):
pushl %ebx
movl C(colormap),%eax
movl $LPatchTable16,%ebx
movl $16,%ecx
LPatchLoop16:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop16
popl %ebx
ret
#endif // USE_INTEL_ASM

View file

@ -0,0 +1,791 @@
/*
surf8.S
Intel x86 assembly-language 8bpp surface block drawing code
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
.data
sb_v: .long 0
.text
.align 4
.globl C(R_Surf8Start)
C(R_Surf8Start):
//----------------------------------------------------------------------
// Surface block drawer for mip level 0
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip0)
C(R_DrawSurfaceBlock8_mip0):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip0:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $4,%ecx
orl $0xF0000000,%ebp
sarl $4,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip0:
movl %ebp,C(lightdelta)
movb 14(%esi),%cl
sarl $4,%ebp
movb %dh,%bh
movb 15(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch0:
movb 13(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch1:
movb 12(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch2:
movb 11(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch3:
movb 10(%esi),%cl
movl %eax,12(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch4:
movb 9(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch5:
movb 8(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch6:
movb 7(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch7:
movb 6(%esi),%cl
movl %eax,8(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch8:
movb 5(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch9:
movb 4(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch10:
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch11:
movb 2(%esi),%cl
movl %eax,4(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch12:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch13:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch14:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch15:
movl C(lightdelta),%ebp
movl %eax,(%edi)
addl C(sourcetstep),%esi
addl C(surfrowbytes),%edi
addl C(lightrightstep),%edx
addl C(lightdeltastep),%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip0
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip0
subl C(r_stepback),%esi
LSkip_mip0:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip0
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 1
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip1)
C(R_DrawSurfaceBlock8_mip1):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip1:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $3,%ecx
orl $0x70000000,%ebp
sarl $3,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip1:
movl %ebp,C(lightdelta)
movb 6(%esi),%cl
sarl $3,%ebp
movb %dh,%bh
movb 7(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch22:
movb 5(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch23:
movb 4(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch24:
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch25:
movb 2(%esi),%cl
movl %eax,4(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch26:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch27:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch28:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch29:
movl C(lightdelta),%ebp
movl %eax,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightrightstep),%eax
addl %eax,%edx
movl C(lightdeltastep),%eax
addl %eax,%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip1
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip1
subl C(r_stepback),%esi
LSkip_mip1:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip1
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 2
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip2)
C(R_DrawSurfaceBlock8_mip2):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip2:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $2,%ecx
orl $0x30000000,%ebp
sarl $2,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip2:
movl %ebp,C(lightdelta)
movb 2(%esi),%cl
sarl $2,%ebp
movb %dh,%bh
movb 3(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch18:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch19:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch20:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch21:
movl C(lightdelta),%ebp
movl %eax,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightrightstep),%eax
addl %eax,%edx
movl C(lightdeltastep),%eax
addl %eax,%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip2
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip2
subl C(r_stepback),%esi
LSkip_mip2:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip2
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 3
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip3)
C(R_DrawSurfaceBlock8_mip3):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip3:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
movl %ebp,C(lightdelta)
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $1,%ecx
sarl $1,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
sarl $1,%ebp
orl $0xF0000000,%ebx
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
movb 1(%esi),%bl
subl %ecx,%ecx // high word must be 0 in loop for addressing
movb %dh,%bh
movb (%esi),%cl
addl %ebp,%edx
movb %dh,%ch
movb 0x12345678(%ebx),%al
LBPatch16:
movl C(lightright),%edx
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch17:
movb %al,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightdeltastep),%eax
movl C(lightdelta),%ebp
movb (%esi),%cl
addl %eax,%ebp
movl C(lightrightstep),%eax
sarl $1,%ebp
addl %eax,%edx
movb %dh,%bh
movb 1(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
movb 0x12345678(%ebx),%al
LBPatch30:
movl C(sourcetstep),%edx
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch31:
movb %al,(%edi)
movl C(surfrowbytes),%ebp
addl %edx,%esi
addl %ebp,%edi
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip3
subl C(r_stepback),%esi
LSkip_mip3:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip3
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
.globl C(R_Surf8End)
C(R_Surf8End):
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
.align 4
LPatchTable8:
.long LBPatch0-4
.long LBPatch1-4
.long LBPatch2-4
.long LBPatch3-4
.long LBPatch4-4
.long LBPatch5-4
.long LBPatch6-4
.long LBPatch7-4
.long LBPatch8-4
.long LBPatch9-4
.long LBPatch10-4
.long LBPatch11-4
.long LBPatch12-4
.long LBPatch13-4
.long LBPatch14-4
.long LBPatch15-4
.long LBPatch16-4
.long LBPatch17-4
.long LBPatch18-4
.long LBPatch19-4
.long LBPatch20-4
.long LBPatch21-4
.long LBPatch22-4
.long LBPatch23-4
.long LBPatch24-4
.long LBPatch25-4
.long LBPatch26-4
.long LBPatch27-4
.long LBPatch28-4
.long LBPatch29-4
.long LBPatch30-4
.long LBPatch31-4
.text
.align 4
.globl C(R_Surf8Patch)
C(R_Surf8Patch):
pushl %ebx
movl C(colormap),%eax
movl $LPatchTable8,%ebx
movl $32,%ecx
LPatchLoop8:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop8
popl %ebx
ret
#endif // USE_INTEL_ASM

View file

@ -37,9 +37,7 @@
#include "QF/render.h" #include "QF/render.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "host.h"
#include "r_local.h" #include "r_local.h"
#include "sbar.h"
void void
R_CheckVariables (void) R_CheckVariables (void)

View file

@ -41,9 +41,6 @@ EXTRA_PROGRAMS= nq-3dfx nq-fbdev nq-glx nq-mgl nq-sdl \
noinst_LIBRARIES= libqfnet.a noinst_LIBRARIES= libqfnet.a
math_ASM= cl_math.S math_ASM= cl_math.S
soft_ASM= d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S \
d_varsa.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S sw_redgea.S \
sw_rvarsa.S surf16.S surf8.S
common_ASM= sys_ia32.S worlda.S $(math_ASM) common_ASM= sys_ia32.S worlda.S $(math_ASM)
common_SOURCES= game.c host_skin.c skin.c wad.c world.c com.c $(common_ASM) common_SOURCES= game.c host_skin.c skin.c wad.c world.c com.c $(common_ASM)
@ -74,7 +71,7 @@ client_LIB_DEPS= libqfnet.a $(qf_client_LIBS)
client_SOURCES= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_screen.c \ client_SOURCES= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_screen.c \
cl_parse.c cl_tent.c \ cl_parse.c cl_tent.c \
console.c keys.c sbar.c r_cvar.c r_efrag.c r_ent.c r_graph.c r_main.c \ console.c keys.c sbar.c \
r_part.c r_view.c nonintel.c locs.c pcx.c tga.c r_part.c r_view.c nonintel.c locs.c pcx.c tga.c
server_SOURCES= host.c host_cmd.c pr_cmds.c sv_cvar.c sv_main.c \ server_SOURCES= host.c host_cmd.c pr_cmds.c sv_cvar.c sv_main.c \
@ -86,66 +83,57 @@ combined_SOURCES= $(common_SOURCES) $(client_SOURCES) $(server_SOURCES) \
# Software-rendering targets # Software-rendering targets
# #
# ... Common stuff # ... Common stuff
soft_SOURCES= d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c \ soft_SOURCES= sw_rpart.c sw_view.c
d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c \
draw.c screen.c sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c \
sw_rdraw.c \
sw_redge.c sw_rlight.c sw_rmain.c sw_rmisc.c sw_rpart.c \
sw_rsky.c sw_rsprite.c sw_rsurf.c sw_skin.c sw_view.c \
$(soft_ASM)
# ... Linux FBDev # ... Linux FBDev
nq_fbdev_SOURCES= $(combined_SOURCES) $(soft_SOURCES) nq_fbdev_SOURCES= $(combined_SOURCES) $(soft_SOURCES)
nq_fbdev_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIBS) nq_fbdev_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIBS)
nq_fbdev_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIB_DEPS) nq_fbdev_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIB_DEPS)
# ... SciTech MGL # ... SciTech MGL
nq_mgl_SOURCES= $(combined_SOURCES) $(soft_SOURCES) nq_mgl_SOURCES= $(combined_SOURCES) $(soft_SOURCES)
nq_mgl_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIBS) $(MGL_LIBS) nq_mgl_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIBS) $(MGL_LIBS)
nq_mgl_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS) nq_mgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS)
# ... Sam Lantinga's Simple DirectMedia Layer, version 1.0 and higher # ... Sam Lantinga's Simple DirectMedia Layer, version 1.0 and higher
nq_sdl_SOURCES= $(combined_SOURCES) $(soft_SOURCES) nq_sdl_SOURCES= $(combined_SOURCES) $(soft_SOURCES)
nq_sdl_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS) nq_sdl_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS)
nq_sdl_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS) nq_sdl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS)
# ... Linux SVGAlib # ... Linux SVGAlib
nq_svga_SOURCES= $(combined_SOURCES) $(soft_SOURCES) nq_svga_SOURCES= $(combined_SOURCES) $(soft_SOURCES)
nq_svga_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS) nq_svga_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS)
nq_svga_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIB_DEPS) nq_svga_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIB_DEPS)
# ... X11 # ... X11
nq_x11_SOURCES= $(combined_SOURCES) $(soft_SOURCES) nq_x11_SOURCES= $(combined_SOURCES) $(soft_SOURCES)
nq_x11_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) nq_x11_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB)
nq_x11_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIB_DEPS) nq_x11_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIB_DEPS)
# OpenGL-using targets # OpenGL-using targets
# ... Common stuff # ... Common stuff
ogl_SOURCES= noisetextures.c gl_textures.c gl_draw.c gl_dyn_fires.c \ ogl_SOURCES= gl_dyn_part.c gl_view.c
gl_dyn_part.c gl_dyn_textures.c gl_graph.c gl_rlight.c \
gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_skin.c \
gl_sky.c gl_sky_clip.c gl_view.c gl_warp.c
# ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL # ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL
nq_3dfx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) nq_3dfx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES)
nq_3dfx_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIBS) $(TDFXGL_LIBS) $(SVGA_LIBS) $(DL_LIBS) nq_3dfx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIBS) $(TDFXGL_LIBS) $(SVGA_LIBS) $(DL_LIBS)
nq_3dfx_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIB_DEPS) nq_3dfx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIB_DEPS)
# ... OpenGL in X Window # ... OpenGL in X Window
nq_glx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) nq_glx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES)
nq_glx_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIBS) $(GLX_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(DL_LIBS) nq_glx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIBS) $(GLX_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(DL_LIBS)
nq_glx_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS) nq_glx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS)
# ... Simple Directmedia Layer, version 1.1 and higher, in GL mode # ... Simple Directmedia Layer, version 1.1 and higher, in GL mode
nq_sgl_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) nq_sgl_SOURCES= $(combined_SOURCES) $(ogl_SOURCES)
nq_sgl_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(X_LIBS) $(SDL_LIBS) $(GLX_LIBS) $(DL_LIBS) nq_sgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(X_LIBS) $(SDL_LIBS) $(GLX_LIBS) $(DL_LIBS)
nq_sgl_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIB_DEPS) nq_sgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIB_DEPS)
# ... SGI/Microsoft WGL (Windows OpenGL) # ... SGI/Microsoft WGL (Windows OpenGL)
nq_wgl_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) conproc.c nq_wgl_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) conproc.c
nq_wgl_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIBS) $(GLX_LIBS) -lgdi32 -lcomctl32 -lwinmm nq_wgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIBS) $(GLX_LIBS) -lgdi32 -lcomctl32 -lwinmm
nq_wgl_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIB_DEPS) nq_wgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIB_DEPS)
# Dedicated Server # Dedicated Server
ded_SOURCES= sys_unixd.c sv_ded.c ded_SOURCES= sys_unixd.c sv_ded.c

View file

@ -1,176 +0,0 @@
/*
d_copy.S
x86 assembly-language screen copying code.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
.data
LCopyWidth: .long 0
LBlockSrcStep: .long 0
LBlockDestStep: .long 0
LSrcDelta: .long 0
LDestDelta: .long 0
#define bufptr 4+16
// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
// no Mode X mode is wider than 360, all the data should fit in the cache for
// the passes for the next 3 planes
.text
.globl C(VGA_UpdatePlanarScreen)
C(VGA_UpdatePlanarScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
movl C(VGA_bufferrowbytes),%eax
shll $1,%eax
movl %eax,LBlockSrcStep
movl C(VGA_rowbytes),%eax
shll $1,%eax
movl %eax,LBlockDestStep
movl $0x3C4,%edx
movb $2,%al
outb %al,%dx // point the SC to the Map Mask
incl %edx
movl bufptr(%esp),%esi
movl C(VGA_pagebase),%edi
movl C(VGA_height),%ebp
shrl $1,%ebp
movl C(VGA_width),%ecx
movl C(VGA_bufferrowbytes),%eax
subl %ecx,%eax
movl %eax,LSrcDelta
movl C(VGA_rowbytes),%eax
shll $2,%eax
subl %ecx,%eax
movl %eax,LDestDelta
shrl $4,%ecx
movl %ecx,LCopyWidth
LRowLoop:
movb $1,%al
LPlaneLoop:
outb %al,%dx
movb $2,%ah
pushl %esi
pushl %edi
LRowSetLoop:
movl LCopyWidth,%ecx
LColumnLoop:
movb 12(%esi),%bh
movb 8(%esi),%bl
shll $16,%ebx
movb 4(%esi),%bh
movb (%esi),%bl
movl %ebx,(%edi)
addl $16,%esi
addl $4,%edi
decl %ecx
jnz LColumnLoop
addl LDestDelta,%edi
addl LSrcDelta,%esi
decb %ah
jnz LRowSetLoop
popl %edi
popl %esi
incl %esi
shlb $1,%al
cmpb $16,%al
jnz LPlaneLoop
subl $4,%esi
addl LBlockSrcStep,%esi
addl LBlockDestStep,%edi
decl %ebp
jnz LRowLoop
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#define srcptr 4+16
#define destptr 8+16
#define width 12+16
#define height 16+16
#define srcrowbytes 20+16
#define destrowbytes 24+16
.globl C(VGA_UpdateLinearScreen)
C(VGA_UpdateLinearScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
cld
movl srcptr(%esp),%esi
movl destptr(%esp),%edi
movl width(%esp),%ebx
movl srcrowbytes(%esp),%eax
subl %ebx,%eax
movl destrowbytes(%esp),%edx
subl %ebx,%edx
shrl $2,%ebx
movl height(%esp),%ebp
LLRowLoop:
movl %ebx,%ecx
rep/movsl (%esi),(%edi)
addl %eax,%esi
addl %edx,%edi
decl %ebp
jnz LLRowLoop
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#endif /* USE_INTEL_ASM */

View file

@ -1,422 +0,0 @@
/*
d_scan.c
Portable C scan-level rasterization code, all pixel depths.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "client.h"
#include "d_local.h"
#include "r_local.h"
#include "QF/render.h"
unsigned char *r_turb_pbase, *r_turb_pdest;
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
int *r_turb_turb;
int r_turb_spancount;
void D_DrawTurbulent8Span (void);
/*
D_WarpScreen
this performs a slight compression of the screen at the same time as
the sine warp, to keep the edges from wrapping
*/
void
D_WarpScreen (void)
{
int w, h;
int u, v;
byte *dest;
int *turb;
int *col;
byte **row;
byte *rowptr[1024];
int column[1280];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_vrect.width;
hratio = h / (float) scr_vrect.height;
for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) {
rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
(screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2)));
}
for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = intsintable + ((int) (cl.time * SPEED) & (CYCLE - 1));
dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
for (v = 0; v < scr_vrect.height; v++, dest += vid.rowbytes) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_vrect.width; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
#ifndef USE_INTEL_ASM
void
D_DrawTurbulent8Span (void)
{
int sturb, tturb;
do {
sturb =
((r_turb_s + r_turb_turb[(r_turb_t >> 16) & (CYCLE - 1)]) >> 16) &
63;
tturb =
((r_turb_t + r_turb_turb[(r_turb_s >> 16) & (CYCLE - 1)]) >> 16) &
63;
*r_turb_pdest++ = *(r_turb_pbase + (tturb << 6) + sturb);
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
}
#endif // !USE_INTEL_ASM
void
Turbulent8 (espan_t *pspan)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
r_turb_turb = sintable + ((int) (cl.time * SPEED) & (CYCLE - 1));
r_turb_sstep = 0; // keep compiler happy
r_turb_tstep = 0; // ditto
r_turb_pbase = (unsigned char *) cacheblock;
sdivz16stepu = d_sdivzstepu * 16;
tdivz16stepu = d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16;
do {
r_turb_pdest = (unsigned char *) ((byte *) d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
r_turb_s = (int) (sdivz * z) + sadjust;
if (r_turb_s > bbextents)
r_turb_s = bbextents;
else if (r_turb_s < 0)
r_turb_s = 0;
r_turb_t = (int) (tdivz * z) + tadjust;
if (r_turb_t > bbextentt)
r_turb_t = bbextentt;
else if (r_turb_t < 0)
r_turb_t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 16)
r_turb_spancount = 16;
else
r_turb_spancount = count;
count -= r_turb_spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz16stepu;
tdivz += tdivz16stepu;
zi += zi16stepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0
// steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on
// <0 steps
r_turb_sstep = (snext - r_turb_s) >> 4;
r_turb_tstep = (tnext - r_turb_t) >> 4;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s and t
// steps across span by division, biasing steps low so we
// don't run off the texture
spancountminus1 = (float) (r_turb_spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps
// from causing overstepping & running
// off the edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on
// <0 steps
if (r_turb_spancount > 1) {
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
}
}
r_turb_s = r_turb_s & ((CYCLE << 16) - 1);
r_turb_t = r_turb_t & ((CYCLE << 16) - 1);
D_DrawTurbulent8Span ();
r_turb_s = snext;
r_turb_t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#ifndef USE_INTEL_ASM
void
D_DrawSpans8 (espan_t *pspan)
{
int count, spancount;
unsigned char *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (unsigned char *) cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
do {
pdest = (unsigned char *) ((byte *) d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
s = (int) (sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps
// from from causing overstepping &
// running off the edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#endif
#ifndef USE_INTEL_ASM
void
D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned int ltemp;
double zi;
float du, dv;
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial 1/z
du = (float) pspan->u;
dv = (float) pspan->v;
zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
// we count on FP exceptions being turned off to avoid range problems
izi = (int) (zi * 0x8000 * 0x10000);
if ((long) pdest & 0x02) {
*pdest++ = (short) (izi >> 16);
izi += izistep;
count--;
}
if ((doublecount = count >> 1) > 0) {
do {
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *) pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
if (count & 1)
*pdest = (short) (izi >> 16);
} while ((pspan = pspan->pnext) != NULL);
}
#endif

View file

@ -1,58 +0,0 @@
/*
d_vars.c
global refresh variables
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef USE_INTEL_ASM
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "host.h"
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
// global refresh variables -----------------------------
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
float d_sdivzstepu, d_tdivzstepu, d_zistepu;
float d_sdivzstepv, d_tdivzstepv, d_zistepv;
float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
fixed16_t sadjust, tadjust, bbextents, bbextentt;
pixel_t *cacheblock;
int cachewidth;
pixel_t *d_viewbuffer;
short *d_pzbuffer;
unsigned int d_zrowbytes;
unsigned int d_zwidth;
#endif // !USE_INTEL_ASM

View file

@ -1,834 +0,0 @@
/*
draw.c
this is the only file outside the refresh that touches the vid buffer
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/console.h"
#include "QF/draw.h"
#include "QF/quakefs.h"
#include "QF/sound.h"
#include "QF/sys.h"
#include "client.h"
#include "d_iface.h"
#include "r_cvar.h"
typedef struct {
vrect_t rect;
int width;
int height;
byte *ptexbytes;
int rowbytes;
} rectdesc_t;
static rectdesc_t r_rectdesc;
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
/* Support Routines */
typedef struct cachepic_s {
char name[MAX_QPATH];
cache_user_t cache;
} cachepic_t;
#define MAX_CACHED_PICS 128
cachepic_t cachepics[MAX_CACHED_PICS];
int numcachepics;
qpic_t *
Draw_PicFromWad (char *name)
{
return W_GetLumpName (name);
}
/*
Draw_ClearCache
This is a no-op in software targets
*/
void
Draw_ClearCache (void)
{
}
qpic_t *
Draw_CachePic (char *path, qboolean alpha)
{
cachepic_t *pic;
int i;
qpic_t *dat;
for (pic = cachepics, i = 0; i < numcachepics; pic++, i++)
if (!strcmp (path, pic->name))
break;
if (i == numcachepics) {
if (numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
numcachepics++;
strcpy (pic->name, path);
}
dat = Cache_Check (&pic->cache);
if (dat)
return dat;
// load the pic from disk
COM_LoadCacheFile (path, &pic->cache);
dat = (qpic_t *) pic->cache.data;
if (!dat) {
Sys_Error ("Draw_CachePic: failed to load %s", path);
}
SwapPic (dat);
return dat;
}
void
Draw_TextBox (int x, int y, int width, int lines)
{
qpic_t *p;
int cx, cy;
int n;
// draw left side
cx = x;
cy = y;
p = Draw_CachePic ("gfx/box_tl.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_ml.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bl.lmp", true);
Draw_Pic (cx, cy + 8, p);
// draw middle
cx += 8;
while (width > 0) {
cy = y;
p = Draw_CachePic ("gfx/box_tm.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mm.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
if (n == 1)
p = Draw_CachePic ("gfx/box_mm2.lmp", true);
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bm.lmp", true);
Draw_Pic (cx, cy + 8, p);
width -= 2;
cx += 16;
}
// draw right side
cy = y;
p = Draw_CachePic ("gfx/box_tr.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mr.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_br.lmp", true);
Draw_Pic (cx, cy + 8, p);
}
void
Draw_Init (void)
{
draw_chars = W_GetLumpName ("conchars");
draw_disc = W_GetLumpName ("disc");
draw_backtile = W_GetLumpName ("backtile");
r_rectdesc.width = draw_backtile->width;
r_rectdesc.height = draw_backtile->height;
r_rectdesc.ptexbytes = draw_backtile->data;
r_rectdesc.rowbytes = draw_backtile->width;
}
/*
Draw_Character8
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
*/
void
Draw_Character8 (int x, int y, int num)
{
byte *dest;
byte *source;
unsigned short *pusdest;
int drawline;
int row, col;
num &= 255;
if (y <= -8)
return; // totally off screen
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
return;
if (num < 0 || num > 255)
return;
row = num >> 4;
col = num & 15;
source = draw_chars + (row << 10) + (col << 3);
if (y < 0) { // clipped
drawline = 8 + y;
source -= 128 * y;
y = 0;
} else
drawline = 8;
if (r_pixbytes == 1) {
dest = vid.conbuffer + y * vid.conrowbytes + x;
while (drawline--) {
if (source[0])
dest[0] = source[0];
if (source[1])
dest[1] = source[1];
if (source[2])
dest[2] = source[2];
if (source[3])
dest[3] = source[3];
if (source[4])
dest[4] = source[4];
if (source[5])
dest[5] = source[5];
if (source[6])
dest[6] = source[6];
if (source[7])
dest[7] = source[7];
source += 128;
dest += vid.conrowbytes;
}
} else {
// FIXME: pre-expand to native format?
pusdest = (unsigned short *)
((byte *) vid.conbuffer + y * vid.conrowbytes + (x << 1));
while (drawline--) {
if (source[0])
pusdest[0] = d_8to16table[source[0]];
if (source[1])
pusdest[1] = d_8to16table[source[1]];
if (source[2])
pusdest[2] = d_8to16table[source[2]];
if (source[3])
pusdest[3] = d_8to16table[source[3]];
if (source[4])
pusdest[4] = d_8to16table[source[4]];
if (source[5])
pusdest[5] = d_8to16table[source[5]];
if (source[6])
pusdest[6] = d_8to16table[source[6]];
if (source[7])
pusdest[7] = d_8to16table[source[7]];
source += 128;
pusdest += (vid.conrowbytes >> 1);
}
}
}
void
Draw_String8 (int x, int y, char *str)
{
while (*str) {
Draw_Character8 (x, y, *str);
str++;
x += 8;
}
}
void
Draw_AltString8 (int x, int y, char *str)
{
while (*str) {
Draw_Character8 (x, y, (*str) | 0x80);
str++;
x += 8;
}
}
void
Draw_Pixel (int x, int y, byte color)
{
byte *dest;
unsigned short *pusdest;
if (r_pixbytes == 1) {
dest = vid.conbuffer + y * vid.conrowbytes + x;
*dest = color;
} else {
// FIXME: pre-expand to native format?
pusdest = (unsigned short *)
((byte *) vid.conbuffer + y * vid.conrowbytes + (x << 1));
*pusdest = d_8to16table[color];
}
}
void
Draw_Crosshair (int swap)
{
int x, y;
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor;
extern vrect_t scr_vrect;
byte c = crosshaircolor->int_val;
if (crosshair->int_val == 2) {
x = scr_vrect.x + scr_vrect.width / 2 + cl_crossx->int_val;
y = scr_vrect.y + scr_vrect.height / 2 + cl_crossy->int_val;
Draw_Pixel (x - 1, y, c);
Draw_Pixel (x - 3, y, c);
Draw_Pixel (x + 1, y, c);
Draw_Pixel (x + 3, y, c);
Draw_Pixel (x, y - 1, c);
Draw_Pixel (x, y - 3, c);
Draw_Pixel (x, y + 1, c);
Draw_Pixel (x, y + 3, c);
} else if (crosshair->int_val)
Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 +
cl_crossx->int_val,
scr_vrect.y + scr_vrect.height / 2 - 4 +
cl_crossy->int_val, '+');
}
void
Draw_Pic (int x, int y, qpic_t *pic)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
if (pic->width & 7) { // general
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u++)
if ((tbyte = source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
dest += vid.rowbytes;
source += pic->width;
}
} else { // unwound
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u += 8) {
if ((tbyte = source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR)
dest[u + 1] = tbyte;
if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR)
dest[u + 2] = tbyte;
if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR)
dest[u + 3] = tbyte;
if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR)
dest[u + 4] = tbyte;
if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR)
dest[u + 5] = tbyte;
if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR)
dest[u + 6] = tbyte;
if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR)
dest[u + 7] = tbyte;
}
dest += vid.rowbytes;
source += pic->width;
}
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u++) {
tbyte = source[u];
if (tbyte != TRANSPARENT_COLOR) {
pusdest[u] = d_8to16table[tbyte];
}
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
void
Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
int height)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
if ((x < 0) ||
(x + width > vid.width) || (y < 0) || (y + height > vid.height)) {
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data + srcy * pic->width + srcx;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < height; v++) {
memcpy (dest, source, width);
dest += vid.rowbytes;
source += pic->width;
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < height; v++) {
for (u = srcx; u < (srcx + width); u++) {
pusdest[u] = d_8to16table[source[u]];
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
void
Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_TransPic: bad coordinates");
}
source = pic->data;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
if (pic->width & 7) { // general
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u++)
if ((tbyte = source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
dest += vid.rowbytes;
source += pic->width;
}
} else { // unwound
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u += 8) {
if ((tbyte = source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR)
dest[u + 1] = translation[tbyte];
if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR)
dest[u + 2] = translation[tbyte];
if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR)
dest[u + 3] = translation[tbyte];
if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR)
dest[u + 4] = translation[tbyte];
if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR)
dest[u + 5] = translation[tbyte];
if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR)
dest[u + 6] = translation[tbyte];
if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR)
dest[u + 7] = translation[tbyte];
}
dest += vid.rowbytes;
source += pic->width;
}
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u++) {
tbyte = source[u];
if (tbyte != TRANSPARENT_COLOR) {
pusdest[u] = d_8to16table[tbyte];
}
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
void
Draw_ConsoleBackground (int lines)
{
int x, y, v;
byte *src, *dest;
unsigned short *pusdest;
int f, fstep;
qpic_t *conback;
conback = Draw_CachePic ("gfx/conback.lmp", false);
// draw the pic
if (r_pixbytes == 1) {
dest = vid.conbuffer;
for (y = 0; y < lines; y++, dest += vid.conrowbytes) {
v = (vid.conheight - lines + y) * 200 / vid.conheight;
src = conback->data + v * 320;
if (vid.conwidth == 320)
memcpy (dest, src, vid.conwidth);
else {
f = 0;
fstep = 320 * 0x10000 / vid.conwidth;
for (x = 0; x < vid.conwidth; x += 4) {
dest[x] = src[f >> 16];
f += fstep;
dest[x + 1] = src[f >> 16];
f += fstep;
dest[x + 2] = src[f >> 16];
f += fstep;
dest[x + 3] = src[f >> 16];
f += fstep;
}
}
}
} else {
pusdest = (unsigned short *) vid.conbuffer;
for (y = 0; y < lines; y++, pusdest += (vid.conrowbytes >> 1)) {
// FIXME: pre-expand to native format?
// FIXME: does the endian switching go away in production?
v = (vid.conheight - lines + y) * 200 / vid.conheight;
src = conback->data + v * 320;
f = 0;
fstep = 320 * 0x10000 / vid.conwidth;
for (x = 0; x < vid.conwidth; x += 4) {
pusdest[x] = d_8to16table[src[f >> 16]];
f += fstep;
pusdest[x + 1] = d_8to16table[src[f >> 16]];
f += fstep;
pusdest[x + 2] = d_8to16table[src[f >> 16]];
f += fstep;
pusdest[x + 3] = d_8to16table[src[f >> 16]];
f += fstep;
}
}
}
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string)
* 8 - 11, lines - 14, cl_verstring->string);
}
void
R_DrawRect8 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
byte *pdest;
pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
srcdelta = rowbytes - prect->width;
destdelta = vid.rowbytes - prect->width;
if (transparent) {
for (i = 0; i < prect->height; i++) {
for (j = 0; j < prect->width; j++) {
t = *psrc;
if (t != TRANSPARENT_COLOR) {
*pdest = t;
}
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
} else {
for (i = 0; i < prect->height; i++) {
memcpy (pdest, psrc, prect->width);
psrc += rowbytes;
pdest += vid.rowbytes;
}
}
}
void
R_DrawRect16 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
unsigned short *pdest;
// FIXME: would it be better to pre-expand native-format versions?
pdest = (unsigned short *) vid.buffer +
(prect->y * (vid.rowbytes >> 1)) + prect->x;
srcdelta = rowbytes - prect->width;
destdelta = (vid.rowbytes >> 1) - prect->width;
if (transparent) {
for (i = 0; i < prect->height; i++) {
for (j = 0; j < prect->width; j++) {
t = *psrc;
if (t != TRANSPARENT_COLOR) {
*pdest = d_8to16table[t];
}
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
} else {
for (i = 0; i < prect->height; i++) {
for (j = 0; j < prect->width; j++) {
*pdest = d_8to16table[*psrc];
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
}
}
/*
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
*/
void
Draw_TileClear (int x, int y, int w, int h)
{
int width, height, tileoffsetx, tileoffsety;
byte *psrc;
vrect_t vr;
r_rectdesc.rect.x = x;
r_rectdesc.rect.y = y;
r_rectdesc.rect.width = w;
r_rectdesc.rect.height = h;
vr.y = r_rectdesc.rect.y;
height = r_rectdesc.rect.height;
tileoffsety = vr.y % r_rectdesc.height;
while (height > 0) {
vr.x = r_rectdesc.rect.x;
width = r_rectdesc.rect.width;
if (tileoffsety != 0)
vr.height = r_rectdesc.height - tileoffsety;
else
vr.height = r_rectdesc.height;
if (vr.height > height)
vr.height = height;
tileoffsetx = vr.x % r_rectdesc.width;
while (width > 0) {
if (tileoffsetx != 0)
vr.width = r_rectdesc.width - tileoffsetx;
else
vr.width = r_rectdesc.width;
if (vr.width > width)
vr.width = width;
psrc = r_rectdesc.ptexbytes +
(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
if (r_pixbytes == 1) {
R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
} else {
R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
}
vr.x += vr.width;
width -= vr.width;
tileoffsetx = 0; // only the left tile can be left-clipped
}
vr.y += vr.height;
height -= vr.height;
tileoffsety = 0; // only the top tile can be top-clipped
}
}
/*
Draw_Fill
Fills a box of pixels with a single color
*/
void
Draw_Fill (int x, int y, int w, int h, int c)
{
byte *dest;
unsigned short *pusdest;
unsigned int uc;
int u, v;
if (x < 0 || x + w > vid.width || y < 0 || y + h > vid.height) {
Con_Printf ("Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c);
return;
}
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < h; v++, dest += vid.rowbytes)
for (u = 0; u < w; u++)
dest[u] = c;
} else {
uc = d_8to16table[c];
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < h; v++, pusdest += (vid.rowbytes >> 1))
for (u = 0; u < w; u++)
pusdest[u] = uc;
}
}
void
Draw_FadeScreen (void)
{
int x, y;
byte *pbuf;
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
for (y = 0; y < vid.height; y++) {
int t;
pbuf = (byte *) (vid.buffer + vid.rowbytes * y);
t = (y & 1) << 1;
for (x = 0; x < vid.width; x++) {
if ((x & 3) != t)
pbuf[x] = 0;
}
}
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
}
/*
Draw_BeginDisc
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
*/
void
Draw_BeginDisc (void)
{
D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
}
/*
Draw_EndDisc
Erases the disc icon.
Call after completing any disc IO
*/
void
Draw_EndDisc (void)
{
D_EndDirectRect (vid.width - 24, 0, 24, 24);
}

View file

@ -712,6 +712,7 @@ _Host_Frame (float time)
r_paused = cl.paused; r_paused = cl.paused;
r_active = cls.state == ca_active; r_active = cls.state == ca_active;
r_view_model = &cl.viewent; r_view_model = &cl.viewent;
r_frametime = host_frametime;
CL_UpdateScreen (cl.time); CL_UpdateScreen (cl.time);

View file

@ -97,78 +97,66 @@ client_LIB_DEPS= libqfnet.a $(qf_client_LIBS)
client_SOURCES= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \ client_SOURCES= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \
cl_main.c cl_misc.c cl_ngraph.c cl_parse.c cl_screen.c cl_pred.c \ cl_main.c cl_misc.c cl_ngraph.c cl_parse.c cl_screen.c cl_pred.c \
cl_skin.c cl_slist.c cl_tent.c \ cl_skin.c cl_slist.c cl_tent.c \
console.c keys.c locs.c nonintel.c pcx.c r_cvar.c r_efrag.c \ console.c keys.c locs.c nonintel.c pcx.c \
r_ent.c r_graph.c r_main.c r_view.c sbar.c skin.c teamplay.c tga.c \ r_view.c sbar.c skin.c teamplay.c tga.c \
wad.c cl_math.S $(syscl_SRC) wad.c cl_math.S $(syscl_SRC)
# Software-rendering clients # Software-rendering clients
# #
# ... Common stuff # ... Common stuff
soft_SOURCES= d_edge.c d_fill.c d_init.c d_modech.c \ soft_SOURCES= sw_rpart.c sw_view.c
d_part.c d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c \
d_vars.c d_zpoint.c draw.c sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c \
sw_rdraw.c sw_redge.c sw_rlight.c sw_rmain.c sw_rmisc.c \
sw_rpart.c sw_rsky.c sw_rsprite.c sw_rsurf.c sw_skin.c \
sw_view.c screen.c \
\
d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S \
d_varsa.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S sw_redgea.S \
sw_rvarsa.S surf16.S surf8.S
# ... Linux FBDev # ... Linux FBDev
qw_client_fbdev_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES) qw_client_fbdev_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES)
qw_client_fbdev_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIBS) qw_client_fbdev_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIBS)
qw_client_fbdev_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIB_DEPS) qw_client_fbdev_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFfbdev.la $(client_LIB_DEPS)
# ... SciTech MGL # ... SciTech MGL
qw_client_mgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES) qw_client_mgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES)
qw_client_mgl_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIBS) $(MGL_LIBS) qw_client_mgl_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIBS) $(MGL_LIBS)
qw_client_mgl_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS) qw_client_mgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS)
# ... Simple DirectMedia Layer, version 1.0 and higher # ... Simple DirectMedia Layer, version 1.0 and higher
qw_client_sdl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES) qw_client_sdl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES)
qw_client_sdl_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS) qw_client_sdl_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS)
qw_client_sdl_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS) qw_client_sdl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS)
# ... Linux SVGAlib # ... Linux SVGAlib
qw_client_svga_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES) qw_client_svga_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES)
qw_client_svga_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS) qw_client_svga_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS)
qw_client_svga_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIB_DEPS) qw_client_svga_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIB_DEPS)
# ... X11 # ... X11
qw_client_x11_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES) qw_client_x11_SOURCES= $(common_SOURCES) $(client_SOURCES) $(soft_SOURCES)
qw_client_x11_LDADD= ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) qw_client_x11_LDADD= ../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB)
qw_client_x11_DEPENDENCIES=../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIB_DEPS) qw_client_x11_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_sw.la ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFx11.la $(client_LIB_DEPS)
# OpenGL-using clients # OpenGL-using clients
# #
# ... Common stuff # ... Common stuff
ogl_SOURCES= noisetextures.c gl_textures.c gl_draw.c gl_dyn_fires.c \ ogl_SOURCES= gl_dyn_part.c gl_view.c
gl_dyn_part.c gl_dyn_textures.c gl_graph.c gl_rlight.c \
gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_skin.c \
gl_sky.c gl_sky_clip.c gl_view.c gl_warp.c
# ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL # ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL
qw_client_3dfx_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES) qw_client_3dfx_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES)
qw_client_3dfx_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIBS) $(TDFXGL_LIBS) $(SVGA_LIBS) $(DL_LIBS) qw_client_3dfx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIBS) $(TDFXGL_LIBS) $(SVGA_LIBS) $(DL_LIBS)
qw_client_3dfx_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIB_DEPS) qw_client_3dfx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFtdfx.la $(client_LIB_DEPS)
# ... OpenGL in X Window # ... OpenGL in X Window
qw_client_glx_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES) qw_client_glx_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES)
qw_client_glx_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIBS) $(GLX_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(DL_LIBS) qw_client_glx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIBS) $(GLX_LIBS) $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(DL_LIBS)
qw_client_glx_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS) qw_client_glx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS)
# ... Simple DirectMedia Layer, version 1.1 and higher, in GL mode # ... Simple DirectMedia Layer, version 1.1 and higher, in GL mode
qw_client_sgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES) qw_client_sgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES)
qw_client_sgl_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(SDL_LIBS) $(X_LIBS) $(GLX_LIBS) $(DL_LIBS) qw_client_sgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(SDL_LIBS) $(X_LIBS) $(GLX_LIBS) $(DL_LIBS)
qw_client_sgl_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIB_DEPS) qw_client_sgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIB_DEPS)
# ... SGI/Microsoft WGL (Windows OpenGL) # ... SGI/Microsoft WGL (Windows OpenGL)
qw_client_wgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES) qw_client_wgl_SOURCES= $(common_SOURCES) $(client_SOURCES) $(ogl_SOURCES)
qw_client_wgl_LDADD= ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIBS) $(GLX_LIBS) -lgdi32 -lwinmm qw_client_wgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIBS) $(GLX_LIBS) -lgdi32 -lwinmm
qw_client_wgl_DEPENDENCIES=../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIB_DEPS) qw_client_wgl_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFwgl.la $(client_LIB_DEPS)
# Stuff that doesn't get linked into an executable NEEDS to be mentioned here, # Stuff that doesn't get linked into an executable NEEDS to be mentioned here,
# or it won't be distributed with 'make dist' # or it won't be distributed with 'make dist'

View file

@ -1496,6 +1496,7 @@ Host_Frame (float time)
r_paused = cl.paused; r_paused = cl.paused;
r_active = cls.state == ca_active; r_active = cls.state == ca_active;
r_view_model = &cl.viewent; r_view_model = &cl.viewent;
r_frametime = host_frametime;
// don't allow cheats in multiplayer // don't allow cheats in multiplayer
if (!atoi (Info_ValueForKey (cl.serverinfo, "watervis"))) if (!atoi (Info_ValueForKey (cl.serverinfo, "watervis")))

View file

@ -1,176 +0,0 @@
/*
d_copy.S
x86 assembly-language screen copying code.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
.data
LCopyWidth: .long 0
LBlockSrcStep: .long 0
LBlockDestStep: .long 0
LSrcDelta: .long 0
LDestDelta: .long 0
#define bufptr 4+16
// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
// no Mode X mode is wider than 360, all the data should fit in the cache for
// the passes for the next 3 planes
.text
.globl C(VGA_UpdatePlanarScreen)
C(VGA_UpdatePlanarScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
movl C(VGA_bufferrowbytes),%eax
shll $1,%eax
movl %eax,LBlockSrcStep
movl C(VGA_rowbytes),%eax
shll $1,%eax
movl %eax,LBlockDestStep
movl $0x3C4,%edx
movb $2,%al
outb %al,%dx // point the SC to the Map Mask
incl %edx
movl bufptr(%esp),%esi
movl C(VGA_pagebase),%edi
movl C(VGA_height),%ebp
shrl $1,%ebp
movl C(VGA_width),%ecx
movl C(VGA_bufferrowbytes),%eax
subl %ecx,%eax
movl %eax,LSrcDelta
movl C(VGA_rowbytes),%eax
shll $2,%eax
subl %ecx,%eax
movl %eax,LDestDelta
shrl $4,%ecx
movl %ecx,LCopyWidth
LRowLoop:
movb $1,%al
LPlaneLoop:
outb %al,%dx
movb $2,%ah
pushl %esi
pushl %edi
LRowSetLoop:
movl LCopyWidth,%ecx
LColumnLoop:
movb 12(%esi),%bh
movb 8(%esi),%bl
shll $16,%ebx
movb 4(%esi),%bh
movb (%esi),%bl
movl %ebx,(%edi)
addl $16,%esi
addl $4,%edi
decl %ecx
jnz LColumnLoop
addl LDestDelta,%edi
addl LSrcDelta,%esi
decb %ah
jnz LRowSetLoop
popl %edi
popl %esi
incl %esi
shlb $1,%al
cmpb $16,%al
jnz LPlaneLoop
subl $4,%esi
addl LBlockSrcStep,%esi
addl LBlockDestStep,%edi
decl %ebp
jnz LRowLoop
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#define srcptr 4+16
#define destptr 8+16
#define width 12+16
#define height 16+16
#define srcrowbytes 20+16
#define destrowbytes 24+16
.globl C(VGA_UpdateLinearScreen)
C(VGA_UpdateLinearScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
cld
movl srcptr(%esp),%esi
movl destptr(%esp),%edi
movl width(%esp),%ebx
movl srcrowbytes(%esp),%eax
subl %ebx,%eax
movl destrowbytes(%esp),%edx
subl %ebx,%edx
shrl $2,%ebx
movl height(%esp),%ebp
LLRowLoop:
movl %ebx,%ecx
rep/movsl (%esi),(%edi)
addl %eax,%esi
addl %edx,%edi
decl %ebp
jnz LLRowLoop
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#endif /* USE_INTEL_ASM */

File diff suppressed because it is too large Load diff

View file

@ -1,981 +0,0 @@
/*
d_draw16.S
x86 assembly-language horizontal 8-bpp span-drawing code, with
16-pixel subdivision.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
#ifdef USE_INTEL_ASM
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with no transparency and
// 16-pixel subdivision.
//
// Assumes there is at least one span in pspans, and that every span
// contains at least one pixel
//----------------------------------------------------------------------
.data
.text
// out-of-line, rarely-needed clamping code
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
LClampLow2:
movl $4096,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
LClampLow3:
movl $4096,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
LClampLow4:
movl $4096,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
LClampLow5:
movl $4096,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
#define pspans 4+16
.align 4
.globl C(D_DrawSpans16)
C(D_DrawSpans16):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
//
// set up scaled-by-16 steps, for 16-long segments; also set up cacheblock
// and span list pointers
//
// TODO: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_16
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_16
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_16
movl %edx,pbase // pbase = cacheblock
fstps zi16stepu
fstps tdivz16stepu
fstps sdivz16stepu
LSpanLoop:
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl espan_t_v(%ebx)
fildl espan_t_u(%ebx)
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
//
// calculate and clamp s & t
//
fdivr %st(0),%st(1) // 1/z | z*64k | t/z | s/z
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ecx
movl espan_t_v(%ebx),%eax
movl %ebx,pspantemp // preserve spans pointer
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ecx,%edi
movl espan_t_u(%ebx),%ecx
addl %ecx,%edi // pdest = &pdestspan[scans->u];
movl espan_t_count(%ebx),%ecx
//
// now start the FDIV for the end of the span
//
cmpl $16,%ecx
ja LSetupNotLast1
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fildl spancountminus1
flds C(d_tdivzstepu) // C(d_tdivzstepu) | spancountminus1
flds C(d_zistepu) // C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
fmul %st(2),%st(0) // C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
fxch %st(1) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(2) // scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
// C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
// C(d_tdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
faddp %st(0),%st(3)
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fadds zi16stepu
fxch %st(2)
fadds sdivz16stepu
fxch %st(2)
flds tdivz16stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
//
// calculate the texture starting address
//
sarl $16,%eax
movl C(cachewidth),%edx
imull %edx,%eax // (tfrac >> 16) * cachewidth
addl %ebx,%esi
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
//
// determine whether last span or not
//
cmpl $16,%ecx
jna LLastSegment
//
// not the last segment; do full 16-wide segment
//
LNotLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
movb (%esi),%bl // get first source texel
subl $16,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
movl %ecx,counttemp // remember count of remaining pixels
movl C(tadjust),%ecx
movb %bl,(%edi) // store first dest pixel
addl %eax,%ebp
addl %edx,%ecx
movl C(bbextents),%eax
movl C(bbextentt),%edx
cmpl $4096,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
cmpl $4096,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
movl %ebp,snext
movl %ecx,tnext
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $20,%eax // tstep >>= 16;
jz LZero
sarl $20,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
imull %ebx,%eax
jmp LSetUp1
LZero:
sarl $20,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
LSetUp1:
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $12,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $12,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
movl %ecx,tstep
addl %ecx,%edx // advance tfrac fractional part by tstep frac
sbbl %ecx,%ecx // turn tstep carry into -1 (0 if none)
addl %ebp,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%ecx,4),%esi // point to next source texel
addl tstep,%edx
sbbl %ecx,%ecx
movb (%esi),%al
addl %ebp,%ebx
movb %al,1(%edi)
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,6(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,7(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
//
// start FDIV for end of next segment in flight, so it can overlap
//
movl counttemp,%ecx
cmpl $16,%ecx // more than one segment after this?
ja LSetupNotLast2 // yes
decl %ecx
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
fildl spancountminus1
flds C(d_zistepu) // C(d_zistepu) | spancountminus1
fmul %st(1),%st(0) // C(d_zistepu)*scm1 | scm1
flds C(d_tdivzstepu) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
faddp %st(0),%st(3) // C(d_tdivzstepu)*scm1 | scm1
fxch %st(1) // scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
flds fp_64k // 64k | C(d_sdivzstepu)*scm1
fxch %st(1) // C(d_sdivzstepu)*scm1 | 64k
faddp %st(0),%st(4) // 64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
.align 4
LSetupNotLast2:
fadds zi16stepu
fxch %st(2)
fadds sdivz16stepu
fxch %st(2)
flds tdivz16stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
movl %ecx,counttemp
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,8(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,9(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,10(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,11(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,12(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,13(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,14(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl $16,%edi
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
movl counttemp,%ecx // retrieve count
//
// determine whether last span or not
//
cmpl $16,%ecx // are there multiple segments remaining?
movb %al,-1(%edi)
ja LNotLastSegment // yes
//
// last segment of scan
//
LLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movb (%esi),%al // load first texel in segment
movl C(tadjust),%ebx
movb %al,(%edi) // store first pixel in segment
movl C(sadjust),%eax
addl snext,%eax
addl tnext,%ebx
movl C(bbextents),%ebp
movl C(bbextentt),%edx
cmpl $4096,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
cmpl $4096,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
imull reciprocal_table_16-8(,%ecx,4) // sstep = (snext - s) /
// (spancount-1)
movl %edx,%ebp
movl %ebx,%eax
imull reciprocal_table_16-8(,%ecx,4) // tstep = (tnext - t) /
// (spancount-1)
LSetEntryvec:
//
// set up advancetable
//
movl entryvec_table_16(,%ecx,4),%ebx
movl %edx,%eax
movl %ebx,jumptemp // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%edx // tstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%ecx // sstep >>= 16;
imull %ebx,%edx
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
movl %eax,tstep
movl %ecx,%edx
addl %eax,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
jmp *jumptemp // jump to the number-of-pixels handler
//----------------------------------------
LNoSteps:
movb (%esi),%al // load first texel in segment
subl $15,%edi // adjust for hardwired offset
jmp LEndSpan
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
//----------------------------------------
.globl Entry2_16, Entry3_16, Entry4_16, Entry5_16
.globl Entry6_16, Entry7_16, Entry8_16, Entry9_16
.globl Entry10_16, Entry11_16, Entry12_16, Entry13_16
.globl Entry14_16, Entry15_16, Entry16_16
Entry2_16:
subl $14,%edi // adjust for hardwired offsets
movb (%esi),%al
jmp LEntry2_16
//----------------------------------------
Entry3_16:
subl $13,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
jmp LEntry3_16
//----------------------------------------
Entry4_16:
subl $12,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry4_16
//----------------------------------------
Entry5_16:
subl $11,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry5_16
//----------------------------------------
Entry6_16:
subl $10,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry6_16
//----------------------------------------
Entry7_16:
subl $9,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry7_16
//----------------------------------------
Entry8_16:
subl $8,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry8_16
//----------------------------------------
Entry9_16:
subl $7,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry9_16
//----------------------------------------
Entry10_16:
subl $6,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry10_16
//----------------------------------------
Entry11_16:
subl $5,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry11_16
//----------------------------------------
Entry12_16:
subl $4,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry12_16
//----------------------------------------
Entry13_16:
subl $3,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry13_16
//----------------------------------------
Entry14_16:
subl $2,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry14_16
//----------------------------------------
Entry15_16:
decl %edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry15_16
//----------------------------------------
Entry16_16:
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,1(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry15_16:
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry14_16:
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry13_16:
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry12_16:
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry11_16:
sbbl %ecx,%ecx
movb %al,6(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry10_16:
sbbl %ecx,%ecx
movb %al,7(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry9_16:
sbbl %ecx,%ecx
movb %al,8(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry8_16:
sbbl %ecx,%ecx
movb %al,9(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry7_16:
sbbl %ecx,%ecx
movb %al,10(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry6_16:
sbbl %ecx,%ecx
movb %al,11(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry5_16:
sbbl %ecx,%ecx
movb %al,12(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry4_16:
sbbl %ecx,%ecx
movb %al,13(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
LEntry3_16:
movb %al,14(%edi)
movb (%esi),%al
LEntry2_16:
LEndSpan:
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
movl pspantemp,%ebx // restore spans pointer
movl espan_t_pnext(%ebx),%ebx // point to next span
testl %ebx,%ebx // any more spans?
movb %al,15(%edi)
jnz LSpanLoop // more spans
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#endif // USE_INTEL_ASM

View file

@ -1,294 +0,0 @@
/*
d_edge.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_local.h"
#include "r_local.h"
#include "QF/render.h"
static int miplevel;
float scale_for_mip;
extern int screenwidth;
int ubasestep, errorterm, erroradjustup, erroradjustdown;
int vstartscan;
vec3_t transformed_modelorg;
void
D_DrawPoly (void)
{
// this driver takes spans, not polygons
}
int
D_MipLevelForScale (float scale)
{
int lmiplevel;
if (scale >= d_scalemip[0])
lmiplevel = 0;
else if (scale >= d_scalemip[1])
lmiplevel = 1;
else if (scale >= d_scalemip[2])
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
return lmiplevel;
}
// FIXME: clean this up
void
D_DrawSolidSurface (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2, pix;
pix = (color << 24) | (color << 16) | (color << 8) | color;
for (span = surf->spans; span; span = span->pnext) {
pdest = (byte *) d_viewbuffer + screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
((byte *) pdest)[u] = pix;
if (u2 - u < 8) {
for (u++; u <= u2; u++)
((byte *) pdest)[u] = pix;
} else {
for (u++; u & 3; u++)
((byte *) pdest)[u] = pix;
u2 -= 4;
for (; u <= u2; u += 4)
*(int *) ((byte *) pdest + u) = pix;
u2 += 4;
for (; u <= u2; u++)
((byte *) pdest)[u] = pix;
}
}
}
void
D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
float mipscale;
vec3_t p_temp1;
vec3_t p_saxis, p_taxis;
float t;
pplane = pface->plane;
mipscale = 1.0 / (float) (1 << miplevel);
TransformVector (pface->texinfo->vecs[0], p_saxis);
TransformVector (pface->texinfo->vecs[1], p_taxis);
t = xscaleinv * mipscale;
d_sdivzstepu = p_saxis[0] * t;
d_tdivzstepu = p_taxis[0] * t;
t = yscaleinv * mipscale;
d_sdivzstepv = -p_saxis[1] * t;
d_tdivzstepv = -p_taxis[1] * t;
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
VectorScale (transformed_modelorg, mipscale, p_temp1);
t = 0x10000 * mipscale;
sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3] * t;
tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3] * t;
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
void
D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
currententity = &r_worldentity;
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
// TODO: could preset a lot of this at mode set time
if (r_drawflat->int_val) {
for (s = &surfaces[1]; s < surface_p; s++) {
if (!s->spans)
continue;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_DrawSolidSurface (s, (int) ((long) s->data & 0xFF));
D_DrawZSpans (s->spans);
}
} else {
for (s = &surfaces[1]; s < surface_p; s++) {
if (!s->spans)
continue;
r_drawnpolycount++;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
if (s->flags & SURF_DRAWSKY) {
if (!r_skymade) {
R_MakeSky ();
}
D_DrawSkyScans8 (s->spans);
D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWBACKGROUND) {
// set up a gradient for the background surface that places
// it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF);
D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWTURB) {
pface = s->data;
miplevel = 0;
cacheblock = (pixel_t *)
((byte *) pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
cachewidth = 64;
if (s->insubmodel) {
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; // FIXME: make this passed in
// to R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the
// frustum, make entity passed in
}
D_CalcGradients (pface);
Turbulent8 (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel) {
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
currententity = &r_worldentity;
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
} else {
if (s->insubmodel) {
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; // FIXME: make this passed in
// to R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the
// frustum, make entity passed in
}
pface = s->data;
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
* pface->texinfo->mipadjust);
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
cacheblock = (pixel_t *) pcurrentcache->data;
cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
(*d_drawspans) (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel) {
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
currententity = &r_worldentity;
}
}
}
}
}

View file

@ -1,87 +0,0 @@
/*
d_fill.c
clears a specified rectangle to the specified color
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_iface.h"
void
D_FillRect (vrect_t *rect, int color)
{
int rx, ry, rwidth, rheight;
unsigned char *dest;
unsigned int *ldest;
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0) {
rwidth += rx;
rx = 0;
}
if (ry < 0) {
rheight += ry;
ry = 0;
}
if (rx + rwidth > vid.width)
rwidth = vid.width - rx;
if (ry + rheight > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = ((byte *) vid.buffer + ry * vid.rowbytes + rx);
if (((rwidth & 0x03) == 0) && (((long) dest & 0x03) == 0)) {
// faster aligned dword clear
ldest = (unsigned int *) dest;
color += color << 16;
rwidth >>= 2;
color += color << 8;
for (ry = 0; ry < rheight; ry++) {
for (rx = 0; rx < rwidth; rx++)
ldest[rx] = color;
ldest = (unsigned int *) ((byte *) ldest + vid.rowbytes);
}
} else {
// slower byte-by-byte clear for unaligned cases
for (ry = 0; ry < rheight; ry++) {
for (rx = 0; rx < rwidth; rx++)
dest[rx] = color;
dest += vid.rowbytes;
}
}
}

View file

@ -1,150 +0,0 @@
/*
d_init.c
rasterization driver initialization
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/compat.h"
#include "QF/cvar.h"
#include "QF/vid.h"
#include "bothdefs.h"
#include "d_local.h"
#include "r_cvar.h"
#include "QF/render.h"
#define NUM_MIPS 4
surfcache_t *d_initial_rover;
qboolean d_roverwrapped;
int d_minmip;
float d_scalemip[NUM_MIPS - 1];
static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 };
extern int d_aflatcolor;
void (*d_drawspans) (espan_t *pspan);
void
D_Init (void)
{
r_skydirect = 1;
r_drawpolys = false;
r_worldpolysbacktofront = false;
r_recursiveaffinetriangles = true;
r_pixbytes = 1;
r_aliasuvscale = 1.0;
vid.surf_cache_size = D_SurfaceCacheForRes;
vid.flush_caches = D_FlushCaches;
vid.init_caches = D_InitCaches;
VID_InitBuffers ();
}
void
D_CopyRects (vrect_t *prects, int transparent)
{
// this function is only required if the CPU doesn't have direct access to the
// back buffer, and there's some driver interface function that the driver
// doesn't support and requires Quake to do in software (such as drawing the
// console); Quake will then draw into wherever the driver points vid.buffer
// and will call this function before swapping buffers
}
void
D_EnableBackBufferAccess (void)
{
VID_LockBuffer ();
}
void
D_TurnZOn (void)
{
// not needed for software version
}
void
D_DisableBackBufferAccess (void)
{
VID_UnlockBuffer ();
}
void
D_SetupFrame (void)
{
int i;
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *) (byte *) vid.buffer;
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
d_roverwrapped = false;
d_initial_rover = sc_rover;
d_minmip = bound (0, d_mipcap->value, 3);
for (i = 0; i < (NUM_MIPS - 1); i++)
d_scalemip[i] = basemip[i] * d_mipscale->value;
#ifdef USE_INTEL_ASM
if (d_subdiv16->int_val)
d_drawspans = D_DrawSpans16;
else
d_drawspans = D_DrawSpans8;
#else
d_drawspans = D_DrawSpans8;
#endif
d_aflatcolor = 0;
}
void
D_UpdateRects (vrect_t *prect)
{
// the software driver draws these directly to the vid buffer
}

View file

@ -1,110 +0,0 @@
/*
d_modech.c
called when mode has just changed
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/sys.h"
#include "d_local.h"
#include "QF/render.h"
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
int d_scantable[MAXHEIGHT];
short *zspantable[MAXHEIGHT];
void
D_Patch (void)
{
#ifdef USE_INTEL_ASM
static qboolean protectset8 = false;
if (!protectset8) {
Sys_MakeCodeWriteable ((int) D_PolysetAff8Start,
(int) D_PolysetAff8End -
(int) D_PolysetAff8Start);
protectset8 = true;
}
#endif // USE_INTEL_ASM
}
void
D_ViewChanged (void)
{
int rowbytes;
if (r_dowarp)
rowbytes = WARP_WIDTH;
else
rowbytes = vid.rowbytes;
scale_for_mip = xscale;
if (yscale > xscale)
scale_for_mip = yscale;
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
d_pix_min = r_refdef.vrect.width / 320;
if (d_pix_min < 1)
d_pix_min = 1;
d_pix_max = (int) ((float) r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
d_pix_shift = 8 - (int) ((float) r_refdef.vrect.width / 320.0 + 0.5);
if (d_pix_max < 1)
d_pix_max = 1;
if (pixelAspect > 1.4)
d_y_aspect_shift = 1;
else
d_y_aspect_shift = 0;
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
{
int i;
for (i = 0; i < vid.height; i++) {
d_scantable[i] = i * rowbytes;
zspantable[i] = d_pzbuffer + i * d_zwidth;
}
}
D_Patch ();
}

View file

@ -1,176 +0,0 @@
/*
d_part.c
software driver module for drawing particles
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_local.h"
void
D_EndParticles (void)
{
// not used by software driver
}
void
D_StartParticles (void)
{
// not used by software driver
}
#ifndef USE_INTEL_ASM
void
D_DrawParticle (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
byte *pdest;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->org, r_origin, local);
transformed[0] = DotProduct (local, r_pright);
transformed[1] = DotProduct (local, r_pup);
transformed[2] = DotProduct (local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int) (xcenter + zi * transformed[0] + 0.5);
v = (int) (ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) || (v < d_vrecty) || (u < d_vrectx)) {
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = (int) (zi * 0x8000);
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
switch (pix) {
case 1:
count = 1 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pparticle->color;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pparticle->color;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pparticle->color;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pparticle->color;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pparticle->color;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pparticle->color;
}
}
}
break;
}
}
#endif // !USE_INTEL_ASM

View file

@ -1,484 +0,0 @@
/*
d_parta.S
x86 assembly-language 8-bpp particle-drawing code.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "d_ifacea.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
//----------------------------------------------------------------------
// 8-bpp particle drawing code.
//----------------------------------------------------------------------
//FIXME: comments, full optimization
//----------------------------------------------------------------------
// 8-bpp particle queueing code.
//----------------------------------------------------------------------
.text
#define P 12+4
.align 4
.globl C(D_DrawParticle)
C(D_DrawParticle):
pushl %ebp // preserve caller's stack frame
pushl %edi // preserve register variables
pushl %ebx
movl P(%esp),%edi
// FIXME: better FP overlap in general here
// transform point
// VectorSubtract (p->org, r_origin, local);
flds C(r_origin)
fsubrs pt_org(%edi)
flds pt_org+4(%edi)
fsubs C(r_origin)+4
flds pt_org+8(%edi)
fsubs C(r_origin)+8
fxch %st(2) // local[0] | local[1] | local[2]
// transformed[2] = DotProduct(local, r_ppn);
flds C(r_ppn) // r_ppn[0] | local[0] | local[1] | local[2]
fmul %st(1),%st(0) // dot0 | local[0] | local[1] | local[2]
flds C(r_ppn)+4 // r_ppn[1] | dot0 | local[0] | local[1] | local[2]
fmul %st(3),%st(0) // dot1 | dot0 | local[0] | local[1] | local[2]
flds C(r_ppn)+8 // r_ppn[2] | dot1 | dot0 | local[0] |
// local[1] | local[2]
fmul %st(5),%st(0) // dot2 | dot1 | dot0 | local[0] | local[1] | local[2]
fxch %st(2) // dot0 | dot1 | dot2 | local[0] | local[1] | local[2]
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[0] | local[1] |
// local[2]
faddp %st(0),%st(1) // z | local[0] | local[1] | local[2]
fld %st(0) // z | z | local[0] | local[1] |
// local[2]
fdivrs float_1 // 1/z | z | local[0] | local[1] | local[2]
fxch %st(1) // z | 1/z | local[0] | local[1] | local[2]
// if (transformed[2] < PARTICLE_Z_CLIP)
// return;
fcomps float_particle_z_clip // 1/z | local[0] | local[1] | local[2]
fxch %st(3) // local[2] | local[0] | local[1] | 1/z
flds C(r_pup) // r_pup[0] | local[2] | local[0] | local[1] | 1/z
fmul %st(2),%st(0) // dot0 | local[2] | local[0] | local[1] | 1/z
flds C(r_pup)+4 // r_pup[1] | dot0 | local[2] | local[0] |
// local[1] | 1/z
fnstsw %ax
testb $1,%ah
jnz LPop6AndDone
// transformed[1] = DotProduct(local, r_pup);
fmul %st(4),%st(0) // dot1 | dot0 | local[2] | local[0] | local[1] | 1/z
flds C(r_pup)+8 // r_pup[2] | dot1 | dot0 | local[2] |
// local[0] | local[1] | 1/z
fmul %st(3),%st(0) // dot2 | dot1 | dot0 | local[2] | local[0] |
// local[1] | 1/z
fxch %st(2) // dot0 | dot1 | dot2 | local[2] | local[0] |
// local[1] | 1/z
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[2] | local[0] |
// local[1] | 1/z
faddp %st(0),%st(1) // y | local[2] | local[0] | local[1] | 1/z
fxch %st(3) // local[1] | local[2] | local[0] | y | 1/z
// transformed[0] = DotProduct(local, r_pright);
fmuls C(r_pright)+4 // dot1 | local[2] | local[0] | y | 1/z
fxch %st(2) // local[0] | local[2] | dot1 | y | 1/z
fmuls C(r_pright) // dot0 | local[2] | dot1 | y | 1/z
fxch %st(1) // local[2] | dot0 | dot1 | y | 1/z
fmuls C(r_pright)+8 // dot2 | dot0 | dot1 | y | 1/z
fxch %st(2) // dot1 | dot0 | dot2 | y | 1/z
faddp %st(0),%st(1) // dot1 + dot0 | dot2 | y | 1/z
faddp %st(0),%st(1) // x | y | 1/z
fxch %st(1) // y | x | 1/z
// project the point
fmul %st(2),%st(0) // y/z | x | 1/z
fxch %st(1) // x | y/z | 1/z
fmul %st(2),%st(0) // x/z | y/z | 1/z
fxch %st(1) // y/z | x/z | 1/z
fsubrs C(ycenter) // v | x/z | 1/z
fxch %st(1) // x/z | v | 1/z
fadds C(xcenter) // u | v | 1/z
// FIXME: preadjust xcenter and ycenter
fxch %st(1) // v | u | 1/z
fadds float_point5 // v | u | 1/z
fxch %st(1) // u | v | 1/z
fadds float_point5 // u | v | 1/z
fxch %st(2) // 1/z | v | u
fmuls DP_32768 // 1/z * 0x8000 | v | u
fxch %st(2) // u | v | 1/z * 0x8000
// FIXME: use Terje's fp->int trick here?
// FIXME: check we're getting proper rounding here
fistpl DP_u // v | 1/z * 0x8000
fistpl DP_v // 1/z * 0x8000
movl DP_u,%eax
movl DP_v,%edx
// if ((v > d_vrectbottom_particle) ||
// (u > d_vrectright_particle) ||
// (v < d_vrecty) ||
// (u < d_vrectx))
// {
// continue;
// }
movl C(d_vrectbottom_particle),%ebx
movl C(d_vrectright_particle),%ecx
cmpl %ebx,%edx
jg LPop1AndDone
cmpl %ecx,%eax
jg LPop1AndDone
movl C(d_vrecty),%ebx
movl C(d_vrectx),%ecx
cmpl %ebx,%edx
jl LPop1AndDone
cmpl %ecx,%eax
jl LPop1AndDone
flds pt_color(%edi) // color | 1/z * 0x8000
// FIXME: use Terje's fast fp->int trick?
fistpl DP_Color // 1/z * 0x8000
movl C(d_viewbuffer),%ebx
addl %eax,%ebx
movl C(d_scantable)(,%edx,4),%edi // point to the pixel
imull C(d_zrowbytes),%edx // point to the z pixel
leal (%edx,%eax,2),%edx
movl C(d_pzbuffer),%eax
fistpl izi
addl %ebx,%edi
addl %eax,%edx
// pix = izi >> d_pix_shift;
movl izi,%eax
movl C(d_pix_shift),%ecx
shrl %cl,%eax
movl izi,%ebp
// if (pix < d_pix_min)
// pix = d_pix_min;
// else if (pix > d_pix_max)
// pix = d_pix_max;
movl C(d_pix_min),%ebx
movl C(d_pix_max),%ecx
cmpl %ebx,%eax
jnl LTestPixMax
movl %ebx,%eax
jmp LTestDone
LTestPixMax:
cmpl %ecx,%eax
jng LTestDone
movl %ecx,%eax
LTestDone:
movb DP_Color,%ch
movl C(d_y_aspect_shift),%ebx
testl %ebx,%ebx
jnz LDefault
cmpl $4,%eax
ja LDefault
jmp *DP_EntryTable-4(,%eax,4)
// 1x1
.globl DP_1x1
DP_1x1:
cmpw %bp,(%edx) // just one pixel to do
jg LDone
movw %bp,(%edx)
movb %ch,(%edi)
jmp LDone
// 2x2
.globl DP_2x2
DP_2x2:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
cmpw %bp,(%edx)
jg L2x2_1
movw %bp,(%edx)
movb %ch,(%edi)
L2x2_1:
cmpw %bp,2(%edx)
jg L2x2_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L2x2_2:
cmpw %bp,(%edx,%esi,1)
jg L2x2_3
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L2x2_3:
cmpw %bp,2(%edx,%esi,1)
jg L2x2_4
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L2x2_4:
popl %esi
jmp LDone
// 3x3
.globl DP_3x3
DP_3x3:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
cmpw %bp,(%edx)
jg L3x3_1
movw %bp,(%edx)
movb %ch,(%edi)
L3x3_1:
cmpw %bp,2(%edx)
jg L3x3_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L3x3_2:
cmpw %bp,4(%edx)
jg L3x3_3
movw %bp,4(%edx)
movb %ch,2(%edi)
L3x3_3:
cmpw %bp,(%edx,%esi,1)
jg L3x3_4
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L3x3_4:
cmpw %bp,2(%edx,%esi,1)
jg L3x3_5
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L3x3_5:
cmpw %bp,4(%edx,%esi,1)
jg L3x3_6
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L3x3_6:
cmpw %bp,(%edx,%esi,2)
jg L3x3_7
movw %bp,(%edx,%esi,2)
movb %ch,(%edi,%ebx,2)
L3x3_7:
cmpw %bp,2(%edx,%esi,2)
jg L3x3_8
movw %bp,2(%edx,%esi,2)
movb %ch,1(%edi,%ebx,2)
L3x3_8:
cmpw %bp,4(%edx,%esi,2)
jg L3x3_9
movw %bp,4(%edx,%esi,2)
movb %ch,2(%edi,%ebx,2)
L3x3_9:
popl %esi
jmp LDone
// 4x4
.globl DP_4x4
DP_4x4:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
cmpw %bp,(%edx)
jg L4x4_1
movw %bp,(%edx)
movb %ch,(%edi)
L4x4_1:
cmpw %bp,2(%edx)
jg L4x4_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L4x4_2:
cmpw %bp,4(%edx)
jg L4x4_3
movw %bp,4(%edx)
movb %ch,2(%edi)
L4x4_3:
cmpw %bp,6(%edx)
jg L4x4_4
movw %bp,6(%edx)
movb %ch,3(%edi)
L4x4_4:
cmpw %bp,(%edx,%esi,1)
jg L4x4_5
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L4x4_5:
cmpw %bp,2(%edx,%esi,1)
jg L4x4_6
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L4x4_6:
cmpw %bp,4(%edx,%esi,1)
jg L4x4_7
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L4x4_7:
cmpw %bp,6(%edx,%esi,1)
jg L4x4_8
movw %bp,6(%edx,%esi,1)
movb %ch,3(%edi,%ebx,1)
L4x4_8:
leal (%edx,%esi,2),%edx
leal (%edi,%ebx,2),%edi
cmpw %bp,(%edx)
jg L4x4_9
movw %bp,(%edx)
movb %ch,(%edi)
L4x4_9:
cmpw %bp,2(%edx)
jg L4x4_10
movw %bp,2(%edx)
movb %ch,1(%edi)
L4x4_10:
cmpw %bp,4(%edx)
jg L4x4_11
movw %bp,4(%edx)
movb %ch,2(%edi)
L4x4_11:
cmpw %bp,6(%edx)
jg L4x4_12
movw %bp,6(%edx)
movb %ch,3(%edi)
L4x4_12:
cmpw %bp,(%edx,%esi,1)
jg L4x4_13
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L4x4_13:
cmpw %bp,2(%edx,%esi,1)
jg L4x4_14
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L4x4_14:
cmpw %bp,4(%edx,%esi,1)
jg L4x4_15
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L4x4_15:
cmpw %bp,6(%edx,%esi,1)
jg L4x4_16
movw %bp,6(%edx,%esi,1)
movb %ch,3(%edi,%ebx,1)
L4x4_16:
popl %esi
jmp LDone
// default case, handling any size particle
LDefault:
// count = pix << d_y_aspect_shift;
movl %eax,%ebx
movl %eax,DP_Pix
movb C(d_y_aspect_shift),%cl
shll %cl,%ebx
// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
// {
// for (i=0 ; i<pix ; i++)
// {
// if (pz[i] <= izi)
// {
// pz[i] = izi;
// pdest[i] = color;
// }
// }
// }
LGenRowLoop:
movl DP_Pix,%eax
LGenColLoop:
cmpw %bp,-2(%edx,%eax,2)
jg LGSkip
movw %bp,-2(%edx,%eax,2)
movb %ch,-1(%edi,%eax,1)
LGSkip:
decl %eax // --pix
jnz LGenColLoop
addl C(d_zrowbytes),%edx
addl C(screenwidth),%edi
decl %ebx // --count
jnz LGenRowLoop
LDone:
popl %ebx // restore register variables
popl %edi
popl %ebp // restore the caller's stack frame
ret
LPop6AndDone:
fstp %st(0)
fstp %st(0)
fstp %st(0)
fstp %st(0)
fstp %st(0)
LPop1AndDone:
fstp %st(0)
jmp LDone
#endif // USE_INTEL_ASM

File diff suppressed because it is too large Load diff

View file

@ -1,965 +0,0 @@
/*
d_polyse.c
routines for drawing sets of polygons sharing the same texture
(used for Alias models)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "r_local.h"
#include "d_local.h"
// TODO: put in span spilling to shrink list size
// !!! if this is changed, it must be changed in d_polysa.s too !!!
#define DPS_MAXSPANS MAXHEIGHT+1
// 1 extra for spanpackage that marks end
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct {
void *pdest;
short *pz;
int count;
byte *ptex;
int sfrac, tfrac, light, zi;
} spanpackage_t;
typedef struct {
int isflattop;
int numleftedges;
int *pleftedgevert0;
int *pleftedgevert1;
int *pleftedgevert2;
int numrightedges;
int *prightedgevert0;
int *prightedgevert1;
int *prightedgevert2;
} edgetable;
int r_p0[6], r_p1[6], r_p2[6];
byte *d_pcolormap;
int d_aflatcolor;
int d_xdenom;
edgetable *pedgetable;
edgetable edgetables[12] = {
{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2},
{0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0},
{0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1},
{0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
};
// FIXME: some of these can become statics
int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
int r_zistepx, r_zistepy;
int d_aspancount, d_countextrastep;
spanpackage_t *a_spans;
spanpackage_t *d_pedgespanpackage;
static int ystart;
byte *d_pdest, *d_ptex;
short *d_pz;
int d_sfrac, d_tfrac, d_light, d_zi;
int d_ptexextrastep, d_sfracextrastep;
int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
int d_sfracbasestep, d_tfracbasestep;
int d_ziextrastep, d_zibasestep;
int d_pzextrastep, d_pzbasestep;
typedef struct {
int quotient;
int remainder;
} adivtab_t;
static adivtab_t adivtab[32 * 32] = {
#include "adivtab.h"
};
byte *skintable[MAX_LBM_HEIGHT];
int skinwidth;
byte *skinstart;
void D_PolysetDrawSpans8 (spanpackage_t * pspanpackage);
void D_PolysetCalcGradients (int skinwidth);
void D_DrawSubdiv (void);
void D_DrawNonSubdiv (void);
void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
void D_PolysetSetEdgeTable (void);
void D_RasterizeAliasPolySmooth (void);
void D_PolysetScanLeftEdge (int height);
#ifndef USE_INTEL_ASM
void
D_PolysetDraw (void)
{
spanpackage_t spans[DPS_MAXSPANS + 1 +
((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1];
// one extra because of cache line pretouching
a_spans = (spanpackage_t *)
(((long) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
if (r_affinetridesc.drawtype) {
D_DrawSubdiv ();
} else {
D_DrawNonSubdiv ();
}
}
void
D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
{
int i, z;
short *zbuf;
for (i = 0; i < numverts; i++, fv++) {
// valid triangle coordinates for filling can include the bottom and
// right clip edges, due to the fill rule; these shouldn't be drawn
if ((fv->v[0] < r_refdef.vrectright) &&
(fv->v[1] < r_refdef.vrectbottom)) {
z = fv->v[5] >> 16;
zbuf = zspantable[fv->v[1]] + fv->v[0];
if (z >= *zbuf) {
int pix;
*zbuf = z;
pix = skintable[fv->v[3] >> 16][fv->v[2] >> 16];
pix = ((byte *) acolormap)[pix + (fv->v[4] & 0xFF00)];
d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
}
}
}
}
void
D_DrawSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
for (i = 0; i < lnumtriangles; i++) {
index0 = pfv + ptri[i].vertindex[0];
index1 = pfv + ptri[i].vertindex[1];
index2 = pfv + ptri[i].vertindex[2];
if (((index0->v[1] - index1->v[1]) *
(index0->v[0] - index2->v[0]) -
(index0->v[0] - index1->v[0]) *
(index0->v[1] - index2->v[1])) >= 0) {
continue;
}
d_pcolormap = &((byte *) acolormap)[index0->v[4] & 0xFF00];
if (ptri[i].facesfront) {
D_PolysetRecursiveTriangle (index0->v, index1->v, index2->v);
} else {
int s0, s1, s2;
s0 = index0->v[2];
s1 = index1->v[2];
s2 = index2->v[2];
if (index0->flags & ALIAS_ONSEAM)
index0->v[2] += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
index1->v[2] += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
index2->v[2] += r_affinetridesc.seamfixupX16;
D_PolysetRecursiveTriangle (index0->v, index1->v, index2->v);
index0->v[2] = s0;
index1->v[2] = s1;
index2->v[2] = s2;
}
}
}
void
D_DrawNonSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
for (i = 0; i < lnumtriangles; i++, ptri++) {
index0 = pfv + ptri->vertindex[0];
index1 = pfv + ptri->vertindex[1];
index2 = pfv + ptri->vertindex[2];
d_xdenom = (index0->v[1] - index1->v[1]) *
(index0->v[0] - index2->v[0]) -
(index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]);
if (d_xdenom >= 0) {
continue;
}
r_p0[0] = index0->v[0]; // u
r_p0[1] = index0->v[1]; // v
r_p0[2] = index0->v[2]; // s
r_p0[3] = index0->v[3]; // t
r_p0[4] = index0->v[4]; // light
r_p0[5] = index0->v[5]; // iz
r_p1[0] = index1->v[0];
r_p1[1] = index1->v[1];
r_p1[2] = index1->v[2];
r_p1[3] = index1->v[3];
r_p1[4] = index1->v[4];
r_p1[5] = index1->v[5];
r_p2[0] = index2->v[0];
r_p2[1] = index2->v[1];
r_p2[2] = index2->v[2];
r_p2[3] = index2->v[3];
r_p2[4] = index2->v[4];
r_p2[5] = index2->v[5];
if (!ptri->facesfront) {
if (index0->flags & ALIAS_ONSEAM)
r_p0[2] += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
r_p1[2] += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
r_p2[2] += r_affinetridesc.seamfixupX16;
}
D_PolysetSetEdgeTable ();
D_RasterizeAliasPolySmooth ();
}
}
void
D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
{
int *temp;
int d;
int new[6];
int z;
short *zbuf;
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
d = lp3[0] - lp2[0];
if (d < -1 || d > 1)
goto split2;
d = lp3[1] - lp2[1];
if (d < -1 || d > 1)
goto split2;
d = lp1[0] - lp3[0];
if (d < -1 || d > 1)
goto split3;
d = lp1[1] - lp3[1];
if (d < -1 || d > 1) {
split3:
temp = lp1;
lp1 = lp3;
lp3 = lp2;
lp2 = temp;
goto split;
}
return; // entire tri is filled
split2:
temp = lp1;
lp1 = lp2;
lp2 = lp3;
lp3 = temp;
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
// draw the point if splitting a leading edge
if (lp2[1] > lp1[1])
goto nodraw;
if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
goto nodraw;
z = new[5] >> 16;
zbuf = zspantable[new[1]] + new[0];
if (z >= *zbuf) {
int pix;
*zbuf = z;
pix = d_pcolormap[skintable[new[3] >> 16][new[2] >> 16]];
d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
}
nodraw:
// recursively continue
D_PolysetRecursiveTriangle (lp3, lp1, new);
D_PolysetRecursiveTriangle (lp3, new, lp2);
}
#endif // !USE_INTEL_ASM
void
D_PolysetUpdateTables (void)
{
int i;
byte *s;
if (r_affinetridesc.skinwidth != skinwidth ||
r_affinetridesc.pskin != skinstart) {
skinwidth = r_affinetridesc.skinwidth;
skinstart = r_affinetridesc.pskin;
s = skinstart;
for (i = 0; i < MAX_LBM_HEIGHT; i++, s += skinwidth)
skintable[i] = s;
}
}
#ifndef USE_INTEL_ASM
void
D_PolysetScanLeftEdge (int height)
{
do {
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light = d_light;
d_pedgespanpackage->zi = d_zi;
d_pedgespanpackage++;
errorterm += erroradjustup;
if (errorterm >= 0) {
d_pdest += d_pdestextrastep;
d_pz += d_pzextrastep;
d_aspancount += d_countextrastep;
d_ptex += d_ptexextrastep;
d_sfrac += d_sfracextrastep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracextrastep;
if (d_tfrac & 0x10000) {
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightextrastep;
d_zi += d_ziextrastep;
errorterm -= erroradjustdown;
} else {
d_pdest += d_pdestbasestep;
d_pz += d_pzbasestep;
d_aspancount += ubasestep;
d_ptex += d_ptexbasestep;
d_sfrac += d_sfracbasestep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracbasestep;
if (d_tfrac & 0x10000) {
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightbasestep;
d_zi += d_zibasestep;
}
} while (--height);
}
#endif // !USE_INTEL_ASM
void
D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv)
{
double dm, dn;
int tm, tn;
adivtab_t *ptemp;
// TODO: implement x86 version
errorterm = -1;
tm = endvertu - startvertu;
tn = endvertv - startvertv;
if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) {
ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)];
ubasestep = ptemp->quotient;
erroradjustup = ptemp->remainder;
erroradjustdown = tn;
} else {
dm = (double) tm;
dn = (double) tn;
FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
erroradjustdown = dn;
}
}
#ifndef USE_INTEL_ASM
void
D_PolysetCalcGradients (int skinwidth)
{
float xstepdenominv, ystepdenominv, t0, t1;
float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
p00_minus_p20 = r_p0[0] - r_p2[0];
p01_minus_p21 = r_p0[1] - r_p2[1];
p10_minus_p20 = r_p1[0] - r_p2[0];
p11_minus_p21 = r_p1[1] - r_p2[1];
xstepdenominv = 1.0 / (float) d_xdenom;
ystepdenominv = -xstepdenominv;
// ceil () for light so positive steps are exaggerated, negative steps
// diminished, pushing us away from underflow toward overflow. Underflow is
// very visible, overflow is very unlikely, because of ambient lighting
t0 = r_p0[4] - r_p2[4];
t1 = r_p1[4] - r_p2[4];
r_lstepx = (int)
ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
r_lstepy = (int)
ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
t0 = r_p0[2] - r_p2[2];
t1 = r_p1[2] - r_p2[2];
r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
t0 = r_p0[3] - r_p2[3];
t1 = r_p1[3] - r_p2[3];
r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
t0 = r_p0[5] - r_p2[5];
t1 = r_p1[5] - r_p2[5];
r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
#ifdef USE_INTEL_ASM
a_sstepxfrac = r_sstepx << 16;
a_tstepxfrac = r_tstepx << 16;
#else
a_sstepxfrac = r_sstepx & 0xFFFF;
a_tstepxfrac = r_tstepx & 0xFFFF;
#endif
a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
}
#endif // !USE_INTEL_ASM
byte gelmap[256];
void
InitGel (byte * palette)
{
int i;
int r;
for (i = 0; i < 256; i++) {
// r = (palette[i*3]>>4);
r =
(palette[i * 3] + palette[i * 3 + 1] +
palette[i * 3 + 2]) / (16 * 3);
gelmap[i] = /* 64 */ 0 + r;
}
}
#ifndef USE_INTEL_ASM
void
D_PolysetDrawSpans8 (spanpackage_t * pspanpackage)
{
int lcount;
byte *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do {
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0) {
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
} else {
d_aspancount += ubasestep;
}
if (lcount) {
lpdest = pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do {
if ((lzi >> 16) >= *lpz) {
*lpdest = ((byte *) acolormap)[*lptex + (llight & 0xFF00)];
// gel mapping *lpdest = gelmap[*lpdest];
*lpz = lzi >> 16;
}
lpdest++;
lzi += r_zistepx;
lpz++;
llight += r_lstepx;
lptex += a_ststepxwhole;
lsfrac += a_sstepxfrac;
lptex += lsfrac >> 16;
lsfrac &= 0xFFFF;
ltfrac += a_tstepxfrac;
if (ltfrac & 0x10000) {
lptex += r_affinetridesc.skinwidth;
ltfrac &= 0xFFFF;
}
} while (--lcount);
}
pspanpackage++;
} while (pspanpackage->count != -999999);
}
#endif // !USE_INTEL_ASM
void
D_PolysetFillSpans8 (spanpackage_t * pspanpackage)
{
int color;
// FIXME: do z buffering
color = d_aflatcolor++;
while (1) {
int lcount;
byte *lpdest;
lcount = pspanpackage->count;
if (lcount == -1)
return;
if (lcount) {
lpdest = pspanpackage->pdest;
do {
*lpdest++ = color;
} while (--lcount);
}
pspanpackage++;
}
}
void
D_RasterizeAliasPolySmooth (void)
{
int initialleftheight, initialrightheight;
int *plefttop, *prighttop, *pleftbottom, *prightbottom;
int working_lstepx, originalcount;
plefttop = pedgetable->pleftedgevert0;
prighttop = pedgetable->prightedgevert0;
pleftbottom = pedgetable->pleftedgevert1;
prightbottom = pedgetable->prightedgevert1;
initialleftheight = pleftbottom[1] - plefttop[1];
initialrightheight = prightbottom[1] - prighttop[1];
// set the s, t, and light gradients, which are consistent across the
// triangle, because being a triangle, things are affine
D_PolysetCalcGradients (r_affinetridesc.skinwidth);
// rasterize the polygon
// scan out the top (and possibly only) part of the left edge
D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
d_pedgespanpackage = a_spans;
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
#ifdef USE_INTEL_ASM
d_sfrac = (plefttop[2] & 0xFFFF) << 16;
d_tfrac = (plefttop[3] & 0xFFFF) << 16;
d_pzbasestep = (d_zwidth + ubasestep) << 1;
d_pzextrastep = d_pzbasestep + 2;
#else
d_sfrac = plefttop[2] & 0xFFFF;
d_tfrac = plefttop[3] & 0xFFFF;
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
#endif
d_light = plefttop[4];
d_zi = plefttop[5];
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0];
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
// TODO: can reuse partial expressions here
// for negative steps in x along left edge, bias toward overflow rather
// than underflow (sort of turning the floor () we did in the gradient
// calcs into ceil (), but plus a little bit)
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) * r_affinetridesc.skinwidth;
#ifdef USE_INTEL_ASM
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
#else
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
#endif
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
#ifdef USE_INTEL_ASM
d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) << 16;
d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) << 16;
#else
d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
#endif
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
D_PolysetScanLeftEdge (initialleftheight);
// scan out the bottom part of the left edge, if it exists
if (pedgetable->numleftedges == 2) {
int height;
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
height = pleftbottom[1] - plefttop[1];
// TODO: make this a function; modularize this function in general
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
d_sfrac = 0;
d_tfrac = 0;
d_light = plefttop[4];
d_zi = plefttop[5];
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0];
#ifdef USE_INTEL_ASM
d_pzbasestep = (d_zwidth + ubasestep) << 1;
d_pzextrastep = d_pzbasestep + 2;
#else
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
#endif
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
r_affinetridesc.skinwidth;
#ifdef USE_INTEL_ASM
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
#else
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
#endif
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
#ifdef USE_INTEL_ASM
d_sfracextrastep =
((r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF) << 16;
d_tfracextrastep =
((r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF) << 16;
#else
d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
#endif
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
D_PolysetScanLeftEdge (height);
}
// scan out the top (and possibly only) part of the right edge, updating
// the count field
d_pedgespanpackage = a_spans;
D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
d_aspancount = 0;
d_countextrastep = ubasestep + 1;
originalcount = a_spans[initialrightheight].count;
a_spans[initialrightheight].count = -999999; // mark end of the
// spanpackages
D_PolysetDrawSpans8 (a_spans);
// scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2) {
int height;
spanpackage_t *pstart;
pstart = a_spans + initialrightheight;
pstart->count = originalcount;
d_aspancount = prightbottom[0] - prighttop[0];
prighttop = prightbottom;
prightbottom = pedgetable->prightedgevert2;
height = prightbottom[1] - prighttop[1];
D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
d_countextrastep = ubasestep + 1;
a_spans[initialrightheight + height].count = -999999;
// mark end of the spanpackages
D_PolysetDrawSpans8 (pstart);
}
}
void
D_PolysetSetEdgeTable (void)
{
int edgetableindex;
edgetableindex = 0; // assume the vertices are already in
// top to bottom order
// determine which edges are right & left, and the order in which
// to rasterize them
if (r_p0[1] >= r_p1[1]) {
if (r_p0[1] == r_p1[1]) {
if (r_p0[1] < r_p2[1])
pedgetable = &edgetables[2];
else
pedgetable = &edgetables[5];
return;
} else {
edgetableindex = 1;
}
}
if (r_p0[1] == r_p2[1]) {
if (edgetableindex)
pedgetable = &edgetables[8];
else
pedgetable = &edgetables[9];
return;
} else if (r_p1[1] == r_p2[1]) {
if (edgetableindex)
pedgetable = &edgetables[10];
else
pedgetable = &edgetables[11];
return;
}
if (r_p0[1] > r_p2[1])
edgetableindex += 2;
if (r_p1[1] > r_p2[1])
edgetableindex += 4;
pedgetable = &edgetables[edgetableindex];
}
#if 0
void
D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
{
int d;
int new[6];
int ofs;
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
return; // line is completed
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[4] = (lp1[4] + lp2[4]) >> 1;
// draw the point
ofs = d_scantable[new[1]] + new[0];
if (new[5] > d_pzbuffer[ofs]) {
int pix;
d_pzbuffer[ofs] = new[5];
pix = skintable[new[3] >> 16][new[2] >> 16];
// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
d_viewbuffer[ofs] = pix;
}
// recursively continue
D_PolysetRecursiveDrawLine (lp1, new);
D_PolysetRecursiveDrawLine (new, lp2);
}
void
D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
{
int d;
int new[4];
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
return;
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[4] = (lp1[4] + lp2[4]) >> 1;
D_PolysetRecursiveDrawLine (new, lp3);
// recursively continue
D_PolysetRecursiveTriangle (lp1, new, lp3);
D_PolysetRecursiveTriangle (new, lp2, lp3);
}
#endif

View file

@ -1,96 +0,0 @@
/*
d_scana.S
x86 assembly-language turbulent texture mapping code
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
#ifdef USE_INTEL_ASM
.data
.text
//----------------------------------------------------------------------
// turbulent texture mapping code
//----------------------------------------------------------------------
.align 4
.globl C(D_DrawTurbulent8Span)
C(D_DrawTurbulent8Span):
pushl %ebp // preserve caller's stack frame pointer
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
movl C(r_turb_s),%esi
movl C(r_turb_t),%ecx
movl C(r_turb_pdest),%edi
movl C(r_turb_spancount),%ebx
Llp:
movl %ecx,%eax
movl %esi,%edx
sarl $16,%eax
movl C(r_turb_turb),%ebp
sarl $16,%edx
andl $(CYCLE-1),%eax
andl $(CYCLE-1),%edx
movl (%ebp,%eax,4),%eax
movl (%ebp,%edx,4),%edx
addl %esi,%eax
sarl $16,%eax
addl %ecx,%edx
sarl $16,%edx
andl $(TURB_TEX_SIZE-1),%eax
andl $(TURB_TEX_SIZE-1),%edx
shll $6,%edx
movl C(r_turb_pbase),%ebp
addl %eax,%edx
incl %edi
addl C(r_turb_sstep),%esi
addl C(r_turb_tstep),%ecx
movb (%ebp,%edx,1),%dl
decl %ebx
movb %dl,-1(%edi)
jnz Llp
movl %edi,C(r_turb_pdest)
popl %ebx // restore register variables
popl %edi
popl %esi
popl %ebp // restore caller's stack frame pointer
ret
#endif // USE_INTEL_ASM

View file

@ -1,134 +0,0 @@
/*
d_sky.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_local.h"
#include "r_local.h"
#include "QF/render.h"
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
void
D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
float wu, wv, temp;
vec3_t end;
if (r_refdef.vrect.width >= r_refdef.vrect.height)
temp = (float) r_refdef.vrect.width;
else
temp = (float) r_refdef.vrect.height;
wu = 8192.0 * (float) (u - ((int) vid.width >> 1)) / temp;
wv = 8192.0 * (float) (((int) vid.height >> 1) - v) / temp;
end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0];
end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1];
end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2];
end[2] *= 3;
VectorNormalize (end);
temp = skytime * skyspeed; // TODO: add D_SetupFrame & set this
// there
*s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000);
*t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000);
}
void
D_DrawSkyScans8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
do {
pdest = (unsigned char *) ((byte *) d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}

View file

@ -1,907 +0,0 @@
/*
d_spr8.S
x86 assembly-language horizontal 8-bpp transparent span-drawing code.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#ifdef USE_INTEL_ASM
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with transparency.
//----------------------------------------------------------------------
.text
// out-of-line, rarely-needed clamping code
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
LClampLow2:
movl $2048,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
LClampLow3:
movl $2048,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
LClampLow4:
movl $2048,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
LClampLow5:
movl $2048,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
#define pspans 4+16
.align 4
.globl C(D_SpriteDrawSpans)
C(D_SpriteDrawSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
//
// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
// and span list pointers, and 1/z step in 0.32 fixed-point
//
// FIXME: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_8
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_8
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_8
movl %edx,pbase // pbase = cacheblock
flds C(d_zistepu)
fmuls fp_64kx64k
fxch %st(3)
fstps sdivz8stepu
fstps zi8stepu
fstps tdivz8stepu
fistpl izistep
movl izistep,%eax
rorl $16,%eax // put upper 16 bits in low word
movl sspan_t_count(%ebx),%ecx
movl %eax,izistep
cmpl $0,%ecx
jle LNextSpan
LSpanLoop:
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl sspan_t_v(%ebx)
fildl sspan_t_u(%ebx)
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
fld %st(0) // FIXME: get rid of stall on FMUL?
fmuls fp_64kx64k
fxch %st(1)
//
// calculate and clamp s & t
//
fdivr %st(0),%st(2) // 1/z | z*64k | t/z | s/z
fxch %st(1)
fistpl izi // 0.32 fixed-point 1/z
movl izi,%ebp
//
// set pz to point to the first z-buffer pixel in the span
//
rorl $16,%ebp // put upper 16 bits in low word
movl sspan_t_v(%ebx),%eax
movl %ebp,izi
movl sspan_t_u(%ebx),%ebp
imull C(d_zrowbytes)
shll $1,%ebp // a word per pixel
addl C(d_pzbuffer),%eax
addl %ebp,%eax
movl %eax,pz
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ebp
movl sspan_t_v(%ebx),%eax
pushl %ebx // preserve spans pointer
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ebp,%edi
movl sspan_t_u(%ebx),%ebp
addl %ebp,%edi // pdest = &pdestspan[scans->u];
//
// now start the FDIV for the end of the span
//
cmpl $8,%ecx
ja LSetupNotLast1
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fildl spancountminus1
flds C(d_tdivzstepu) // _d_tdivzstepu | spancountminus1
flds C(d_zistepu) // _d_zistepu | _d_tdivzstepu | spancountminus1
fmul %st(2),%st(0) // _d_zistepu*scm1 | _d_tdivzstepu | scm1
fxch %st(1) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(2) // scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
// _d_tdivzstepu*scm1
fxch %st(1) // _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
// _d_tdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
faddp %st(0),%st(3)
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
//
// calculate the texture starting address
//
sarl $16,%eax
addl %ebx,%esi
imull C(cachewidth),%eax // (tfrac >> 16) * cachewidth
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
//
// determine whether last span or not
//
cmpl $8,%ecx
jna LLastSegment
//
// not the last segment; do full 8-wide segment
//
LNotLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
subl $8,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
pushl %ecx // remember count of remaining pixels
movl C(tadjust),%ecx
addl %eax,%ebp
addl %edx,%ecx
movl C(bbextents),%eax
movl C(bbextentt),%edx
cmpl $2048,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
cmpl $2048,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
movl %ebp,snext
movl %ecx,tnext
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $19,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $19,%eax // tstep >>= 16;
jz LIsZero
imull %ebx,%eax // (tstep >> 16) * cachewidth;
LIsZero:
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $13,%ebp // left-justify sstep fractional part
movl %ebp,sstep
movl sfracf,%ebx
shll $13,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
movl %ecx,tstep
movl pz,%ecx
movl izi,%ebp
cmpw (%ecx),%bp
jl Lp1
movb (%esi),%al // get first source texel
cmpb $(TRANSPARENT_COLOR),%al
jz Lp1
movw %bp,(%ecx)
movb %al,(%edi) // store first dest pixel
Lp1:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx // advance tfrac fractional part by tstep frac
sbbl %eax,%eax // turn tstep carry into -1 (0 if none)
addl sstep,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%eax,4),%esi // point to next source texel
cmpw 2(%ecx),%bp
jl Lp2
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp2
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp2:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 4(%ecx),%bp
jl Lp3
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp3
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp3:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 6(%ecx),%bp
jl Lp4
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp4
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp4:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 8(%ecx),%bp
jl Lp5
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp5
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp5:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
//
// start FDIV for end of next segment in flight, so it can overlap
//
popl %eax
cmpl $8,%eax // more than one segment after this?
ja LSetupNotLast2 // yes
decl %eax
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %eax,spancountminus1
fildl spancountminus1
flds C(d_zistepu) // _d_zistepu | spancountminus1
fmul %st(1),%st(0) // _d_zistepu*scm1 | scm1
flds C(d_tdivzstepu) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(1) // _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
faddp %st(0),%st(3) // _d_tdivzstepu*scm1 | scm1
fxch %st(1) // scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
flds fp_64k // 64k | _d_sdivzstepu*scm1
fxch %st(1) // _d_sdivzstepu*scm1 | 64k
faddp %st(0),%st(4) // 64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
.align 4
LSetupNotLast2:
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
pushl %eax
cmpw 10(%ecx),%bp
jl Lp6
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp6
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp6:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 12(%ecx),%bp
jl Lp7
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp7
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp7:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 14(%ecx),%bp
jl Lp8
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp8
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp8:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
addl $8,%edi
addl $16,%ecx
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
movl %ecx,pz
movl %ebp,izi
popl %ecx // retrieve count
//
// determine whether last span or not
//
cmpl $8,%ecx // are there multiple segments remaining?
ja LNotLastSegment // yes
//
// last segment of scan
//
LLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl C(tadjust),%ebx
movl C(sadjust),%eax
addl snext,%eax
addl tnext,%ebx
movl C(bbextents),%ebp
movl C(bbextentt),%edx
cmpl $2048,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
cmpl $2048,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
imull reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
movl %edx,%ebp
movl %ebx,%eax
imull reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
LSetEntryvec:
//
// set up advancetable
//
movl spr8entryvec_table(,%ecx,4),%ebx
movl %edx,%eax
pushl %ebx // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%ecx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%edx // tstep >>= 16;
jz LIsZeroLast
imull %ebx,%edx // (tstep >> 16) * cachewidth;
LIsZeroLast:
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
movl %eax,tstep
movl %ebp,sstep
movl %ecx,%edx
movl pz,%ecx
movl izi,%ebp
ret // jump to the number-of-pixels handler
//----------------------------------------
LNoSteps:
movl pz,%ecx
subl $7,%edi // adjust for hardwired offset
subl $14,%ecx
jmp LEndSpan
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
//----------------------------------------
.globl Spr8Entry2_8
Spr8Entry2_8:
subl $6,%edi // adjust for hardwired offsets
subl $12,%ecx
movb (%esi),%al
jmp LLEntry2_8
//----------------------------------------
.globl Spr8Entry3_8
Spr8Entry3_8:
subl $5,%edi // adjust for hardwired offsets
subl $10,%ecx
jmp LLEntry3_8
//----------------------------------------
.globl Spr8Entry4_8
Spr8Entry4_8:
subl $4,%edi // adjust for hardwired offsets
subl $8,%ecx
jmp LLEntry4_8
//----------------------------------------
.globl Spr8Entry5_8
Spr8Entry5_8:
subl $3,%edi // adjust for hardwired offsets
subl $6,%ecx
jmp LLEntry5_8
//----------------------------------------
.globl Spr8Entry6_8
Spr8Entry6_8:
subl $2,%edi // adjust for hardwired offsets
subl $4,%ecx
jmp LLEntry6_8
//----------------------------------------
.globl Spr8Entry7_8
Spr8Entry7_8:
decl %edi // adjust for hardwired offsets
subl $2,%ecx
jmp LLEntry7_8
//----------------------------------------
.globl Spr8Entry8_8
Spr8Entry8_8:
cmpw (%ecx),%bp
jl Lp9
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp9
movw %bp,(%ecx)
movb %al,(%edi)
Lp9:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry7_8:
cmpw 2(%ecx),%bp
jl Lp10
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp10
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp10:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry6_8:
cmpw 4(%ecx),%bp
jl Lp11
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp11
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp11:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry5_8:
cmpw 6(%ecx),%bp
jl Lp12
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp12
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp12:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry4_8:
cmpw 8(%ecx),%bp
jl Lp13
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp13
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp13:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry3_8:
cmpw 10(%ecx),%bp
jl Lp14
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp14
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp14:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry2_8:
cmpw 12(%ecx),%bp
jl Lp15
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp15
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp15:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LEndSpan:
cmpw 14(%ecx),%bp
jl Lp16
movb (%esi),%al // load first texel in segment
cmpb $(TRANSPARENT_COLOR),%al
jz Lp16
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp16:
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
popl %ebx // restore spans pointer
LNextSpan:
addl $(sspan_t_size),%ebx // point to next span
movl sspan_t_count(%ebx),%ecx
cmpl $0,%ecx // any more spans?
jg LSpanLoop // yes
jz LNextSpan // yes, but this one's empty
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#endif // USE_INTEL_ASM

View file

@ -1,416 +0,0 @@
/*
d_sprite.c
software top-level rasterization driver module for drawing sprites
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_local.h"
#include "QF/render.h"
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
#ifndef USE_INTEL_ASM
void
D_SpriteDrawSpans (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (byte *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int) (zi * 0x8000 * 0x10000);
s = (int) (sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s and t
// steps across span by division, biasing steps low so we
// don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float) 0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps
// from from causing overstepping &
// running off the edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = btemp;
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
#endif
void
D_SpriteScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
vtop = ceil (r_spritedesc.pverts[i].v);
do {
pvert = &r_spritedesc.pverts[i];
pnext = pvert - 1;
vbottom = ceil (pnext->v);
if (vtop < vbottom) {
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int) (slope * 0x10000);
// adjust u to ceil the integer portion
u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int) vtop;
ibottom = (int) vbottom;
for (v = itop; v < ibottom; v++) {
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = r_spritedesc.nump;
} while (i != lmaxindex);
}
void
D_SpriteScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
vvert = r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = ceil (vvert);
do {
pvert = &r_spritedesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = ceil (vnext);
if (vtop < vbottom) {
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int) (slope * 0x10000);
// adjust u to ceil the integer portion
u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int) vtop;
ibottom = (int) vbottom;
for (v = itop; v < ibottom; v++) {
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
void
D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
TransformVector (modelorg, p_temp1);
sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
}
void
D_DrawSprite (void)
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT + 1];
sprite_spans = spans;
// find the top and bottom vertices, and make sure there's at least one
// scan to draw
ymin = 999999.9;
ymax = -999999.9;
pverts = r_spritedesc.pverts;
for (i = 0; i < r_spritedesc.nump; i++) {
if (pverts->v < ymin) {
ymin = pverts->v;
minindex = i;
}
if (pverts->v > ymax) {
ymax = pverts->v;
maxindex = i;
}
pverts++;
}
ymin = ceil (ymin);
ymax = ceil (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
cachewidth = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
cacheblock = (byte *) & r_spritedesc.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedesc.nump;
pverts = r_spritedesc.pverts;
pverts[nump] = pverts[0];
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
D_SpriteDrawSpans (sprite_spans);
}

View file

@ -1,325 +0,0 @@
/*
d_surf.c
rasterization driver surface heap manager
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "d_local.h"
#include "QF/qargs.h"
#include "r_local.h"
#include "QF/sys.h"
float surfscale;
qboolean r_cache_thrash; // set if surface cache is thrashing
int sc_size;
surfcache_t *sc_rover, *sc_base;
#define GUARDSIZE 4
void *
D_SurfaceCacheAddress (void)
{
return sc_base;
}
int
D_SurfaceCacheForRes (int width, int height)
{
int size, pix;
if (COM_CheckParm ("-surfcachesize")) {
size = atoi (com_argv[COM_CheckParm ("-surfcachesize") + 1]) * 1024;
return size;
}
size = SURFCACHE_SIZE_AT_320X200;
pix = width * height;
if (pix > 64000)
size += (pix - 64000) * 3;
return size;
}
void
D_CheckCacheGuard (void)
{
byte *s;
int i;
s = (byte *) sc_base + sc_size;
for (i = 0; i < GUARDSIZE; i++)
if (s[i] != (byte) i)
Sys_Error ("D_CheckCacheGuard: failed");
}
void
D_ClearCacheGuard (void)
{
byte *s;
int i;
s = (byte *) sc_base + sc_size;
for (i = 0; i < GUARDSIZE; i++)
s[i] = (byte) i;
}
void
D_InitCaches (void *buffer, int size)
{
// if (!msg_suppress_1)
// Con_Printf ("%ik surface cache\n", size/1024);
sc_size = size - GUARDSIZE;
sc_base = (surfcache_t *) buffer;
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
d_pzbuffer = vid.zbuffer;
D_ClearCacheGuard ();
}
void
D_FlushCaches (void)
{
surfcache_t *c;
if (!sc_base)
return;
for (c = sc_base; c; c = c->next) {
if (c->owner)
*c->owner = NULL;
}
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
}
surfcache_t *
D_SCAlloc (int width, int size)
{
surfcache_t *new;
qboolean wrapped_this_time;
if ((width < 0) || (width > 256))
Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
if ((size <= 0) || (size > 0x10000))
Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
/* This adds the offset of data[0] in the surfcache_t struct. */
size += (int) ((surfcache_t *) 0)->data;
#define SIZE_ALIGN (sizeof(surfcache_t*)-1)
size = (size + SIZE_ALIGN) & ~SIZE_ALIGN;
#undef SIZE_ALIGN
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size", size);
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
if (!sc_rover || (byte *) sc_rover - (byte *) sc_base > sc_size - size) {
if (sc_rover) {
wrapped_this_time = true;
}
sc_rover = sc_base;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sc_rover;
if (sc_rover->owner)
*sc_rover->owner = NULL;
while (new->size < size) {
// free another
sc_rover = sc_rover->next;
if (!sc_rover)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sc_rover->owner)
*sc_rover->owner = NULL;
new->size += sc_rover->size;
new->next = sc_rover->next;
}
// create a fragment out of any leftovers
if (new->size - size > 256) {
sc_rover = (surfcache_t *) ((byte *) new + size);
sc_rover->size = new->size - size;
sc_rover->next = new->next;
sc_rover->width = 0;
sc_rover->owner = NULL;
new->next = sc_rover;
new->size = size;
} else
sc_rover = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof (*new) + sizeof (new->data)) / width;
new->owner = NULL; // should be set properly after return
if (d_roverwrapped) {
if (wrapped_this_time || (sc_rover >= d_initial_rover))
r_cache_thrash = true;
} else if (wrapped_this_time) {
d_roverwrapped = true;
}
D_CheckCacheGuard (); // DEBUG
return new;
}
void
D_SCDump (void)
{
surfcache_t *test;
for (test = sc_base; test; test = test->next) {
if (test == sc_rover)
Sys_Printf ("ROVER:\n");
Sys_Printf ("%p : %i bytes %i width\n", test, test->size,
test->width);
}
}
// if the num is not a power of 2, assume it will not repeat
int
MaskForNum (int num)
{
if (num == 128)
return 127;
if (num == 64)
return 63;
if (num == 32)
return 31;
if (num == 16)
return 15;
return 255;
}
int
D_log2 (int num)
{
int c;
c = 0;
while (num >>= 1)
c++;
return c;
}
surfcache_t *
D_CacheSurface (msurface_t *surface, int miplevel)
{
surfcache_t *cache;
// if the surface is animating or flashing, flush the cache
r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
// see if the cache holds apropriate data
cache = surface->cachespots[miplevel];
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == r_drawsurf.texture
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
&& cache->lightadj[3] == r_drawsurf.lightadj[3])
return cache;
// determine shape of surface
surfscale = 1.0 / (1 << miplevel);
r_drawsurf.surfmip = miplevel;
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
// allocate memory if needed
if (!cache) // if a texture just animated, don't
// reallocate it
{
cache = D_SCAlloc (r_drawsurf.surfwidth,
r_drawsurf.surfwidth * r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
r_drawsurf.surfdat = (pixel_t *) cache->data;
cache->texture = r_drawsurf.texture;
cache->lightadj[0] = r_drawsurf.lightadj[0];
cache->lightadj[1] = r_drawsurf.lightadj[1];
cache->lightadj[2] = r_drawsurf.lightadj[2];
cache->lightadj[3] = r_drawsurf.lightadj[3];
// draw and light the surface texture
r_drawsurf.surf = surface;
c_surf++;
R_DrawSurface ();
return surface->cachespots[miplevel];
}

View file

@ -1,221 +0,0 @@
/*
d_varsa.S
(description)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
#ifdef USE_INTEL_ASM
.data
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
// FIXME: put all refresh variables into one contiguous block. Make into one
// big structure, like cl or sv?
.align 4
.globl C(d_sdivzstepu)
.globl C(d_tdivzstepu)
.globl C(d_zistepu)
.globl C(d_sdivzstepv)
.globl C(d_tdivzstepv)
.globl C(d_zistepv)
.globl C(d_sdivzorigin)
.globl C(d_tdivzorigin)
.globl C(d_ziorigin)
C(d_sdivzstepu): .single 0
C(d_tdivzstepu): .single 0
C(d_zistepu): .single 0
C(d_sdivzstepv): .single 0
C(d_tdivzstepv): .single 0
C(d_zistepv): .single 0
C(d_sdivzorigin): .single 0
C(d_tdivzorigin): .single 0
C(d_ziorigin): .single 0
.globl C(sadjust)
.globl C(tadjust)
.globl C(bbextents)
.globl C(bbextentt)
C(sadjust): .long 0
C(tadjust): .long 0
C(bbextents): .long 0
C(bbextentt): .long 0
.globl C(cacheblock)
.globl C(d_viewbuffer)
.globl C(cachewidth)
.globl C(d_pzbuffer)
.globl C(d_zrowbytes)
.globl C(d_zwidth)
C(cacheblock): .long 0
C(cachewidth): .long 0
C(d_viewbuffer): .long 0
C(d_pzbuffer): .long 0
C(d_zrowbytes): .long 0
C(d_zwidth): .long 0
//-------------------------------------------------------
// ASM-only variables
//-------------------------------------------------------
.globl izi
izi: .long 0
.globl pbase, s, t, sfracf, tfracf, snext, tnext
.globl spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
.globl zi8stepu, sdivz8stepu, tdivz8stepu, pz
s: .long 0
t: .long 0
snext: .long 0
tnext: .long 0
sfracf: .long 0
tfracf: .long 0
pbase: .long 0
zi8stepu: .long 0
sdivz8stepu: .long 0
tdivz8stepu: .long 0
zi16stepu: .long 0
sdivz16stepu: .long 0
tdivz16stepu: .long 0
spancountminus1: .long 0
pz: .long 0
.globl izistep
izistep: .long 0
//-------------------------------------------------------
// local variables for d_draw16.s
//-------------------------------------------------------
.globl reciprocal_table_16, entryvec_table_16
// 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13,
// 1/14, and 1/15 in 0.32 form
reciprocal_table_16: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
.long 0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
.long 0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
#ifndef NeXT
.extern Entry2_16
.extern Entry3_16
.extern Entry4_16
.extern Entry5_16
.extern Entry6_16
.extern Entry7_16
.extern Entry8_16
.extern Entry9_16
.extern Entry10_16
.extern Entry11_16
.extern Entry12_16
.extern Entry13_16
.extern Entry14_16
.extern Entry15_16
.extern Entry16_16
#endif
entryvec_table_16: .long 0, Entry2_16, Entry3_16, Entry4_16
.long Entry5_16, Entry6_16, Entry7_16, Entry8_16
.long Entry9_16, Entry10_16, Entry11_16, Entry12_16
.long Entry13_16, Entry14_16, Entry15_16, Entry16_16
//-------------------------------------------------------
// local variables for d_parta.s
//-------------------------------------------------------
.globl DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
DP_Count: .long 0
DP_u: .long 0
DP_v: .long 0
DP_32768: .single 32768.0
DP_Color: .long 0
DP_Pix: .long 0
#ifndef NeXT
.extern DP_1x1
.extern DP_2x2
.extern DP_3x3
.extern DP_4x4
#endif
DP_EntryTable: .long DP_1x1, DP_2x2, DP_3x3, DP_4x4
//
// advancetable is 8 bytes, but points to the middle of that range so negative
// offsets will work
//
.globl advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
advancetable: .long 0, 0
sstep: .long 0
tstep: .long 0
pspantemp: .long 0
counttemp: .long 0
jumptemp: .long 0
// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
.globl reciprocal_table, entryvec_table
reciprocal_table: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
#ifndef NeXT
.extern Entry2_8
.extern Entry3_8
.extern Entry4_8
.extern Entry5_8
.extern Entry6_8
.extern Entry7_8
.extern Entry8_8
#endif
entryvec_table: .long 0, Entry2_8, Entry3_8, Entry4_8
.long Entry5_8, Entry6_8, Entry7_8, Entry8_8
#ifndef NeXT
.extern Spr8Entry2_8
.extern Spr8Entry3_8
.extern Spr8Entry4_8
.extern Spr8Entry5_8
.extern Spr8Entry6_8
.extern Spr8Entry7_8
.extern Spr8Entry8_8
#endif
.globl spr8entryvec_table
spr8entryvec_table: .long 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
.long Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
#endif // USE_INTEL_ASM

View file

@ -1,51 +0,0 @@
/*
d_zpoint.c
software driver module for drawing z-buffered points
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d_local.h"
void
D_DrawZPoint (void)
{
byte *pdest;
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
izi = (int) (r_zpointdesc.zi * 0x8000);
if (*pz <= izi) {
*pz = izi;
*pdest = r_zpointdesc.color;
}
}

View file

@ -1,735 +0,0 @@
/*
gl_draw.c
Draw functions for chars, textures, etc
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdio.h>
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/draw.h"
#include "QF/quakefs.h"
#include "QF/render.h"
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/vid.h"
#include "QF/va.h"
#include "glquake.h"
#include "r_cvar.h"
#include "sbar.h"
extern byte *vid_basepal;
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor,
*gl_lightmap_components;
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
static int translate_texture;
static int char_texture;
static int cs_texture; // crosshair texturea
static byte cs_data[64] = {
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
typedef struct {
int texnum;
int bytesperpixel;
float sl, tl, sh, th;
} glpic_t;
extern int gl_filter_min, gl_filter_max;
typedef struct cachepic_s {
char name[MAX_QPATH];
qboolean dirty;
qpic_t pic;
byte padding[32]; // for appended glpic
} cachepic_t;
#define MAX_CACHED_PICS 128
static cachepic_t cachepics[MAX_CACHED_PICS];
static int numcachepics;
static byte menuplyr_pixels[4096];
qpic_t *
Draw_PicFromWad (char *name)
{
qpic_t *p;
glpic_t *gl;
p = W_GetLumpName (name);
gl = (glpic_t *) p->data;
gl->texnum = GL_LoadTexture ("", p->width, p->height, p->data, false, true, 1);
gl->sl = 0;
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
return p;
}
void
Draw_ClearCache (void)
{
cachepic_t *pic;
int i;
for (pic = cachepics, i = 0; i < numcachepics; pic++, i++)
pic->dirty = true;
}
qpic_t *
Draw_CachePic (char *path, qboolean alpha)
{
cachepic_t *pic;
int i;
qpic_t *dat;
glpic_t *gl;
// First, check if its cached..
for (pic = cachepics, i = 0; i < numcachepics; pic++, i++)
if ((!strcmp (path, pic->name)) && !pic->dirty)
return &pic->pic;
// Its not cached, lets make sure we have space in the cache..
if (numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
// Load the picture..
dat = (qpic_t *) COM_LoadTempFile (path);
if (!dat)
Sys_Error ("Draw_CachePic: failed to load %s", path);
// Adjust for endian..
SwapPic (dat);
// Ok, the image is here, lets load it up into the cache..
// First the image name..
strncpy (pic->name, path, sizeof (pic->name));
// Now the width and height.
pic->pic.width = dat->width;
pic->pic.height = dat->height;
// Now feed it to the GL stuff and get a texture number..
gl = (glpic_t *) pic->pic.data;
gl->texnum = GL_LoadTexture ("", dat->width, dat->height, dat->data, false, alpha, 1);
// Alignment stuff..
gl->sl = 0;
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
// Now lets mark this cache entry as used..
pic->dirty = false;
numcachepics++;
// FIXME:
// A really ugly kluge, keep a specific image in memory
// for the menu system.
// Some days I really dislike legacy support..
if (!strcmp (path, "gfx/menuplyr.lmp"))
memcpy (menuplyr_pixels, dat->data, dat->width * dat->height);
// And now we are done, return what was asked for..
return &pic->pic;
}
void
Draw_TextBox (int x, int y, int width, int lines)
{
qpic_t *p;
int cx, cy;
int n;
// draw left side
cx = x;
cy = y;
p = Draw_CachePic ("gfx/box_tl.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_ml.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bl.lmp", true);
Draw_Pic (cx, cy + 8, p);
// draw middle
cx += 8;
while (width > 0) {
cy = y;
p = Draw_CachePic ("gfx/box_tm.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mm.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
if (n == 1)
p = Draw_CachePic ("gfx/box_mm2.lmp", true);
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bm.lmp", true);
Draw_Pic (cx, cy + 8, p);
width -= 2;
cx += 16;
}
// draw right side
cy = y;
p = Draw_CachePic ("gfx/box_tr.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mr.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_br.lmp", true);
Draw_Pic (cx, cy + 8, p);
}
extern void glrmain_init (void);
extern void glrsurf_init (void);
extern void GL_TextureMode_f (void);
void
Draw_Init (void)
{
int i;
GLint texSize;
// Some cards have a texture size limit.
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
Cvar_Set (gl_max_size, va("%d", texSize));
// LordHavoc: 3DFX's dithering has terrible artifacts with lightmode 1
if (strstr (gl_renderer, "3dfx") || strstr (gl_renderer, "Mesa Glide"))
{
Cvar_Set (gl_lightmode, "0");
}
Cmd_AddCommand ("gl_texturemode", &GL_TextureMode_f, "Texture mipmap quality.");
// load the console background and the charset
// by hand, because we need to write the version
// string into the background before turning
// it into a texture
draw_chars = W_GetLumpName ("conchars");
for (i = 0; i < 256 * 64; i++)
if (draw_chars[i] == 0)
draw_chars[i] = 255; // proper transparent color
// now turn them into textures
char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); // 1999-12-27 Conwidth/height charset fix by TcT
cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true, 1);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// save a texture slot for translated picture
translate_texture = texture_extension_number++;
// get the other pics we need
draw_disc = Draw_PicFromWad ("disc");
draw_backtile = Draw_PicFromWad ("backtile");
// LordHavoc: call init code for other GL renderer modules;
glrmain_init ();
glrsurf_init ();
}
/*
Draw_Character8
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
*/
void
Draw_Character8 (int x, int y, int num)
{
int row, col;
float frow, fcol, size;
if (num == 32)
return; // space
num &= 255;
if (y <= -8)
return; // totally off screen
row = num >> 4;
col = num & 15;
frow = row * 0.0625;
fcol = col * 0.0625;
size = 0.0625;
glBindTexture (GL_TEXTURE_2D, char_texture);
glBegin (GL_QUADS);
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + size, frow);
glVertex2f (x + 8, y);
glTexCoord2f (fcol + size, frow + size);
glVertex2f (x + 8, y + 8);
glTexCoord2f (fcol, frow + size);
glVertex2f (x, y + 8);
glEnd ();
}
void
Draw_String8 (int x, int y, char *str)
{
while (*str) {
Draw_Character8 (x, y, *str);
str++;
x += 8;
}
}
void
Draw_AltString8 (int x, int y, char *str)
{
while (*str) {
Draw_Character8 (x, y, (*str) | 0x80);
str++;
x += 8;
}
}
void
Draw_Crosshair (int swap)
{
int x, y;
extern vrect_t scr_vrect;
unsigned char *pColor;
switch (crosshair->int_val) {
case 0:
break;
case 1:
default:
Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 +
cl_crossx->int_val,
scr_vrect.y + scr_vrect.height / 2 - 4 +
cl_crossy->int_val, '+');
break;
case 2:
x = scr_vrect.x + scr_vrect.width / 2 - 3 + cl_crossx->int_val;
y = scr_vrect.y + scr_vrect.height / 2 - 3 + cl_crossy->int_val;
pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val];
if (lighthalf)
glColor4ub ((byte) ((int) pColor[0] >> 1),
(byte) ((int) pColor[1] >> 1),
(byte) ((int) pColor[2] >> 1), pColor[3]);
else
glColor4ubv (pColor);
glBindTexture (GL_TEXTURE_2D, cs_texture);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x - 4, y - 4);
glTexCoord2f (1, 0);
glVertex2f (x + 12, y - 4);
glTexCoord2f (1, 1);
glVertex2f (x + 12, y + 12);
glTexCoord2f (0, 1);
glVertex2f (x - 4, y + 12);
glEnd ();
glColor3ubv (lighthalf_v);
break;
}
}
void
Draw_Pic (int x, int y, qpic_t *pic)
{
glpic_t *gl;
gl = (glpic_t *) pic->data;
glBindTexture (GL_TEXTURE_2D, gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x + pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x + pic->width, y + pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y + pic->height);
glEnd ();
}
void
Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
int height)
{
glpic_t *gl;
float newsl, newtl, newsh, newth;
float oldglwidth, oldglheight;
gl = (glpic_t *) pic->data;
oldglwidth = gl->sh - gl->sl;
oldglheight = gl->th - gl->tl;
newsl = gl->sl + (srcx * oldglwidth) / pic->width;
newsh = newsl + (width * oldglwidth) / pic->width;
newtl = gl->tl + (srcy * oldglheight) / pic->height;
newth = newtl + (height * oldglheight) / pic->height;
if (lighthalf)
glColor3f (0.4, 0.4, 0.4);
else
glColor3f (0.8, 0.8, 0.8);
glBindTexture (GL_TEXTURE_2D, gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (newsl, newtl);
glVertex2f (x, y);
glTexCoord2f (newsh, newtl);
glVertex2f (x + width, y);
glTexCoord2f (newsh, newth);
glVertex2f (x + width, y + height);
glTexCoord2f (newsl, newth);
glVertex2f (x, y + height);
glEnd ();
glColor3ubv (lighthalf_v);
}
/*
Draw_TransPicTranslate
Only used for the player color selection menu
*/
void
Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation)
{
int v, u, c;
unsigned int trans[64 * 64], *dest;
byte *src;
int p;
glBindTexture (GL_TEXTURE_2D, translate_texture);
c = pic->width * pic->height;
dest = trans;
for (v = 0; v < 64; v++, dest += 64) {
src = &menuplyr_pixels[((v * pic->height) >> 6) * pic->width];
for (u = 0; u < 64; u++) {
p = src[(u * pic->width) >> 6];
if (p == 255)
dest[u] = p;
else
dest[u] = d_8to24table[translation[p]];
}
}
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA,
GL_UNSIGNED_BYTE, trans);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
if (lighthalf)
glColor3f (0.4, 0.4, 0.4);
else
glColor3f (0.8, 0.8, 0.8);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x + pic->width, y);
glTexCoord2f (1, 1);
glVertex2f (x + pic->width, y + pic->height);
glTexCoord2f (0, 1);
glVertex2f (x, y + pic->height);
glEnd ();
glColor3ubv (lighthalf_v);
}
/*
Draw_ConsoleBackground
Draws console background (obviously!) Completely rewritten to use
several simple yet very cool GL effects. --KB
*/
void
Draw_ConsoleBackground (int lines)
{
int y;
qpic_t *conback;
glpic_t *gl;
float ofs;
float alpha;
// This can be a CachePic now, just like in software
conback = Draw_CachePic ("gfx/conback.lmp", false);
gl = (glpic_t *) conback->data;
// spin the console? - effect described in a QER tutorial
if (gl_conspin->value) {
static float xangle = 0;
static float xfactor = .3f;
static float xstep = .005f;
glPushMatrix ();
glMatrixMode (GL_TEXTURE);
glPushMatrix ();
glLoadIdentity ();
xangle += gl_conspin->value;
xfactor += xstep;
if (xfactor > 8 || xfactor < .3f)
xstep = -xstep;
glRotatef (xangle, 0, 0, 1);
glScalef (xfactor, xfactor, xfactor);
}
// slide console up/down or stretch it?
if (gl_constretch->int_val)
ofs = 0;
else
ofs = (vid.conheight - lines) / (float) vid.conheight;
y = vid.height * scr_consize->value;
if (!r_active || lines > y) {
alpha = 1.0;
} else {
// set up to draw alpha console
alpha = (float) (gl_conalpha->value * lines) / y;
}
if (lighthalf)
glColor4f (0.4, 0.4, 0.4, alpha);
else
glColor4f (0.8, 0.8, 0.8, alpha);
// draw the console texture
glBindTexture (GL_TEXTURE_2D, gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl + ofs);
glVertex2f (0, 0);
glTexCoord2f (gl->sh, gl->tl + ofs);
glVertex2f (vid.conwidth, 0);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (vid.conwidth, lines);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (0, lines);
glEnd ();
// turn off alpha blending
if (alpha < 1.0) {
if (lighthalf)
glColor3f (0.4, 0.4, 0.4);
else
glColor3f (0.8, 0.8, 0.8);
}
if (gl_conspin->value) {
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
}
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
lines - 14, cl_verstring->string);
glColor3ubv (lighthalf_v);
}
/*
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
*/
void
Draw_TileClear (int x, int y, int w, int h)
{
if (lighthalf)
glColor3f (0.4, 0.4, 0.4);
else
glColor3f (0.8, 0.8, 0.8);
glBindTexture (GL_TEXTURE_2D, *(int *) draw_backtile->data);
glBegin (GL_QUADS);
glTexCoord2f (x / 64.0, y / 64.0);
glVertex2f (x, y);
glTexCoord2f ((x + w) / 64.0, y / 64.0);
glVertex2f (x + w, y);
glTexCoord2f ((x + w) / 64.0, (y + h) / 64.0);
glVertex2f (x + w, y + h);
glTexCoord2f (x / 64.0, (y + h) / 64.0);
glVertex2f (x, y + h);
glEnd ();
glColor3ubv (lighthalf_v);
}
/*
Draw_Fill
Fills a box of pixels with a single color
*/
void
Draw_Fill (int x, int y, int w, int h, int c)
{
glDisable (GL_TEXTURE_2D);
if (lighthalf)
glColor3f (vid_basepal[c * 3] / 510.0, vid_basepal[c * 3 + 1] / 510.0,
vid_basepal[c * 3 + 2] / 510.0);
else
glColor3f (vid_basepal[c * 3] / 255.0, vid_basepal[c * 3 + 1] / 255.0,
vid_basepal[c * 3 + 2] / 255.0);
glBegin (GL_QUADS);
glVertex2f (x, y);
glVertex2f (x + w, y);
glVertex2f (x + w, y + h);
glVertex2f (x, y + h);
glEnd ();
glColor3ubv (lighthalf_v);
glEnable (GL_TEXTURE_2D);
}
//=============================================================================
void
Draw_FadeScreen (void)
{
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.7);
glBegin (GL_QUADS);
glVertex2f (0, 0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
glEnd ();
glColor3ubv (lighthalf_v);
glEnable (GL_TEXTURE_2D);
Sbar_Changed ();
}
//=============================================================================
/*
Draw_BeginDisc
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
*/
void
Draw_BeginDisc (void)
{
}
/*
Draw_EndDisc
Erases the disc icon.
Call after completing any disc IO
*/
void
Draw_EndDisc (void)
{
}
/*
GL_Set2D
Setup as if the screen was 320*200
*/
void
GL_Set2D (void)
{
glViewport (glx, gly, glwidth, glheight);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
glColor3ubv (lighthalf_v);
}

View file

@ -1,210 +0,0 @@
/*
gl_dyn_fires.c
dynamic fires
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/render.h"
#include "glquake.h"
#include "r_shared.h"
#define MAX_FIRES 128 // rocket flames
static fire_t r_fires[MAX_FIRES];
extern cvar_t *gl_fires;
extern cvar_t *r_firecolor;
/*
R_AddFire
Nifty ball of fire GL effect. Kinda a meshing of the dlight and
particle engine code.
*/
void
R_AddFire (vec3_t start, vec3_t end, entity_t *ent)
{
float len;
fire_t *f;
vec3_t vec;
int key;
if (!gl_fires->int_val)
return;
VectorSubtract (end, start, vec);
len = VectorNormalize (vec);
key = ent->keynum;
if (len) {
f = R_AllocFire (key);
VectorCopy (end, f->origin);
VectorCopy (start, f->owner);
f->size = 10;
f->die = r_realtime + 0.5;
f->decay = 1;
VectorCopy (r_firecolor->vec, f->color);
}
}
/*
R_AllocFire
Clears out and returns a new fireball
*/
fire_t *
R_AllocFire (int key)
{
int i;
fire_t *f;
if (key) // first try to find/reuse a keyed
// spot
{
f = r_fires;
for (i = 0; i < MAX_FIRES; i++, f++)
if (f->key == key) {
memset (f, 0, sizeof (*f));
f->key = key;
return f;
}
}
f = r_fires; // no match, look for a free spot
for (i = 0; i < MAX_FIRES; i++, f++) {
if (f->die < r_realtime) {
memset (f, 0, sizeof (*f));
f->key = key;
return f;
}
}
f = &r_fires[0];
memset (f, 0, sizeof (*f));
f->key = key;
return f;
}
/*
R_DrawFire
draws one fireball - probably never need to call this directly
*/
void
R_DrawFire (fire_t *f)
{
int i, j;
vec3_t vec, vec2;
float radius;
float *b_sin, *b_cos;
b_sin = bubble_sintable;
b_cos = bubble_costable;
radius = f->size - 0.5;
// figure out if we're inside the area of effect
VectorSubtract (f->origin, r_origin, vec);
if (Length (vec) < radius) {
AddLightBlend (f->color[0], f->color[1], f->color[2], f->size * 0.0003); // we are
return;
}
// we're not - draw it
glBegin (GL_TRIANGLE_FAN);
if (lighthalf)
glColor3f (f->color[0] * 0.5, f->color[1] * 0.5, f->color[2] * 0.5);
else
glColor3fv (f->color);
for (i = 0; i < 3; i++)
vec[i] = f->origin[i] - vpn[i] * radius;
glVertex3fv (vec);
glColor3f (0.0, 0.0, 0.0);
// don't panic, this just draws a bubble...
for (i = 16; i >= 0; i--) {
for (j = 0; j < 3; j++) {
vec[j] = f->origin[j] + (*b_cos * vright[j]
+ vup[j] * (*b_sin)) * radius;
vec2[j] = f->owner[j] + (*b_cos * vright[j]
+ vup[j] * (*b_sin)) * radius;
}
glVertex3fv (vec);
glVertex3fv (vec2);
b_sin += 2;
b_cos += 2;
}
glEnd ();
glColor3ubv (lighthalf_v);
}
/*
R_UpdateFires
Draws each fireball in sequence
*/
void
R_UpdateFires (void)
{
int i;
fire_t *f;
if (!gl_fires->int_val)
return;
glDepthMask (GL_FALSE);
glDisable (GL_TEXTURE_2D);
glBlendFunc (GL_ONE, GL_ONE);
f = r_fires;
for (i = 0; i < MAX_FIRES; i++, f++) {
if (f->die < r_realtime || !f->size)
continue;
f->size += f->decay;
R_DrawFire (f);
}
glEnable (GL_TEXTURE_2D);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask (GL_TRUE);
}

View file

@ -1,203 +0,0 @@
/*
gl_dyn_textures.c
Dynamic texture generation.
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "glquake.h"
extern void noise_diamondsquare(unsigned char *noise, int size);
extern void noise_plasma(unsigned char *noise, int size);
static void GDT_InitDotParticleTexture (void);
static void GDT_InitSparkParticleTexture (void);
static void GDT_InitSmokeParticleTexture (void);
static void GDT_InitSmokeRingParticleTexture (void);
int part_tex_dot;
int part_tex_spark;
int part_tex_smoke[8];
int part_tex_smoke_ring[8];
void
GDT_Init (void)
{
GDT_InitDotParticleTexture ();
GDT_InitSparkParticleTexture ();
GDT_InitSmokeParticleTexture ();
GDT_InitSmokeRingParticleTexture ();
}
static void
GDT_InitDotParticleTexture (void)
{
int x, y, dx2, dy, d;
byte data[16][16][2];
for (x = 0; x < 16; x++) {
dx2 = x - 8;
dx2 *= dx2;
for (y = 0; y < 16; y++) {
dy = y - 8;
d = 255 - 4 * (dx2 + (dy * dy));
if (d<=0) {
d = 0;
data[y][x][0] = 0;
} else
data[y][x][0] = 255;
data[y][x][1] = (byte) d;
}
}
part_tex_dot = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, part_tex_dot);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, 2, 16, 16, 0, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE, data);
}
static void
GDT_InitSparkParticleTexture (void)
{
int x, y, dx2, dy, d;
byte data[16][16][2];
for (x = 0; x < 16; x++) {
dx2 = 8 - abs(x - 8);
dx2 *= dx2;
for (y = 0; y < 16; y++) {
dy = 8 - abs(y - 8);
d = 3 * (dx2 + dy * dy) - 100;
if (d>255)
d = 255;
if (d<1) {
d = 0;
data[y][x][0] = 0;
} else
data[y][x][0] = 255;
data[y][x][1] = (byte) d;
}
}
part_tex_spark = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, part_tex_spark);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, 2, 16, 16, 0, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE, data);
}
static void
GDT_InitSmokeParticleTexture (void)
{
int i, x, y, c;
float dx, dy2;
byte d, data[32][32][2], noise1[32][32], noise2[32][32];
for (i = 0; i < 8; i++) {
noise_plasma (&noise1[0][0], 32);
noise_diamondsquare (&noise2[0][0], 32);
for (y = 0; y < 32; y++)
{
dy2 = y - 16;
dy2 *= dy2;
for (x = 0; x < 32; x++) {
dx = x - 16;
c = 255 - (dx*dx + dy2);
if (c < 1)
c = 0;
d = (noise1[y][x] + noise2[y][x]) / 2;
if (d > 0) {
data[y][x][0] = 255;
data[y][x][1] = (d * c)/255;
} else {
data[y][x][0] = 255;
data[y][x][1] = 0;
}
}
}
part_tex_smoke[i] = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, part_tex_smoke[i]);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, 2, 32, 32, 0, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE, data);
}
}
static void
GDT_InitSmokeRingParticleTexture (void)
{
int i, x, y, b;
float dx, dy, c, c2;
byte d, data[32][32][2], noise1[32][32], noise2[32][32];
for (i = 0; i < 8; i++) {
noise_diamondsquare (&noise1[0][0], 32);
noise_plasma (&noise2[0][0], 32);
for (y = 0; y < 32; y++)
{
dy = y - 16;
dy *= dy;
for (x = 0; x < 32; x++) {
dx = x - 16;
dx *= dx;
c = 255 - (dx + dy);
c2 = (dx + dy);
if (c < 1) c = 0;
if (c2 < 1) c2 = 0;
//b = ((c / 255) * (c2 / 255)) * 512;
b = (c * c2) * 512 / (255*255);
if (b < 1) b = 0;
d = (noise1[y][x] + noise2[y][x]) / 2;
if (d > 0) {
data[y][x][0] = 255;
data[y][x][1] = (d * b)/255;
} else {
data[y][x][0] = 255;
data[y][x][1] = 0;
}
}
}
part_tex_smoke_ring[i] = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, part_tex_smoke_ring[i]);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, 2, 32, 32, 0, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE, data);
}
}

View file

@ -1,140 +0,0 @@
/*
gl_ngraph.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include "QF/cvar.h"
#include "QF/draw.h"
#include "QF/sys.h"
#include "glquake.h"
#include "r_cvar.h"
extern byte *draw_chars; // 8*8 graphic characters
extern qboolean lighthalf;
extern cvar_t *r_netgraph;
extern cvar_t *r_netgraph_alpha;
extern cvar_t *r_netgraph_box;
static int graph_index;
static int graph_size[NUM_GRAPH_TEXTURES];
static int graph_width[NUM_GRAPH_TEXTURES];
static byte *graph_texels[NUM_GRAPH_TEXTURES];
int graph_texture[NUM_GRAPH_TEXTURES];
int
R_InitGraphTextures (int base)
{
int i;
for (i = 0; i < NUM_GRAPH_TEXTURES; i++)
graph_texture[i] = base++;
return base;
}
void
R_LineGraph (int x, int y, int *h_vals, int count)
{
int i, j;
int h;
int s;
byte color;
int size;
byte *dest;
if (!count)
return;
s = r_graphheight->int_val;
size = s * count;
if (size > graph_size[graph_index]) {
graph_size[graph_index] = size;
graph_texels[graph_index] = realloc (graph_texels[graph_index], size);
}
graph_width[graph_index] = count;
if (!graph_texels[graph_index])
Sys_Error ("R_LineGraph: failed to allocate texture buffer\n");
i = 0;
while (count--) {
dest = graph_texels[graph_index] + i++;
h = *h_vals++;
if (h == 10000)
color = 0x6f; // yellow
else if (h == 9999)
color = 0x4f; // red
else if (h == 9998)
color = 0xd0; // blue
else
color = 0xfe; // white
if (h > s)
h = s;
for (j = 0; j < h; j++, dest += graph_width[graph_index])
dest[0] = color;
for (; j < s; j++, dest += graph_width[graph_index])
dest[0] = 0xff;
}
glBindTexture (GL_TEXTURE_2D, graph_texture[graph_index]);
GL_Upload8 (graph_texels[graph_index], graph_width[graph_index], s, 0, 1);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x + graph_width[graph_index], y);
glTexCoord2f (1, 1);
glVertex2f (x + graph_width[graph_index], y - s);
glTexCoord2f (0, 1);
glVertex2f (x, y - s);
glEnd ();
glColor3ubv (lighthalf_v);
graph_index = (graph_index + 1) % NUM_GRAPH_TEXTURES;
}

View file

@ -1,429 +0,0 @@
/*
gl_rlight.c
@description@
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include <stdio.h>
#include "QF/render.h"
#include "glquake.h"
#include "r_shared.h"
void
R_AnimateLight (void)
{
int i, j, k;
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int) (r_realtime * 10);
for (j = 0; j < MAX_LIGHTSTYLES; j++) {
if (!r_lightstyle[j].length) {
d_lightstylevalue[j] = 256;
continue;
}
k = i % r_lightstyle[j].length;
k = r_lightstyle[j].map[k] - 'a';
k = k * 22;
d_lightstylevalue[j] = k;
}
}
/*
DYNAMIC LIGHTS BLEND RENDERING
*/
void
AddLightBlend (float r, float g, float b, float a2)
{
float a;
v_blend[3] = a = v_blend[3] + a2 * (1 - v_blend[3]);
a2 = a2 / a;
v_blend[0] = v_blend[0] * (1 - a2) + r * a2;
v_blend[1] = v_blend[1] * (1 - a2) + g * a2;
v_blend[2] = v_blend[2] * (1 - a2) + b * a2;
//Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
}
float bubble_sintable[33], bubble_costable[33];
void
R_InitBubble ()
{
int i;
float a;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
for (i = 32; i >= 0; i--) {
a = i / 32.0 * M_PI * 2;
*bub_sin++ = sin (a);
*bub_cos++ = cos (a);
}
}
void
R_RenderDlight (dlight_t *light)
{
int i, j;
vec3_t v;
float rad;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
rad = light->radius * 0.35;
VectorSubtract (light->origin, r_origin, v);
if (Length (v) < rad) { // view is inside the dlight
return;
}
glBegin (GL_TRIANGLE_FAN);
if (lighthalf)
glColor3f (light->color[0] * 0.5, light->color[1] * 0.5,
light->color[2] * 0.5);
else
glColor3fv (light->color);
VectorSubtract (r_origin, light->origin, v);
VectorNormalize (v);
for (i = 0; i < 3; i++)
v[i] = light->origin[i] + v[i] * rad;
glVertex3fv (v);
glColor3f (0, 0, 0);
for (i = 16; i >= 0; i--) {
for (j = 0; j < 3; j++)
v[j] = light->origin[j] + (vright[j] * (*bub_cos) +
vup[j] * (*bub_sin)) * rad;
bub_sin += 2;
bub_cos += 2;
glVertex3fv (v);
}
glEnd ();
}
void
R_RenderDlights (void)
{
int i;
dlight_t *l;
if (!gl_dlight_polyblend->int_val)
return;
glDepthMask (GL_FALSE);
glDisable (GL_TEXTURE_2D);
glBlendFunc (GL_ONE, GL_ONE);
glShadeModel (GL_SMOOTH);
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
R_RenderDlight (l);
}
if (!gl_dlight_smooth->int_val)
glShadeModel (GL_FLAT);
glColor3ubv (lighthalf_v);
glEnable (GL_TEXTURE_2D);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask (GL_TRUE);
}
/*
DYNAMIC LIGHTS
*/
// LordHavoc: heavily modified, to eliminate unnecessary texture uploads,
// and support bmodel lighting better
void
R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float ndist, maxdist;
msurface_t *surf;
int i;
maxdist = light->radius * light->radius;
loc0:
if (node->contents < 0)
return;
splitplane = node->plane;
ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist;
if (ndist > light->radius) {
// Save time by not pushing another stack frame.
if (node->children[0]->contents >= 0) {
node = node->children[0];
goto loc0;
}
return;
}
if (ndist < -light->radius) {
// Save time by not pushing another stack frame.
if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
return;
}
// mark the polygons
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
int s, t;
float l, dist, dist2;
vec3_t impact;
dist = ndist;
dist2 = dist * dist;
if (dist2 >= maxdist)
continue;
impact[0] = light->origin[0] - surf->plane->normal[0] * dist;
impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
l = DotProduct (impact, surf->texinfo->vecs[0]) +
surf->texinfo->vecs[0][3] - surf->texturemins[0];
s = l + 0.5;
if (s < 0)
s = 0;
else if (s > surf->extents[0])
s = surf->extents[0];
s = l - s;
l = DotProduct (impact, surf->texinfo->vecs[1]) +
surf->texinfo->vecs[1][3] - surf->texturemins[1];
t = l + 0.5;
if (t < 0)
t = 0;
else if (t > surf->extents[1])
t = surf->extents[1];
t = l - t;
if ((s * s + t * t + dist * dist) < maxdist) {
if (surf->dlightframe != r_framecount) {
surf->dlightframe = r_framecount;
surf->dlightbits = bit;
} else {
surf->dlightbits |= bit;
}
}
}
if (node->children[0]->contents >= 0) {
if (node->children[1]->contents >= 0)
R_MarkLights (lightorigin, light, bit, node->children[1]);
node = node->children[0];
goto loc0;
} else if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
}
void
R_PushDlights (vec3_t entorigin)
{
int i;
dlight_t *l;
vec3_t lightorigin;
if (!gl_dlight_lightmap->int_val)
return;
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
VectorSubtract (l->origin, entorigin, lightorigin);
R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model->nodes);
}
}
/*
LIGHT SAMPLING
*/
mplane_t *lightplane;
vec3_t lightspot;
int
RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
int r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
unsigned int scale;
int maps;
if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
return RecursiveLightPoint (node->children[side], start, end);
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
// go down front side
r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ((back < 0) == side)
return -1; // didn't hit anything
// check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
if (s < surf->texturemins[0] || t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if (ds > surf->extents[0] || dt > surf->extents[1])
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap) {
lightmap += dt * ((surf->extents[0] >> 4) + 1) + ds;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
maps++) {
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0] >> 4) + 1) *
((surf->extents[1] >> 4) + 1);
}
r >>= 8;
}
return r;
}
// go down back side
return RecursiveLightPoint (node->children[!side], mid, end);
}
int
R_LightPoint (vec3_t p)
{
vec3_t end;
int r;
if (!r_worldentity.model->lightdata)
return 255;
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint (r_worldentity.model->nodes, p, end);
if (r == -1)
r = 0;
return r;
}

Some files were not shown because too many files have changed in this diff Show more