1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_glide.c 1388 2018-04-15 02:10:08Z wesleyjohnson $
5 //
6 // Copyright (C) 1998-2012 by DooM Legacy Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 //
19 // $Log: r_glide.c,v $
20 // Revision 1.26 2001/08/26 15:27:30 bpereira
21 // added fov for glide and fixed newcoronas code
22 //
23 // Revision 1.25 2001/08/20 18:34:20 bpereira
24 // glide ligthing and map30 bug
25 //
26 // Revision 1.24 2001/08/19 15:40:07 bpereira
27 // added Treansform (and lighting) to glide
28 //
29 // Revision 1.23 2001/07/28 16:18:39 bpereira
30 // Revision 1.22 2001/02/24 13:35:22 bpereira
31 // Revision 1.21 2001/01/25 18:56:28 bpereira
32 //
33 // Revision 1.20 2001/01/05 18:19:13 hurdler
34 // add renderer version checking
35 //
36 // Revision 1.19 2000/11/04 16:23:45 bpereira
37 // Revision 1.18 2000/10/08 13:30:02 bpereira
38 //
39 // Revision 1.17 2000/10/04 16:29:57 hurdler
40 // Implement hardware texture memory stats (TODO in glide mode)
41 //
42 // Revision 1.16 2000/09/28 20:57:21 bpereira
43 // Revision 1.15 2000/08/31 14:30:57 bpereira
44 //
45 // Revision 1.14 2000/08/10 14:17:58 hurdler
46 // add waitvbl
47 //
48 // Revision 1.13 2000/08/03 17:57:42 bpereira
49 // Revision 1.12 2000/07/01 09:23:50 bpereira
50 // Revision 1.11 2000/05/09 20:50:57 hurdler
51 // Revision 1.10 2000/05/05 18:00:06 bpereira
52 // Revision 1.9 2000/04/30 10:30:10 bpereira
53 // Revision 1.8 2000/04/23 16:19:52 bpereira
54 // Revision 1.7 2000/04/18 12:50:55 hurdler
55 //
56 // Revision 1.5 2000/04/14 16:38:24 hurdler
57 // some nice changes for coronas
58 //
59 // Revision 1.4 2000/03/06 15:26:17 hurdler
60 // Revision 1.3 2000/02/27 00:42:11 hurdler
61 // Revision 1.2 2000/02/26 00:28:42 hurdler
62 // Mostly bug fix (see borislog.txt 23-2-2000, 24-2-2000)
63 //
64 //
65 // DESCRIPTION:
66 // 3Dfx Glide Render driver
67 //
68 //-----------------------------------------------------------------------------
69
70 //output debugging msgs to r_glide.log
71 //#define DEBUG_GLIDE_TO_FILE
72
73 #ifndef SMIF_WIN_NATIVE
74 # error r_glide is WIN_NATIVE only
75 #endif
76
77 #include <windows.h>
78 #include <glide.h>
79 #include <math.h>
80
81 #define HWRAPI_CREATE_DLL
82 #include "hardware/hw_drv.h"
83
84 #include "screen.h"
85 #include "3dmath.h"
86
87
88 // **************************************************************************
89 // PROTOS
90 // **************************************************************************
91
92 // output all debugging messages to this file
93 #ifdef DEBUG_GLIDE_TO_FILE
94 static HANDLE glide_logstream;
95 #endif
96
97 static void GR_ResetStates(viddef_t *lvid);
98 static void GR_InitMipmapCache(void);
99 static void GR_ClearMipmapCache(void);
100
101 static void MakeFogTable(void);
102 static void FreeFogTable(void);
103 static void ReSetSpecialState(void);
104
105 // **************************************************************************
106 // GLOBALS
107 // **************************************************************************
108
109 //0 means glide mode not set yet, this is returned by grSstWinOpen()
110 static GrContext_t grPreviousContext = 0;
111
112 // align boundary for textures in texture cache, set at Init()
113 static FxU32 gr_alignboundary;
114
115 static FBITFIELD CurrentPolyFlags;
116 static FBITFIELD CurrentTextureFlags;
117
118 static vxtx3d_t tmpVerts[MAXCLIPVERTS*2];
119 static vxtx3d_t tmp2Verts[MAXCLIPVERTS*2];
120 static vxtx3d_t tmp3Verts[MAXCLIPVERTS*2];
121
122 static FTransform_t grTransform;
123 static FTransform_t defaulttransform = {0,0,0,0,90,1,1,1,90,90};
124 static float szsinx, szcosx, siny, cosy, sxsiny, sxcosy, sysinx, sycosx;
125
126 static I_Error_t I_ErrorGr = NULL;
127 static glide_initialized = false;
128 static int glide_state[HWD_NUMSTATE];
129
130 // **************************************************************************
131 // DLL ENTRY POINT
132 // **************************************************************************
DllMain(HANDLE hModule,DWORD fdwReason,LPVOID lpReserved)133 BOOL APIENTRY DllMain( HANDLE hModule, // handle to DLL module
134 DWORD fdwReason, // reason for calling function
135 LPVOID lpReserved ) // reserved
136 {
137 // Perform actions based on the reason for calling.
138 switch( fdwReason )
139 {
140 case DLL_PROCESS_ATTACH:
141 // Initialize once for each new process.
142 // Return FALSE to fail DLL load.
143 #ifdef DEBUG_GLIDE_TO_FILE
144 glide_logstream = INVALID_HANDLE_VALUE;
145 glide_logstream = CreateFile ("r_glide.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
146 FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_WRITE_THROUGH*/, NULL);
147 if (glide_logstream == INVALID_HANDLE_VALUE)
148 return FALSE;
149 #endif
150 break;
151
152 case DLL_THREAD_ATTACH:
153 // Do thread-specific initialization.
154 break;
155
156 case DLL_THREAD_DETACH:
157 // Do thread-specific cleanup.
158 break;
159
160 case DLL_PROCESS_DETACH:
161 // Perform any necessary cleanup.
162 #ifdef DEBUG_GLIDE_TO_FILE
163 if ( glide_logstream != INVALID_HANDLE_VALUE ) {
164 CloseHandle ( glide_logstream );
165 glide_logstream = INVALID_HANDLE_VALUE;
166 }
167 #endif
168 break;
169 }
170 return TRUE; // Successful DLL_PROCESS_ATTACH.
171 }
172
173
174 // ----------
175 // DBG_Printf
176 // Output error messages to debug log if DEBUG_GLIDE_TO_FILE is defined,
177 // else do nothing
178 // ----------
DBG_Printf(LPCTSTR lpFmt,...)179 void DBG_Printf (LPCTSTR lpFmt, ...)
180 {
181 #ifdef DEBUG_GLIDE_TO_FILE
182 char str[1999];
183 va_list arglist;
184 DWORD bytesWritten;
185
186 va_start (arglist, lpFmt);
187 vsprintf (str, lpFmt, arglist);
188 va_end (arglist);
189
190 if ( glide_logstream != INVALID_HANDLE_VALUE )
191 WriteFile (glide_logstream, str, lstrlen(str), &bytesWritten, NULL);
192 #endif
193 }
194
195
196 // error callback function
GrErrorCallbackFnc(const char * string,FxBool fatal)197 void GrErrorCallbackFnc (const char *string, FxBool fatal)
198 {
199 DBG_Printf ("Glide error(%d) : %s\n",string,fatal);
200 if( fatal && I_ErrorGr )
201 I_ErrorGr ("Glide error : %s",string);
202 }
203
204 // ==========================================================================
205 // Initialise
206 // ==========================================================================
HWRAPI(Init)207 EXPORT BOOL HWRAPI( Init ) (I_Error_t FatalErrorFunction)
208 {
209 FxU32 numboards;
210 FxI32 fxret;
211
212 I_ErrorGr = FatalErrorFunction;
213 DBG_Printf ("HWRAPI Init(): 3Dfx Glide Render driver for Doom Legacy v1.31\n");
214
215 // check for Voodoo card
216 // - the ONLY possible call before GlideInit
217 grGet (GR_NUM_BOARDS,4,&numboards);
218 DBG_Printf ("Num 3Dfx boards : %d\n", numboards);
219 if (!numboards) {
220 I_ErrorGr ("3dfx chipset not detected\n");
221 return FALSE;
222 }
223
224 // init
225 grGlideInit();
226 grErrorSetCallback(GrErrorCallbackFnc);
227
228 // select subsystem
229 grSstSelect( 0 );
230
231 DBG_Printf( "GR_VENDOR: %s\n", grGetString(GR_VENDOR) );
232 DBG_Printf( "GR_EXTENSION: %s\n", grGetString(GR_EXTENSION) );
233 DBG_Printf( "GR_HARDWARE: %s\n", grGetString(GR_HARDWARE) );
234 DBG_Printf( "GR_RENDERER: %s\n", grGetString(GR_RENDERER) );
235 DBG_Printf( "GR_VERSION: %s\n", grGetString(GR_VERSION) );
236
237 // info
238 grGet (GR_MAX_TEXTURE_SIZE, 4, &fxret);
239 DBG_Printf ( "Max texture size : %d\n", fxret);
240 grGet (GR_NUM_TMU, 4, &fxret);
241 DBG_Printf ( "Number of TMU's : %d\n", fxret);
242 grGet (GR_TEXTURE_ALIGN, 4, &fxret);
243 DBG_Printf ( "Align boundary for textures : %d\n", fxret);
244 // save for later!
245 gr_alignboundary = fxret;
246 if (fxret==0)
247 gr_alignboundary = 16; //hack, need to be > 0
248
249 glide_state[HWD_SET_FOG_MODE] = 1;
250 glide_state[HWD_SET_FOG_COLOR] = 0x7f7f7f;
251 glide_state[HWD_SET_FOG_DENSITY] = 500;
252 glide_state[HWD_SET_POLYGON_SMOOTH] = false;
253 glide_state[HWD_SET_TEXTUREFILTERMODE] = HWD_SET_TEXTUREFILTER_BILINEAR;
254
255 SetTransform(NULL);
256
257 return TRUE;
258 }
259
260
261 static viddef_t* viddef;
262 // ==========================================================================
263 //
264 // ==========================================================================
HWRAPI(Shutdown)265 EXPORT void HWRAPI( Shutdown ) (void)
266 {
267 DBG_Printf ("HWRAPI Shutdown()\n");
268 grGlideShutdown();
269 FreeFogTable();
270 glide_initialized = false;
271 }
272
273
274 // **************************************************************************
275 // 3DFX DISPLAY MODES DRIVER
276 // **************************************************************************
277
278 static int Set3DfxMode (viddef_t *lvid, vmode_t *pcurrentmode) ;
279
280
281 // --------------------------------------------------------------------------
282 //
283 // --------------------------------------------------------------------------
284 #define MAX_VIDEO_MODES 30
285 static vmode_t video_modes[MAX_VIDEO_MODES] = {{NULL, NULL}};
286
287
HWRAPI(GetModeList)288 EXPORT void HWRAPI( GetModeList ) (vmode_t** pvidmodes, int* numvidmodes)
289 {
290 GrResolution query;
291 GrResolution *list;
292 GrResolution *grRes;
293 char* resTxt;
294 int listSize;
295 int listPos;
296 int iPrevWidth, iPrevHeight; //skip duplicate modes
297 int iMode, iWidth, iHeight;
298
299 DBG_Printf ("HWRAPI GetModeList()\n");
300
301 // find all possible modes that include a z-buffer
302 query.resolution = GR_QUERY_ANY;
303 query.refresh = GR_QUERY_ANY;
304 query.numColorBuffers = 2; //GR_QUERY_ANY;
305 query.numAuxBuffers = 1;
306 listSize = grQueryResolutions (&query, NULL);
307 list = _alloca(listSize);
308 grQueryResolutions (&query, list);
309
310 iMode=0;
311 grRes = list;
312 iPrevWidth = 0; iPrevHeight = 0;
313 for (listPos=0; listPos<listSize; listPos+=sizeof(GrResolution) , grRes++)
314 {
315 if (iMode>=MAX_VIDEO_MODES)
316 {
317 DBG_Printf ("Too many vidmode\n");
318 break; // quit the for
319 }
320
321 switch (grRes->resolution)
322 {
323 case GR_RESOLUTION_320x200 : resTxt = "320x200"; iWidth = 320; iHeight = 200; break;
324 case GR_RESOLUTION_320x240 : resTxt = "320x240"; iWidth = 320; iHeight = 240; break;
325 case GR_RESOLUTION_400x256 : resTxt = "400x256"; iWidth = 400; iHeight = 256; break;
326 case GR_RESOLUTION_512x384 : resTxt = "512x384"; iWidth = 512; iHeight = 384; break;
327 case GR_RESOLUTION_640x200 : resTxt = "640x200"; iWidth = 640; iHeight = 200; break;
328 case GR_RESOLUTION_640x350 : resTxt = "640x350"; iWidth = 640; iHeight = 350; break;
329 case GR_RESOLUTION_640x400 : resTxt = "640x400"; iWidth = 640; iHeight = 400; break;
330 case GR_RESOLUTION_640x480 : resTxt = "640x480"; iWidth = 640; iHeight = 480; break;
331 case GR_RESOLUTION_800x600 : resTxt = "800x600"; iWidth = 800; iHeight = 600; break;
332 case GR_RESOLUTION_960x720 : resTxt = "960x720"; iWidth = 960; iHeight = 720; break;
333 case GR_RESOLUTION_856x480 : resTxt = "856x480"; iWidth = 856; iHeight = 480; break;
334 case GR_RESOLUTION_512x256 : resTxt = "512x256"; iWidth = 512; iHeight = 256; break;
335 case GR_RESOLUTION_1024x768 : resTxt = "1024x768"; iWidth = 1024; iHeight = 768; break;
336 case GR_RESOLUTION_1280x1024: resTxt = "1280x1024"; iWidth = 1280; iHeight = 1024; break;
337 case GR_RESOLUTION_1600x1200: resTxt = "1600x1200"; iWidth = 1600; iHeight = 1200; break;
338 case GR_RESOLUTION_400x300 : resTxt = "400x300"; iWidth = 400; iHeight = 300; break;
339 case GR_RESOLUTION_NONE : resTxt = "NONE"; iWidth = 0; iHeight = 0; break;
340 default:
341 iWidth = 0; iHeight = 0;
342 resTxt = "unknown resolution"; break;
343 }
344
345 if( iWidth == 0 || iHeight == 0)
346 {
347 DBG_Printf ("Wrong Mode (%s)\n",resTxt);
348 continue;
349 }
350
351 // skip duplicate resolutions where only the refresh rate changes
352 if( iWidth==iPrevWidth && iHeight==iPrevHeight)
353 {
354 DBG_Printf ("Same mode (%s) %d\n",resTxt,grRes->refresh);
355 continue;
356 }
357
358 // disable too big modes until we get it fixed
359 if ( iWidth > MAXVIDWIDTH || iHeight > MAXVIDHEIGHT )
360 {
361 DBG_Printf ("Mode too big (%s)\n",resTxt);
362 continue;
363 }
364
365 // save video mode information for video modes menu
366 video_modes[iMode].pnext = &video_modes[iMode+1];
367 video_modes[iMode].windowed = 0;
368 video_modes[iMode].misc = grRes->resolution;
369 video_modes[iMode].name = resTxt;
370 video_modes[iMode].width = iWidth;
371 video_modes[iMode].height = iHeight;
372 video_modes[iMode].rowbytes = iWidth * 2; //framebuffer 16bit, but we don't use this anyway..
373 video_modes[iMode].bytesperpixel = 2;
374 video_modes[iMode].pextradata = NULL; // for VESA, unused here
375 video_modes[iMode].setmode = Set3DfxMode;
376 DBG_Printf ("Mode %d : %s (%dx%d) %dHz ires %d \n",
377 iMode,resTxt, iWidth, iHeight, grRes->refresh, grRes->resolution);
378 iMode++;
379 iPrevWidth = iWidth; iPrevHeight = iHeight;
380 }
381
382 // add video modes to the list
383 if (iMode>0)
384 {
385 video_modes[iMode-1].pnext = NULL;
386 (*(vmode_t**)pvidmodes) = &video_modes[0];
387 (*numvidmodes) = iMode;
388 }
389
390 // VGA Init equivalent (add first defautlt mode)
391 //glidevidmodes[NUMGLIDEVIDMODES-1].pnext = NULL;
392 //*((vmode_t**)pvidmodes) = &glidevidmodes[0];
393 //*numvidmodes = NUMGLIDEVIDMODES;
394 }
395
396 static int currentmode_width;
397 static int currentmode_height;
398
399 // Set3DfxMode
400 // switch to one of the video modes querried at initialization
Set3DfxMode(viddef_t * lvid,vmode_t * pcurrentmode)401 static int Set3DfxMode (viddef_t *lvid, vmode_t *pcurrentmode)
402 {
403 int iResolution;
404
405 // we stored the GR_RESOLUTION_XXX number into the 'misc' field
406 iResolution = pcurrentmode->misc;
407
408 DBG_Printf ("Set3DfxMode() iResolution(%d)\n", iResolution);
409
410 // this is normally not used (but we are actually double-buffering with glide)
411 lvid->u.numpages = 2;
412
413 // Change window attributes
414 SetWindowLong (lvid->WndParent, GWL_STYLE, WS_POPUP | WS_VISIBLE);
415 SetWindowPos(lvid->WndParent, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE |
416 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
417
418
419 //cleanup previous mode
420 if (grPreviousContext) {
421 // close the current graphics subsystem
422 DBG_Printf ("grSstWinClose()\n");
423 grSstWinClose (grPreviousContext);
424 }
425
426 // create Glide window
427 grPreviousContext = grSstWinOpen( (FxU32)lvid->WndParent,
428 iResolution,
429 GR_REFRESH_60Hz, //note: we could always use the higher refresh?
430 GR_COLORFORMAT_ABGR,
431 GR_ORIGIN_UPPER_LEFT,
432 2, 1 );
433
434 if ( !grPreviousContext ) {
435 DBG_Printf ("grSstWinOpen() FAILED\n");
436 return 0;
437 }
438
439 // for glide debug console
440 //tlSetScreen (pcurrentmode->width, pcurrentmode->height);
441 glide_initialized = true;
442 GR_ResetStates (lvid);
443
444 // force reload of patches because the memory is trashed while we change the screen
445 GR_InitMipmapCache();
446
447 lvid->buffer = NULL; //unless we use the software view
448 lvid->direct = NULL; //direct access to video memory, old DOS crap
449
450 currentmode_width = pcurrentmode->width;
451 currentmode_height = pcurrentmode->height;
452
453 // remember lvid here, to free the software buffer if we used it (software view)
454 viddef = lvid;
455
456 return 1;
457 }
458
459
460 // --------------------------------------------------------------------------
461 // Swap front and back buffers
462 // --------------------------------------------------------------------------
463 static int glide_console = 1;
HWRAPI(FinishUpdate)464 EXPORT void HWRAPI( FinishUpdate ) ( int waitvbl )
465 {
466 if (!grPreviousContext) {
467 DBG_Printf ("HWRAPI FinishUpdate() : display not set\n");
468 return;
469 }
470
471 /*
472 static int frame=0;
473 static int lasttic=0;
474 int tic,fps;
475
476 // draw silly stuff here
477 if (glide_console & 1)
478 tlPrintNumber (frame++);
479
480 if (glide_console & 1)
481 {
482 tic = dl.I_GetTime();
483 fps = TICRATE - (tic - lasttic) + 1;
484 lasttic = tic;
485 tlPrintNumber (fps);
486 }
487 */
488
489 //DBG_Printf ("HWRAPI FinishUpdate()\n");
490
491 // flip screen
492 grBufferSwap( waitvbl );
493 }
494
495
496 // --------------------------------------------------------------------------
497 //
498 // --------------------------------------------------------------------------
499 static unsigned long myPaletteData[256]; // 256 ARGB entries
500 //TODO: do the chroma key stuff out of here
HWRAPI(SetPalette)501 EXPORT void HWRAPI( SetPalette ) (RGBA_t* pal, RGBA_t *gamma)
502 {
503 int i;
504
505 if (!grPreviousContext) {
506 DBG_Printf ("HWRAPI SetPalette() : display not set\n");
507 return;
508 }
509
510 // create the palette in the format used for downloading to 3Dfx card
511 for (i=0; i<256; i++)
512 myPaletteData[i] = (pal[i].s.alpha << 24) |
513 (pal[i].s.red<<16) |
514 (pal[i].s.green<<8) |
515 pal[i].s.blue;
516
517 // make sure the chromakey color is always the same value
518 myPaletteData[HWR_PATCHES_CHROMAKEY_COLORINDEX] = HWR_PATCHES_CHROMAKEY_COLORVALUE;
519
520 grTexDownloadTable (GR_TEXTABLE_PALETTE, (void*)myPaletteData);
521 guGammaCorrectionRGB(gamma->s.red/127.0f,gamma->s.green/127.0f,gamma->s.blue/127.0f);
522 }
523
524
525 // **************************************************************************
526 //
527 // **************************************************************************
528
529 // store min/max w depth buffer values here, used to clear buffer
530 static FxU32 gr_wrange[2];
531
532
533 // --------------------------------------------------------------------------
534 // Do a full buffer clear including color / alpha / and Z buffers
535 // --------------------------------------------------------------------------
BufferClear(void)536 static void BufferClear (void)
537 {
538 if (!grPreviousContext) {
539 DBG_Printf ("BufferClear() : display not set\n");
540 return;
541 }
542 grDepthMask (FXTRUE);
543 grColorMask (FXTRUE,FXFALSE);
544 grBufferClear(0x00000000, 0, gr_wrange[1]);
545 }
546
547
548 //
549 // set initial state of 3d card settings
550 //
GR_ResetStates(viddef_t * lvid)551 static void GR_ResetStates (viddef_t *lvid)
552 {
553 DBG_Printf ("ResetStates()\n");
554
555 if (!grPreviousContext) {
556 DBG_Printf ("ResetStates() : display not set\n");
557 return;
558 }
559 //grSplash( 64, 64, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 0 ); //splash screen!
560
561 // get min/max w buffer range values
562 grGet (GR_WDEPTH_MIN_MAX, 8, gr_wrange);
563 grCoordinateSpace(GR_CLIP_COORDS);
564 grViewport((FxU32)0, (FxU32)0, (FxU32)lvid->width, (FxU32)lvid->height);
565
566 // don't work ! the only function that support this is drawpoly
567 // y=0 is in lower left corner, (not like in vga)
568 //grSstOrigin( GR_ORIGIN_LOWER_LEFT );
569
570
571 // initialize depth buffer type
572 grDepthRange( 0.0, 1.0 );
573 grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER);
574 grDepthBufferFunction( GR_CMP_LEQUAL );
575 grDepthMask( FXTRUE );
576 grColorMask ( FXTRUE, FXFALSE);
577
578 // my vertex format
579 grVertexLayout(GR_PARAM_XY , FIELD_OFFSET(vxtx3d_t,x) , GR_PARAM_ENABLE);
580 #ifdef _GLIDE_ARGB_
581 grVertexLayout(GR_PARAM_PARGB, FIELD_OFFSET(vxtx3d_t,argb), GR_PARAM_ENABLE);
582 #endif
583 //grVertexLayout(GR_PARAM_Q, 12, GR_PARAM_ENABLE);
584 grVertexLayout(GR_PARAM_W , FIELD_OFFSET(vxtx3d_t,z) , GR_PARAM_ENABLE);
585 grVertexLayout(GR_PARAM_ST0 , FIELD_OFFSET(vxtx3d_t,sow) , GR_PARAM_ENABLE); //s and t for tmu0
586
587 grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_LOCAL,
588 GR_COMBINE_FACTOR_NONE,
589 GR_COMBINE_FUNCTION_LOCAL,
590 GR_COMBINE_FACTOR_NONE,
591 FXFALSE, FXFALSE );
592
593 // no mipmaps based on depth
594 grTexMipMapMode (GR_TMU0, GR_MIPMAP_DISABLE, FXFALSE );
595
596 grConstantColorValue (0xffffffff);
597
598 grChromakeyValue(HWR_PATCHES_CHROMAKEY_COLORVALUE);
599
600 grAlphaTestReferenceValue( 0 );
601
602 // this set CurrentPolyFlags to the acctual configuration
603 CurrentPolyFlags = 0xffffffff;
604 SetBlend(0);
605
606 BufferClear();
607 MakeFogTable();
608 ReSetSpecialState();
609 }
610
611
612 // **************************************************************************
613 // 3DFX MEMORY CACHE MANAGEMENT
614 // **************************************************************************
615
616 #define TEXMEM_2MB_EDGE (1<<21)
617
618 static FxU32 gr_cachemin;
619 static FxU32 gr_cachemax;
620
621 static FxU32 gr_cachepos;
622 static Mipmap_t* gr_cachetail = NULL;
623 static Mipmap_t* gr_cachehead;
624 static Mipmap_t* lastmipmapset;
625
626 // --------------------------------------------------------------------------
627 // This must be done once only for all program execution
628 // --------------------------------------------------------------------------
629 Mipmap_t fakemipmap;
GR_ClearMipmapCache(void)630 static void GR_ClearMipmapCache (void)
631 {
632 while (gr_cachetail)
633 {
634 gr_cachetail->downloaded = false;
635 gr_cachehead = gr_cachetail;
636 gr_cachetail = gr_cachetail->nextmipmap;
637 gr_cachehead->nextmipmap = NULL;
638 }
639
640 // make a dummy first just for easy cache handling
641 fakemipmap.cachepos = gr_cachemin;
642 fakemipmap.mipmapSize = grTexCalcMemRequired(GR_LOD_LOG2_1,GR_LOD_LOG2_1,GR_ASPECT_LOG2_1x1,GR_TEXFMT_P_8);
643 fakemipmap.downloaded = true;
644 fakemipmap.nextmipmap = NULL;
645 lastmipmapset = NULL;
646
647 gr_cachetail = &fakemipmap;
648 gr_cachehead = &fakemipmap;
649 gr_cachepos = gr_cachetail->cachepos + fakemipmap.mipmapSize;
650
651 DBG_Printf ("Cache cleared\n");
652 }
653
HWRAPI(ClearMipMapCache)654 EXPORT void HWRAPI( ClearMipMapCache ) (void)
655 {
656 GR_ClearMipmapCache ();
657 }
658
GR_InitMipmapCache(void)659 static void GR_InitMipmapCache (void)
660 {
661 gr_cachemin = grTexMinAddress(GR_TMU0);
662 gr_cachemax = grTexMaxAddress(GR_TMU0);
663
664 // deboging...
665 // reduise memory so there will use more the legacy heap
666 //gr_cachemax = gr_cachemin + (256<<10);
667
668 if( gr_cachemax-gr_cachemin < 64<<10 )
669 I_ErrorGr("R_Glide : Only %d memory available for texture !\n",gr_cachemax-gr_cachemin);
670
671 GR_ClearMipmapCache();
672
673 DBG_Printf ("HWR_InitMipmapCache() : %d kb, from %x to %x\n"
674 "tmu2 : from %x to %x\n", (gr_cachemax-gr_cachemin)>>10,gr_cachemin,gr_cachemax,
675 grTexMinAddress(GR_TMU1),grTexMaxAddress(GR_TMU1));
676 }
677
678 static boolean possibleproblem=false;
679
GR_FlushMipmap()680 static void GR_FlushMipmap ()
681 {
682 if( !gr_cachetail)
683 return;
684 if(!gr_cachetail->downloaded)
685 DBG_Printf ("flush not dowloaded !!\n");
686 gr_cachetail->downloaded = false;
687 // should never happen
688 if (!gr_cachetail->nextmipmap)
689 {
690 if( possibleproblem )
691 I_ErrorGr ("This just CAN'T HAPPEN!!! So you think you're different eh ?");
692 possibleproblem=true;
693 DBG_Printf ("Never happen happen !!\n");
694 GR_ClearMipmapCache ();
695 }
696 else
697 {
698 // DBG_Printf ("flushing mipmap at position %d (%d bytes) tailpos=%d (%d byte)\n",gr_cachetail->cachepos,gr_cachetail->mipmapSize,gr_cachetail->nextmipmap->cachepos,gr_cachetail->nextmipmap->mipmapSize);
699 gr_cachetail->cachepos = 0;
700 gr_cachetail->mipmapSize = -1;
701 gr_cachetail = gr_cachetail->nextmipmap;
702 }
703 }
704
705 // --------------------------------------------------------------------------
706 // Download a 'surface' into the graphics card memory
707 // --------------------------------------------------------------------------
GR_DownloadMipmap(Mipmap_t * grMipmap)708 static void GR_DownloadMipmap (Mipmap_t* grMipmap)
709 {
710 FxU32 mipmapSize;
711
712 if (!grPreviousContext) {
713 DBG_Printf ("HWRAPI DownloadMipmap() : display not set\n");
714 return;
715 }
716
717 if ( !grMipmap->grInfo.data ) {
718 DBG_Printf ("HWRAPI DownloadMipmap() : No DATA !!!\n");
719 return;
720 }
721
722 mipmapSize = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &grMipmap->grInfo);
723
724 while (1)
725 {
726 // 3Dfx specs : a mipmap level can not straddle the 2MByte boundary
727 if (gr_cachetail->cachepos >= gr_cachepos)
728 {
729 if (gr_cachetail->cachepos >= gr_cachepos + mipmapSize)
730 if((gr_cachepos < TEXMEM_2MB_EDGE) && (gr_cachepos+mipmapSize > TEXMEM_2MB_EDGE))
731 {
732 if( gr_cachetail->cachepos >= TEXMEM_2MB_EDGE )
733 {
734 gr_cachepos = TEXMEM_2MB_EDGE;
735 continue;
736 }
737 // else FlushMipmap
738 }
739 else
740 break;
741 GR_FlushMipmap ();
742 }
743 else
744 {
745 if (gr_cachemax >= gr_cachepos + mipmapSize)
746 {
747 if((gr_cachepos < TEXMEM_2MB_EDGE) && (gr_cachepos+mipmapSize > TEXMEM_2MB_EDGE) && (gr_cachetail->cachepos < TEXMEM_2MB_EDGE))
748 gr_cachepos = TEXMEM_2MB_EDGE;
749 else
750 break;
751 }
752 else
753 // not enough space in the end of the buffer
754 gr_cachepos = gr_cachemin;
755 //dbg_printf (" cycle over\n");
756 }
757 //dbg_printf (" tailpos: %7d pos: %7d size: %7d free: %7d\n",
758 // gr_cachetail->cachepos, gr_cachepos, mipmapsize, freespace);
759 }
760 gr_cachehead->nextmipmap = grMipmap;
761
762 //DBG_Printf ("download %d byte at %d\n",mipmapSize,gr_cachepos);
763
764 grTexDownloadMipMap (GR_TMU0, gr_cachepos, GR_MIPMAPLEVELMASK_BOTH, &grMipmap->grInfo);
765 grMipmap->cachepos = gr_cachepos;
766 grMipmap->mipmapSize = mipmapSize;
767 grMipmap->downloaded = true;
768 grMipmap->nextmipmap = NULL; // the head don't have next
769
770 gr_cachepos += mipmapSize;
771
772 gr_cachehead = grMipmap; // the head is the last loaded texture (FIFO)
773 possibleproblem=false;
774 }
775
776
777 // ==========================================================================
778 // The mipmap becomes the current texture source
779 // ==========================================================================
HWRAPI(SetTexture)780 EXPORT void HWRAPI( SetTexture ) (Mipmap_t* grMipmap)
781 {
782 FBITFIELD xor;
783 if (!grPreviousContext) {
784 DBG_Printf ("HWRAPI SetTexture() : display not set\n");
785 return;
786 }
787
788 // don't set exactly the same mipmap
789 if( lastmipmapset == grMipmap )
790 return;
791
792 if (!grMipmap->downloaded)
793 GR_DownloadMipmap (grMipmap);
794
795 xor = grMipmap->tfflags ^ CurrentTextureFlags;
796 if(xor)
797 {
798 if(xor&TF_WRAPXY)
799 {
800 switch(grMipmap->tfflags & TF_WRAPXY)
801 {
802 case 0 :
803 grTexClampMode (GR_TMU0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
804 break;
805 case TF_WRAPX :
806 grTexClampMode (GR_TMU0, GR_TEXTURECLAMP_WRAP , GR_TEXTURECLAMP_CLAMP);
807 break;
808 case TF_WRAPY :
809 grTexClampMode (GR_TMU0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_WRAP);
810 break;
811 case TF_WRAPXY :
812 grTexClampMode (GR_TMU0, GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP);
813 break;
814 }
815 }
816 if( xor & TF_CHROMAKEYED )
817 {
818 if(grMipmap->tfflags & TF_CHROMAKEYED )
819 grChromakeyMode (GR_CHROMAKEY_ENABLE);
820 else
821 grChromakeyMode (GR_CHROMAKEY_DISABLE);
822 }
823 CurrentTextureFlags = grMipmap->tfflags;
824 }
825 grTexSource (GR_TMU0, grMipmap->cachepos, GR_MIPMAPLEVELMASK_BOTH, &grMipmap->grInfo);
826 lastmipmapset = grMipmap;
827 }
828
829
830 // -----------------+
831 // SetBlend : Set render mode
832 // -----------------+
833 // PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
834 // is it faster when pixels are discarded ?
HWRAPI(SetBlend)835 EXPORT void HWRAPI( SetBlend ) ( FBITFIELD PolyFlags )
836 {
837 FBITFIELD Xor;
838
839 if (!grPreviousContext) {
840 DBG_Printf ("HWRAPI SetBlend() : display not set\n");
841 return;
842 }
843
844 // Detect changes in the blending modes.
845 Xor = CurrentPolyFlags^PolyFlags;
846 if( !Xor )
847 return;
848
849 if( Xor&(PF_Blending) ) // if blending mode must be changed
850 {
851 switch(PolyFlags & PF_Blending) {
852 case PF_Translucent & PF_Blending:
853 grAlphaBlendFunction (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
854 GR_BLEND_ONE , GR_BLEND_ZERO );
855 break;
856 case PF_Masked & PF_Blending:
857 // no alpha blending
858 grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
859 break;
860 case PF_Additive & PF_Blending:
861 // blend destination for transparency, but no source for additive
862 grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ONE, GR_BLEND_ZERO);
863 break;
864 case PF_Environment & PF_Blending:
865 grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ONE_MINUS_SRC_ALPHA,
866 GR_BLEND_ONE, GR_BLEND_ZERO );
867 break;
868 case PF_Substractive & PF_Blending:
869 // not realy but what else ?
870 grAlphaBlendFunction (GR_BLEND_ZERO, GR_BLEND_ONE_MINUS_SRC_COLOR,
871 GR_BLEND_ONE , GR_BLEND_ZERO );
872 break;
873 default :
874 grAlphaBlendFunction (GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO );
875 break;
876 }
877 }
878 if( Xor & PF_NoAlphaTest)
879 {
880 if( PolyFlags & PF_NoAlphaTest)
881 // desable alpha testing
882 grAlphaTestFunction (GR_CMP_ALWAYS);
883 else
884 // discard 0 alpha pixels (holes in texture)
885 grAlphaTestFunction (GR_CMP_GREATER);
886 }
887 if( Xor & PF_Decal )
888 {
889 // work a little but not like opengl one :(
890 if( PolyFlags & PF_Decal )
891 grDepthBiasLevel( -1 );
892 else
893 grDepthBiasLevel( 0 );
894 }
895 if( Xor&(PF_Modulated | PF_NoTexture))
896 {
897 switch (PolyFlags & (PF_Modulated | PF_NoTexture)) {
898 case 0 :
899 // colour from texture is unchanged before blending
900 grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
901 GR_COMBINE_FACTOR_ONE,
902 GR_COMBINE_LOCAL_NONE,
903 GR_COMBINE_OTHER_TEXTURE,
904 FXFALSE );
905 // use alpha texture only
906 grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
907 GR_COMBINE_FACTOR_ONE,
908 GR_COMBINE_LOCAL_NONE,
909 GR_COMBINE_OTHER_TEXTURE,
910 FXFALSE );
911 break;
912 case PF_Modulated :
913 // mix texture colour with Surface->FlatColor (constant color)
914 grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, // factor * Color other
915 GR_COMBINE_FACTOR_LOCAL, // or local_alpha ???
916 GR_COMBINE_LOCAL_CONSTANT, // local is constant color
917 GR_COMBINE_OTHER_TEXTURE, // color from texture map
918 FXFALSE );
919 // use (alpha constant)*(alpha texture)
920 grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
921 GR_COMBINE_FACTOR_LOCAL,
922 GR_COMBINE_LOCAL_CONSTANT,
923 GR_COMBINE_OTHER_TEXTURE,
924 FXFALSE );
925 break;
926 case PF_NoTexture :
927 // no texture, no modulate what color use ?
928 // in opengl fab use white texture
929 grConstantColorValue(0xffFFffFF);
930 // no need break
931 case PF_Modulated | PF_NoTexture :
932 grColorCombine( GR_COMBINE_FUNCTION_LOCAL, // factor * Color other
933 GR_COMBINE_FACTOR_NONE,
934 GR_COMBINE_LOCAL_CONSTANT, // local is constant color
935 GR_COMBINE_OTHER_NONE, // color from texture map
936 FXFALSE);
937 // use (alpha constant)*(alpha texture)
938 grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL,
939 GR_COMBINE_FACTOR_NONE,
940 GR_COMBINE_LOCAL_CONSTANT,
941 GR_COMBINE_OTHER_NONE,
942 FXFALSE );
943 break;
944 }
945 }
946 if( Xor&PF_NoDepthTest )
947 {
948 if( PolyFlags & PF_NoDepthTest )
949 grDepthBufferFunction(GR_CMP_ALWAYS);
950 else
951 grDepthBufferFunction(GR_CMP_LEQUAL);
952 }
953 if( Xor & PF_Occlude )
954 {
955 // depth is tested but no writed
956 grDepthMask( (PolyFlags&PF_Occlude)!=0 );
957 }
958 if( Xor & PF_Invisible )
959 {
960 grColorMask( (PolyFlags&PF_Invisible)==0 , FXFALSE );
961 }
962
963 CurrentPolyFlags = PolyFlags;
964 }
965
966
967 // ==========================================================================
968 // Read a rectangle region of the truecolor framebuffer
969 // store pixels as 16bit 565 RGB
970 // ==========================================================================
HWRAPI(ReadRect)971 EXPORT void HWRAPI( ReadRect ) (int x, int y, int width, int height,
972 /*OUT*/ byte * buf, byte * bitpp )
973 {
974 if (!grPreviousContext) {
975 DBG_Printf ("HWRAPI ReadRect() : display not set\n");
976 return;
977 }
978 // dst_stride = width*2
979 grLfbReadRegion (GR_BUFFER_FRONTBUFFER,
980 x, y, width, height, width*2, (uint16_t*)buf);
981 *bitpp = 16; // return output
982 }
983
984
985 // ==========================================================================
986 // Defines the 2D hardware clipping window
987 // ==========================================================================
HWRAPI(GClipRect)988 EXPORT void HWRAPI( GClipRect ) (int minx, int miny, int maxx, int maxy, float nearclip)
989 {
990 if (!grPreviousContext) {
991 DBG_Printf ("HWRAPI GClipRect() : display not set\n");
992 return;
993 }
994 // BP: swap maxy and miny because wrong axe position
995 grClipWindow ( (FxU32)minx, (FxU32)miny, (FxU32)maxx, (FxU32)maxy);
996 }
997
998
999 // -----------------+
1000 // HWRAPI ClearBuffer
1001 // : Clear the color/alpha/depth buffer(s)
1002 // -----------------+
HWRAPI(ClearBuffer)1003 EXPORT void HWRAPI( ClearBuffer ) ( boolean ColorMask, boolean DepthMask,
1004 RGBA_float_t * ClearColor )
1005 {
1006 FBITFIELD polyflags;
1007
1008 if (!grPreviousContext) {
1009 DBG_Printf ("HWRAPI ClearBuffer() : display not set\n");
1010 return;
1011 }
1012
1013 grColorMask (ColorMask, FXFALSE);
1014
1015 polyflags = CurrentPolyFlags;
1016 // enable or desable z-buffer
1017 if( DepthMask )
1018 polyflags |= PF_Occlude;
1019 else
1020 polyflags &= ~PF_Occlude;
1021 // enable disable colorbuffer
1022 if( ColorMask )
1023 polyflags &= ~PF_Invisible;
1024 else
1025 polyflags |= PF_Invisible;
1026
1027 SetBlend( polyflags );
1028
1029 if( ClearColor )
1030 grBufferClear ((int)(ClearColor->alpha*255)<<24|
1031 (int)(ClearColor->red*255)<<16 |
1032 (int)(ClearColor->green*255)<<8 |
1033 (int)(ClearColor->blue)*255,
1034 0, gr_wrange[1]);
1035 else
1036 grBufferClear (0,0,gr_wrange[1]);
1037 }
1038
1039
1040 // -----------------+
1041 // HWRAPI Draw2DLine: Render a 2D line
1042 // -----------------+
HWRAPI(Draw2DLine)1043 EXPORT void HWRAPI( Draw2DLine ) ( v2d_t * v1, v2d_t * v2, RGBA_t Color )
1044 {
1045 vxtx3d_t a,b;
1046
1047 if (!grPreviousContext) {
1048 DBG_Printf ("HWRAPI DrawLine() : display not set\n");
1049 return;
1050 }
1051
1052 a.x = v1->x;
1053 a.y = v1->y;
1054 a.z = 1.0f;
1055
1056 b.x = v2->x;
1057 b.y = v2->y;
1058 b.z = 1.0f;
1059
1060 SetBlend( PF_Modulated|PF_NoTexture );
1061 grConstantColorValue(Color.rgba);
1062
1063 // damed, 3dfx have a bug in grDrawLine !
1064 //v1->y = -v1->y;
1065 //v2->y = -v2->y;
1066
1067 grDrawLine (&a, &b);
1068 }
1069
1070 // convert 4exp mantice 12 (w-buffer) to ieee float
1071 #define W16_TO_FLOAT(w) ((( ( ((int)w) & 0xF000) <<11) + 0x3F800000) | ((( ((int)w) & 0xFFF)<<11) + (1<<10)) )
1072 // convert ieee float to 4exp mantice 12 (w-buffer)
1073 #define FLOAT_TO_W16(f) ( ( ( ( (*(int*)&(f)) & 0x7F800000) - 0x3F800000)>>11 ) | ( ( *(int*)&(f) & 0x7FFFFF)>>11) )
1074 #define BYTEPERPIXEL 2
1075
1076 // test if center of corona is visible with the zbuffer (need raw acces to zbuffer)
ComputeCoronaAlpha(float * retscalef,vxtx3d_t * projVerts)1077 static boolean ComputeCoronaAlpha( float *retscalef, vxtx3d_t *projVerts )
1078 {
1079 #define NUMPIXELS 8
1080 unsigned short buf[NUMPIXELS][NUMPIXELS];
1081 float cx, cy, cz;
1082 float scalef = 0;
1083 int x,y;
1084 int i,j;
1085 unsigned short z;
1086
1087 // negative z, so not drawed !
1088 if( projVerts[0].z < 0)
1089 return false;
1090
1091 cx = (projVerts[0].x + projVerts[2].x) / 2.0f; // we should change the coronas' ...
1092 cy = (projVerts[0].y + projVerts[2].y) / 2.0f; // ... code so its only done once.
1093 cz = projVerts[0].z;
1094 //DBG_Printf("z : %f\n",cz);
1095
1096 // project (note y is -y in glide)
1097 x = (int)(currentmode_width * (1 + cx / cz) /2);
1098 if(x>=currentmode_width || x<0) return false;
1099 y = (int)(currentmode_height * (1 - cy / cz) /2);
1100 if(y>=currentmode_height || y<0) return false;
1101
1102 // get z buffer
1103 grLfbReadRegion( GR_BUFFER_AUXBUFFER,
1104 x-NUMPIXELS/2,y-NUMPIXELS/2,NUMPIXELS,NUMPIXELS,
1105 BYTEPERPIXEL*NUMPIXELS,buf);
1106
1107 // comparaison in float are the same as in int so use int compare
1108 // anyway 1 comparaison is better than 64 !
1109 z = FLOAT_TO_W16(cz);
1110 //DBG_Printf("z (w16) : %x\n",z);
1111 for (i=0; i<NUMPIXELS; i++)
1112 if(i+x>=0 && i+x<currentmode_width)
1113 for (j=0; j<NUMPIXELS; j++)
1114 {
1115 // BP: it seam like not perfect :( not find why ...
1116 #if 1
1117 if(z < buf[i][j] && j+y>=0 && j+y<currentmode_height)
1118 scalef += 1;
1119 //DBG_Printf("buf[%d][%d]=%x (w16) : %x scale %f\n",i,j,buf[i][j],z,scalef);
1120 #else
1121 float f;
1122 *(int *)&f = W16_TO_FLOAT(buf[i][j]);
1123 if(cz < f && j+y>=0 && j+y<currentmode_height)
1124 scalef += 1;
1125 //DBG_Printf("buf[%d][%d] : %f scale %f\n",i,j,f,scalef);
1126 #endif
1127
1128 }
1129
1130 scalef /= NUMPIXELS*NUMPIXELS;
1131
1132 #if 0 // see what pixel we are testing !
1133 // write white rectangle
1134 for(i=0;i<NUMPIXELS;i++)
1135 for(j=0;j<NUMPIXELS;j++)
1136 buf[i][j] = 0xffff;
1137 grLfbWriteRegion( GR_BUFFER_BACKBUFFER,
1138 x-NUMPIXELS/2,y-NUMPIXELS/2,GR_LFB_SRC_FMT_565,
1139 NUMPIXELS,NUMPIXELS,FXTRUE,
1140 BYTEPERPIXEL*NUMPIXELS,buf);
1141
1142 // can't be overwrited, z=0
1143 for(i=0;i<8;i++)
1144 for(j=0;j<8;j++)
1145 buf[i][j] = 0x0000;
1146 grLfbWriteRegion( GR_BUFFER_AUXBUFFER,
1147 x-NUMPIXELS/2,y-NUMPIXELS/2,GR_LFB_SRC_FMT_ZA16,
1148 NUMPIXELS,NUMPIXELS,FXTRUE,
1149 BYTEPERPIXEL*NUMPIXELS,buf);
1150
1151 #endif
1152 if (scalef < 0.05) // alpha too small so don't draw
1153 return false;
1154
1155 *retscalef = scalef;
1156 return true;
1157 }
1158
doTransform(vxtx3d_t * projVerts,FUINT nClipVerts)1159 static vxtx3d_t * doTransform(vxtx3d_t *projVerts,
1160 FUINT nClipVerts )
1161 {
1162 float tx,ty,tz;
1163 FUINT i;
1164 vxtx3d_t *p = tmp3Verts;
1165
1166 for(i=0;i<nClipVerts;i++,p++,projVerts++)
1167 {
1168
1169 *p = *projVerts; // copy texture coord too
1170 tx = projVerts->x - grTransform.x;
1171 ty = projVerts->y - grTransform.z;
1172 tz = projVerts->z - grTransform.y;
1173
1174 p->x = tx*sxsiny - tz * sxcosy;
1175 tz = tx*cosy + tz * siny;
1176
1177 p->y = ty * sycosx - tz * sysinx;
1178 p->z = ty * szsinx + tz * szcosx;
1179
1180 }
1181
1182 return tmp3Verts;
1183 }
1184
1185
1186 // ==========================================================================
1187 // Draw a triangulated polygon
1188 // ==========================================================================
HWRAPI(DrawPolygon)1189 EXPORT void HWRAPI( DrawPolygon ) ( FSurfaceInfo *pSurf,
1190 vxtx3d_t *projVerts,
1191 FUINT nClipVerts,
1192 FBITFIELD PolyFlags )
1193 {
1194 int i;
1195
1196 if (!grPreviousContext) {
1197 DBG_Printf ("HWRAPI DrawPolygon() : display not set\n");
1198 return;
1199 }
1200
1201 if (nClipVerts < 3)
1202 return;
1203
1204 SetBlend( PolyFlags );
1205
1206 projVerts = doTransform(projVerts, nClipVerts);
1207
1208 // this test is added for new coronas' code (without depth buffer)
1209 // I think I should do a separate function for drawing coronas, so it will be a little faster
1210 if (PolyFlags & PF_Corona) // check to see if we need to draw the corona
1211 {
1212 RGBA_t c;
1213 float scalef;
1214
1215 if( !ComputeCoronaAlpha(&scalef, projVerts) )
1216 return;
1217
1218 c.rgba = pSurf->FlatColor.rgba;
1219 c.s.alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona)
1220 grConstantColorValue(c.rgba);
1221 }
1222 else
1223 if( (CurrentPolyFlags & PF_Modulated) && pSurf )
1224 grConstantColorValue(pSurf->FlatColor.rgba);
1225
1226
1227 // cut polygone to the screen
1228 if( CurrentPolyFlags & PF_Clip )
1229 {
1230 if( CurrentPolyFlags & PF_NoZClip )
1231 {
1232 nClipVerts = ClipToFrustum (projVerts, tmp2Verts, nClipVerts );
1233
1234 if (nClipVerts<3)
1235 return;
1236 }
1237 else
1238 {
1239 // clip to near z plane
1240 nClipVerts = ClipZ (projVerts, tmpVerts, nClipVerts );
1241
1242 // -!!!- EXIT HERE if not enough points
1243 if (nClipVerts<3)
1244 return;
1245 nClipVerts = ClipToFrustum (tmpVerts, tmp2Verts, nClipVerts );
1246
1247 if (nClipVerts<3)
1248 return;
1249 }
1250
1251 projVerts=tmp2Verts;
1252 }
1253
1254 for(i=0; (FUINT)i < nClipVerts; i++)
1255 projVerts[i].y = -projVerts[i].y;
1256
1257 grDrawVertexArrayContiguous(GR_POLYGON, nClipVerts, projVerts, sizeof(vxtx3d_t));
1258 }
1259
1260 // ==========================================================================
1261 // Fog stuff
1262 // ==========================================================================
1263 static GrFog_t *fogtable =NULL;
1264 static float fogdensity=500.0f/(6000.0f);
1265 static int nFog=0;
1266
ComputeFogTable(void)1267 static void ComputeFogTable(void)
1268 {
1269 int i,j;
1270
1271 // happen because cvar execution of config.cfg
1272 if(!fogtable)
1273 {
1274 DBG_Printf ("Fog table size: nFog %d\n", nFog);
1275 return;
1276 }
1277
1278 // the table is an exponential fog table. It computes q from i using guFogTableIndexToW()
1279 // and then computes the fog table entries as fog[i]=(1�e -kw )�255 where k is a user-defined
1280 // constant, FOG_DENSITY.
1281 for (i=0; i<nFog; i++) {
1282 // remove (float) to see original doom bands
1283
1284 //j = (int) (exp((float)i*fogdensity)-1);
1285 //j = (int)((1 - exp((- fogdensity) * guFogTableIndexToW(i))) * 255);
1286 j = fogdensity * i*i;//guFogTableIndexToW(i);
1287 //DBG_Printf ("Fog[%d]= %d\n", i, j);
1288 // see something even if far
1289 //if (j > 128) j = 128;
1290 if (j > 200) j = 200;
1291 fogtable[i] = j;
1292
1293 }
1294 grFogTable (fogtable);
1295 }
1296
MakeFogTable(void)1297 static void MakeFogTable(void)
1298 {
1299 FreeFogTable();
1300
1301 grGet (GR_FOG_TABLE_ENTRIES, 4, &nFog);
1302
1303 fogtable = (GrFog_t*) malloc(nFog * sizeof(GrFog_t) );
1304
1305 if (!fogtable)
1306 I_ErrorGr ("could not allocate fog table\n");
1307 else
1308 DBG_Printf ("Fog table size: nFog %d\n", nFog);
1309
1310 ComputeFogTable();
1311 }
1312
FreeFogTable(void)1313 static void FreeFogTable(void)
1314 {
1315 if(fogtable)
1316 {
1317 free(fogtable);
1318 fogtable = NULL;
1319 }
1320 }
1321
1322
1323
1324 // ==========================================================================
1325 //
1326 // ==========================================================================
Glide_SetSpecialState(hwd_specialstate_e IdState,int value)1327 static Glide_SetSpecialState( hwd_specialstate_e IdState, int value )
1328 {
1329 switch (IdState)
1330 {
1331 case HWD_SET_FOG_MODE:
1332 if( value )
1333 grFogMode (GR_FOG_WITH_TABLE_ON_Q);
1334 else
1335 grFogMode (GR_FOG_DISABLE);
1336 break;
1337
1338 case HWD_SET_FOG_COLOR:
1339 grFogColorValue (value);
1340 break;
1341
1342 case HWD_SET_FOG_DENSITY:
1343 fogdensity = (float)value/(6000.0f);
1344 ComputeFogTable();
1345 break;
1346
1347 case HWD_SET_FOV:
1348 //can't be implementd until we find a "Liang-Barsky" algo for non 90�
1349 break;
1350
1351 case HWD_SET_POLYGON_SMOOTH:
1352 if( value )
1353 grEnable(GR_AA_ORDERED);
1354 else
1355 grDisable(GR_AA_ORDERED);
1356 break;
1357 case HWD_SET_TEXTUREFILTERMODE:
1358 switch (value) {
1359 case HWD_SET_TEXTUREFILTER_BILINEAR :
1360 case HWD_SET_TEXTUREFILTER_TRILINEAR:
1361 grTexFilterMode (GR_TMU0, GR_TEXTUREFILTER_BILINEAR,
1362 GR_TEXTUREFILTER_BILINEAR);
1363 break;
1364 case HWD_SET_TEXTUREFILTER_POINTSAMPLED :
1365 grTexFilterMode (GR_TMU0, GR_TEXTUREFILTER_POINT_SAMPLED,
1366 GR_TEXTUREFILTER_POINT_SAMPLED);
1367 break;
1368 case HWD_SET_TEXTUREFILTER_MIXED1 :
1369 grTexFilterMode (GR_TMU0, GR_TEXTUREFILTER_BILINEAR,
1370 GR_TEXTUREFILTER_POINT_SAMPLED);
1371 break;
1372 case HWD_SET_TEXTUREFILTER_MIXED2 :
1373 grTexFilterMode (GR_TMU0, GR_TEXTUREFILTER_POINT_SAMPLED,
1374 GR_TEXTUREFILTER_BILINEAR);
1375 break;
1376 }
1377 break;
1378 }
1379 }
1380
ReSetSpecialState(void)1381 static void ReSetSpecialState(void)
1382 {
1383 int i;
1384 for(i=0;i<HWD_NUMSTATE;i++)
1385 Glide_SetSpecialState(i, glide_state[i]);
1386 }
1387
HWRAPI(SetSpecialState)1388 EXPORT void HWRAPI( SetSpecialState ) (hwdspecialstate_t IdState, int value)
1389 {
1390 glide_state[IdState]=value;
1391 if( glide_initialized )
1392 Glide_SetSpecialState(IdState, value);
1393 }
1394
1395
1396 // -----------------+
1397 // HWRAPI DrawMD2 : Draw an MD2 model with glcommands
1398 // -----------------+
HWRAPI(DrawMD2)1399 EXPORT void HWRAPI( DrawMD2 ) (int *gl_cmd_buffer, md2_frame_t *frame,
1400 FTransform_t *pos, float scale)
1401 {
1402 }
1403
HWRAPI(SetTransform)1404 EXPORT void HWRAPI( SetTransform ) (FTransform_t *transform_parm)
1405 {
1406 float sinx, cosx;
1407
1408 if( transform_parm )
1409 grTransform = *transform_parm;
1410 else
1411 grTransform = defaulttransform;
1412
1413 sinx = sin( grTransform.anglex*2*PI/360);
1414 cosx = cos( grTransform.anglex*2*PI/360);
1415 siny = sin( grTransform.angley*2*PI/360);
1416 cosy = cos( grTransform.angley*2*PI/360);
1417
1418 szsinx = sinx * grTransform.scalez;
1419 szcosx = cosx * grTransform.scalez;
1420 sxsiny = siny * grTransform.scalex * (1/tan(grTransform.fovxangle*PI/360));
1421 sxcosy = cosy * grTransform.scalex * (1/tan(grTransform.fovxangle*PI/360));
1422 sysinx = sinx * grTransform.scaley * (1/tan(grTransform.fovyangle*PI/360));
1423 sycosx = cosx * grTransform.scaley * (1/tan(grTransform.fovyangle*PI/360));
1424 }
1425
1426
HWRAPI(GetTextureUsed)1427 EXPORT int HWRAPI( GetTextureUsed ) (void)
1428 {
1429 FTextureInfo* tmp = gr_cachehead;
1430 int res = 0;
1431
1432 for(tmp=gr_cachetail;tmp;tmp = tmp->nextmipmap)
1433 res += tmp->mipmapSize;
1434 return res;
1435 }
1436
HWRAPI(GetRenderVersion)1437 EXPORT int HWRAPI( GetRenderVersion ) (void)
1438 {
1439 return VERSION;
1440 }
1441