2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Graphics/GrD3D.cpp $
15 * Code for our Direct3D renderer
18 * Revision 1.3 2002/06/09 04:41:17 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:45 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:09 root
28 * 42 10/13/99 3:49p Jefff
29 * fixed unnumbered XSTRs
31 * 41 9/13/99 11:25p Dave
32 * Fixed problem with mode-switching and D3D movies.
34 * 40 9/13/99 11:30a Dave
35 * Added checkboxes and functionality for disabling PXO banners as well as
36 * disabling d3d zbuffer biasing.
38 * 39 9/10/99 11:53a Dave
39 * Shutdown graphics before sound to eliminate apparent lockups when
40 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
42 * 38 9/04/99 8:00p Dave
43 * Fixed up 1024 and 32 bit movie support.
45 * 37 8/30/99 5:01p Dave
46 * Made d3d do less state changing in the nebula. Use new chat server for
49 * 36 8/20/99 2:09p Dave
52 * 35 8/18/99 9:35a Dave
53 * Made d3d shutdown more stable.
55 * 34 8/11/99 3:30p Dave
56 * Fixed window focus problems.
58 * 33 8/04/99 5:36p Dave
59 * Make glide and D3D switch out properly.
61 * 32 8/02/99 6:25p Dave
62 * Fixed d3d screen save/popup problem.
64 * 31 7/30/99 7:01p Dave
65 * Dogfight escort gauge. Fixed up laser rendering in Glide.
67 * 30 7/29/99 10:47p Dave
68 * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
70 * 29 7/27/99 3:09p Dave
71 * Made g400 work. Whee.
73 * 28 7/24/99 4:19p Dave
74 * Fixed dumb code with briefing bitmaps. Made d3d zbuffer work much
75 * better. Made model code use zbuffer more intelligently.
77 * 27 7/16/99 1:49p Dave
78 * 8 bit aabitmaps. yay.
80 * 26 7/14/99 9:42a Dave
81 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
84 * 25 7/13/99 1:15p Dave
85 * 32 bit support. Whee!
87 * 24 6/29/99 10:35a Dave
88 * Interface polygon bitmaps! Whee!
90 * 23 6/03/99 6:37p Dave
91 * More TNT fun. Made perspective bitmaps more flexible.
93 * 22 5/05/99 9:02p Dave
94 * Fixed D3D aabitmap rendering. Spiffed up nebula effect a bit (added
95 * rotations, tweaked values, made bitmap selection more random). Fixed
96 * D3D beam weapon clipping problem. Added D3d frame dumping.
98 * 21 2/03/99 11:44a Dave
99 * Fixed d3d transparent textures.
101 * 20 1/24/99 11:36p Dave
102 * First full rev of beam weapons. Very customizable. Removed some bogus
103 * Int3()'s in low level net code.
105 * 19 1/15/99 11:29a Neilk
106 * Fixed D3D screen/texture pixel formatting problem.
108 * 18 1/11/99 6:21p Neilk
109 * Fixed broken D3D card fog-capability check.
111 * 17 1/06/99 2:24p Dave
112 * Stubs and release build fixes.
114 * 16 12/18/98 1:13a Dave
115 * Rough 1024x768 support for Direct3D. Proper detection and usage through
118 * 15 12/09/98 7:34p Dave
119 * Cleanup up nebula effect. Tweaked many values.
121 * 14 12/08/98 7:30p Dave
122 * Fixed broken compile.
124 * 13 12/08/98 7:03p Dave
125 * Much improved D3D fogging. Also put in vertex fogging for the cheesiest
128 * 12 12/08/98 2:47p Johnson
129 * Made D3D fogging use eye-relative depth instead of z-depth. Works like
130 * Glide w-buffer now.
132 * 11 12/08/98 9:36a Dave
133 * Almost done nebula effect for D3D. Looks 85% as good as Glide.
135 * 10 12/07/98 5:51p Dave
136 * Finally got d3d fog working! Now we just need to tweak values.
138 * 9 12/06/98 6:53p Dave
140 * 8 12/06/98 3:08p Dave
141 * Fixed grx_tmapper to handle pixel fog flag. First run fog support for
144 * 7 12/06/98 2:36p Dave
145 * Drastically improved nebula fogging.
147 * 6 12/01/98 10:25a Johnson
148 * Fixed direct3d texture coord/font problems.
150 * 5 11/30/98 1:07p Dave
151 * 16 bit conversion, first run.
153 * 4 11/11/98 5:37p Dave
154 * Checkin for multiplayer testing.
156 * 3 10/09/98 2:57p Dave
157 * Starting splitting up OS stuff.
159 * 2 10/07/98 10:52a Dave
162 * 1 10/07/98 10:49a Dave
164 * 110 6/13/98 6:01p Hoffoss
165 * Externalized all new (or forgot to be added) strings to all the code.
167 * 109 6/13/98 3:18p Hoffoss
168 * NOX()ed out a bunch of strings that shouldn't be translated.
170 * 108 5/24/98 9:41p John
171 * changed allender's previous fix to actually not draw the lines on
174 * 107 5/24/98 9:16p Allender
175 * put in previously non-NDEBUG code to draw bogus cursor when Gr_cursor
176 * wasn't defined. Caused d3d to crash before playing movies
178 * 106 5/22/98 10:29p John
179 * fixed some mode switching and line offset detection bugs.
181 * 105 5/22/98 1:11p John
182 * Added code to actually detect which offset a line needs
190 #include "grd3dinternal.h"
196 #include "floating.h"
198 #include "osregistry.h"
202 #include "grinternal.h"
204 #include "alphacolors.h"
205 #include "systemvars.h"
210 LPDIRECTDRAW lpDD1 = NULL;
211 LPDIRECTDRAW2 lpDD = NULL;
212 LPDIRECT3D2 lpD3D = NULL;
213 LPDIRECT3DDEVICE2 lpD3DDevice = NULL;
214 // LPDIRECT3DDEVICE lpD3DDeviceEB = NULL;
215 LPDIRECTDRAWSURFACE lpBackBuffer = NULL;
216 LPDIRECTDRAWSURFACE lpFrontBuffer = NULL;
217 LPDIRECTDRAWSURFACE lpZBuffer = NULL;
219 LPDIRECT3DVIEWPORT2 lpViewport;
221 DDPIXELFORMAT AlphaTextureFormat;
222 int Largest_alpha = 0;
223 DDPIXELFORMAT NonAlphaTextureFormat;
224 DDPIXELFORMAT NonAlphaTextureFormat_1555;
225 DDPIXELFORMAT NonAlphaTextureFormat_565;
227 DDPIXELFORMAT ScreenFormat;
229 static RECT D3D_cursor_clip_rect;
231 D3DDEVICEDESC D3DHWDevDesc, D3DHELDevDesc;
232 LPD3DDEVICEDESC lpDevDesc = NULL;
234 DDCAPS DD_driver_caps;
237 int D3D_texture_divider = 1;
241 char Device_init_error[512] = "";
243 // -1 == no fog, bad bad bad
246 int D3D_fog_mode = -1;
248 static int In_frame = 0;
254 int D3d_rendition_uvs = 0;
261 D3D_zbias = !D3D_zbias;
264 #define MAX_D2D_DEVICES 8
265 #define MAX_D3D_DEVICES 16
267 typedef struct d3d_device {
277 d3d_device D2D_devices[MAX_D2D_DEVICES];
278 d3d_device D3D_devices[MAX_D3D_DEVICES];
280 int Num_d2d_devices = 0;
281 int Num_d3d_devices = 0;
283 d3d_device *D3D_device;
285 void mprint_guid( LPGUID lpGuid )
289 mprintf(( "None\n" ));
292 for (i=0; i<sizeof(GUID); i++ ) {
293 mprintf(( "%x ", *ptr++ ));
295 mprintf(( "\n", *ptr++ ));
300 #define PUTD3DINSTRUCTION(op, sz, cnt, ptr) do { \
301 ((LPD3DINSTRUCTION) ptr)->bOpcode = op; \
302 ((LPD3DINSTRUCTION) ptr)->bSize = sz; \
303 ((LPD3DINSTRUCTION) ptr)->wCount = cnt; \
304 ptr = (void *)(((LPD3DINSTRUCTION) ptr) + 1); } while (0)
306 #define VERTEX_DATA(loc, cnt, ptr) do { \
307 if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DVERTEX) * (cnt)); \
308 ptr = (void *)(((LPD3DVERTEX) (ptr)) + (cnt)); } while (0)
310 // OP_MATRIX_MULTIPLY size: 4 (sizeof D3DINSTRUCTION)
311 #define OP_MATRIX_MULTIPLY(cnt, ptr) \
312 PUTD3DINSTRUCTION(D3DOP_MATRIXMULTIPLY, sizeof(D3DMATRIXMULTIPLY), cnt, ptr)
314 // MATRIX_MULTIPLY_DATA size: 12 (sizeof MATRIXMULTIPLY)
315 #define MATRIX_MULTIPLY_DATA(src1, src2, dest, ptr) do { \
316 ((LPD3DMATRIXMULTIPLY) ptr)->hSrcMatrix1 = src1; \
317 ((LPD3DMATRIXMULTIPLY) ptr)->hSrcMatrix2 = src2; \
318 ((LPD3DMATRIXMULTIPLY) ptr)->hDestMatrix = dest; \
319 ptr = (void *)(((LPD3DMATRIXMULTIPLY) ptr) + 1); } while (0)
321 // OP_STATE_LIGHT size: 4 (sizeof D3DINSTRUCTION)
322 #define OP_STATE_LIGHT(cnt, ptr) \
323 PUTD3DINSTRUCTION(D3DOP_STATELIGHT, sizeof(D3DSTATE), cnt, ptr)
325 // OP_STATE_TRANSFORM size: 4 (sizeof D3DINSTRUCTION)
326 #define OP_STATE_TRANSFORM(cnt, ptr) \
327 PUTD3DINSTRUCTION(D3DOP_STATETRANSFORM, sizeof(D3DSTATE), cnt, ptr)
329 // OP_STATE_RENDER size: 4 (sizeof D3DINSTRUCTION)
330 #define OP_STATE_RENDER(cnt, ptr) \
331 PUTD3DINSTRUCTION(D3DOP_STATERENDER, sizeof(D3DSTATE), cnt, ptr)
333 // STATE_DATA size: 8 (sizeof D3DSTATE)
334 #define STATE_DATA(type, arg, ptr) do { \
335 ((LPD3DSTATE) ptr)->drstRenderStateType = (D3DRENDERSTATETYPE)type; \
336 ((LPD3DSTATE) ptr)->dwArg[0] = arg; \
337 ptr = (void *)(((LPD3DSTATE) ptr) + 1); } while (0)
339 // OP_PROCESS_VERTICES size: 4 (sizeof D3DINSTRUCTION)
340 #define OP_PROCESS_VERTICES(cnt, ptr) \
341 PUTD3DINSTRUCTION(D3DOP_PROCESSVERTICES, sizeof(D3DPROCESSVERTICES), cnt, ptr)
343 // PROCESSVERTICES_DATA size: 16 (sizeof D3DPROCESSVERTICES)
344 #define PROCESSVERTICES_DATA(flgs, strt, cnt, ptr) do { \
345 ((LPD3DPROCESSVERTICES) ptr)->dwFlags = flgs; \
346 ((LPD3DPROCESSVERTICES) ptr)->wStart = strt; \
347 ((LPD3DPROCESSVERTICES) ptr)->wDest = strt; \
348 ((LPD3DPROCESSVERTICES) ptr)->dwCount = cnt; \
349 ((LPD3DPROCESSVERTICES) ptr)->dwReserved = 0; \
350 ptr = (void *)(((LPD3DPROCESSVERTICES) ptr) + 1); } while (0)
352 // OP_TRIANGLE_LIST size: 4 (sizeof D3DINSTRUCTION)
353 #define OP_TRIANGLE_LIST(cnt, ptr) \
354 PUTD3DINSTRUCTION(D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), cnt, ptr)
356 #define TRIANGLE_LIST_DATA(loc, count, ptr) do { \
357 if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DTRIANGLE) * (count)); \
358 ptr = (void *)(((LPD3DTRIANGLE) (ptr)) + (count)); } while (0)
360 // OP_LINE_LIST size: 4 (sizeof D3DINSTRUCTION)
361 #define OP_LINE_LIST(cnt, ptr) \
362 PUTD3DINSTRUCTION(D3DOP_LINE, sizeof(D3DLINE), cnt, ptr)
364 #define LINE_LIST_DATA(loc, count, ptr) do { \
365 if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DLINE) * (count)); \
366 ptr = (void *)(((LPD3DLINE) (ptr)) + (count)); } while (0)
368 // OP_POINT_LIST size: 8 (sizeof D3DINSTRUCTION + sizeof D3DPOINT)
369 #define OP_POINT_LIST(first, cnt, ptr) do { \
370 PUTD3DINSTRUCTION(D3DOP_POINT, sizeof(D3DPOINT), 1, ptr); \
371 ((LPD3DPOINT)(ptr))->wCount = cnt; \
372 ((LPD3DPOINT)(ptr))->wFirst = first; \
373 ptr = (void*)(((LPD3DPOINT)(ptr)) + 1); } while(0)
375 // OP_SPAN_LIST size: 8 (sizeof D3DINSTRUCTION + sizeof D3DSPAN)
376 #define OP_SPAN_LIST(first, cnt, ptr) \
377 PUTD3DINSTRUCTION(D3DOP_SPAN, sizeof(D3DSPAN), 1, ptr); \
378 ((LPD3DSPAN)(ptr))->wCount = cnt; \
379 ((LPD3DSPAN)(ptr))->wFirst = first; \
380 ptr = (void*)(((LPD3DSPAN)(ptr)) + 1); } while(0)
382 // OP_BRANCH_FORWARD size: 18 (sizeof D3DINSTRUCTION + sizeof D3DBRANCH)
383 #define OP_BRANCH_FORWARD(tmask, tvalue, tnegate, toffset, ptr) \
384 PUTD3DINSTRUCTION(D3DOP_BRANCHFORWARD, sizeof(D3DBRANCH), 1, ptr); \
385 ((LPD3DBRANCH) ptr)->dwMask = tmask; \
386 ((LPD3DBRANCH) ptr)->dwValue = tvalue; \
387 ((LPD3DBRANCH) ptr)->bNegate = tnegate; \
388 ((LPD3DBRANCH) ptr)->dwOffset = toffset; \
389 ptr = (void *)(((LPD3DBRANCH) (ptr)) + 1); } while (0)
391 // OP_SET_STATUS size: 20 (sizeof D3DINSTRUCTION + sizeof D3DSTATUS)
392 #define OP_SET_STATUS(flags, status, _x1, _y1, _x2, _y2, ptr) \
393 PUTD3DINSTRUCTION(D3DOP_SETSTATUS, sizeof(D3DSTATUS), 1, ptr); \
394 ((LPD3DSTATUS)(ptr))->dwFlags = flags; \
395 ((LPD3DSTATUS)(ptr))->dwStatus = status; \
396 ((LPD3DSTATUS)(ptr))->drExtent.x1 = _x1; \
397 ((LPD3DSTATUS)(ptr))->drExtent.y1 = _y1; \
398 ((LPD3DSTATUS)(ptr))->drExtent.x2 = _x2; \
399 ((LPD3DSTATUS)(ptr))->drExtent.y2 = _y2; \
400 ptr = (void *)(((LPD3DSTATUS) (ptr)) + 1); } while (0)
403 #define OP_NOP(ptr) \
404 PUTD3DINSTRUCTION(D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0, ptr)
406 #define OP_EXIT(ptr) \
407 PUTD3DINSTRUCTION(D3DOP_EXIT, 0, 0, ptr)
409 #define QWORD_ALIGNED(ptr) \
410 (!(0x00000007L & (ULONG)(ptr)))
412 #define D3D_MAX_VERTS 512
413 #define D3D_EXBUFFER_SIZE 65536
414 static int D3D_num_verts;
415 //static D3DTLVERTEX D3D_vertices[D3D_MAX_VERTS];
416 static D3DTLVERTEX *D3D_vertices;
417 //static ubyte D3D_exbuffer[D3D_EXBUFFER_SIZE];
418 static void *D3D_ex_ptr, *D3D_ex_end;
419 LPDIRECT3DEXECUTEBUFFER lpExBuf = NULL;
421 LPVOID lpBufStart, lpPointer, lpInsStart;
425 void gr_d3d_exb_init()
429 D3DEXECUTEBUFFERDESC debDesc;
435 Exb_size = D3D_EXBUFFER_SIZE + sizeof(D3DTLVERTEX)*D3D_MAX_VERTS;
437 // create a D3DEXECUTEBUFFERDESC
438 memset( &debDesc, 0, sizeof( debDesc ) );
439 debDesc.dwSize = sizeof( debDesc );
440 debDesc.dwFlags = D3DDEB_BUFSIZE;
441 debDesc.dwBufferSize = Exb_size;
444 ddrval = lpD3DDeviceEB->CreateExecuteBuffer( &debDesc, &lpExBuf, NULL );
445 if ( ddrval != DD_OK ) {
446 mprintf(( "GR_D3D_INIT: CreateExecuteBuffer failed. size=%d, '%s'\n", Exb_size, d3d_error_string(ddrval) ));
450 memset( &debDesc, 0, sizeof( debDesc ) );
451 debDesc.dwSize = sizeof( debDesc );
452 ddrval = lpExBuf->Lock( &debDesc );
453 if ( ddrval != DD_OK ) {
454 mprintf(( "Failed to lock the execute buffer!\n" ));
458 lpPointer = lpBufStart = lpInsStart = debDesc.lpData;
460 lpPointer = (void *)((uint)lpPointer+sizeof(D3DTLVERTEX)*D3D_MAX_VERTS);
461 lpInsStart = lpPointer;
463 OP_PROCESS_VERTICES( 1, lpPointer );
464 PROCESSVERTICES_DATA( D3DPROCESSVERTICES_COPY, 0, 1, lpPointer );
467 D3D_ex_ptr = lpPointer;
468 D3D_ex_end = (void *)((uint)lpBufStart + Exb_size - 1024);
469 D3D_vertices = (D3DTLVERTEX *)lpBufStart;
484 HRESULT set_wbuffer_planes(LPDIRECT3DDEVICE2 lpDev, float dvWNear, float dvWFar)
491 memset(&matWorld, 0, sizeof(matWorld));
492 memset(&matView, 0, sizeof(matWorld));
493 memset(&matProj, 0, sizeof(matWorld));
494 matWorld._11 = 1; matWorld._22 = 1; matWorld._33 = 1; matWorld._44 = 1;
495 matView._11 = 1; matView._22 = 1; matView._33 = 1; matView._44 = 1;
496 matProj._11 = 1; matProj._22 = 1; matProj._33 = 1; matProj._44 = 1;
498 res = lpDev->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );
500 res = lpDev->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );
505 matProj._44 = dvWNear; // not used
506 matProj._33 = dvWNear / (dvWFar - dvWNear) + 1;
508 res = lpDev->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );
514 dc_get_arg(ARG_FLOAT);
515 float n = Dc_arg_float;
516 dc_get_arg(ARG_FLOAT);
517 float f = Dc_arg_float;
518 set_wbuffer_planes(lpD3DDevice, n, f);
521 void gr_d3d_exb_flush(int end_of_frame)
525 D3DEXECUTEBUFFERDESC debDesc;
526 D3DEXECUTEDATA d3dExData;
532 if (!lpExBuf) return;
534 OP_EXIT( D3D_ex_ptr );
536 lpPointer = lpInsStart;
537 OP_PROCESS_VERTICES( 1, lpPointer );
538 PROCESSVERTICES_DATA( D3DPROCESSVERTICES_COPY, 0, D3D_num_verts, lpPointer );
540 ddrval = lpExBuf->Unlock();
541 if (ddrval != DD_OK ) {
542 mprintf(( "Failed to unlock the execute buffer!\n" ));
546 memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
547 d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
548 d3dExData.dwVertexCount = D3D_num_verts;
549 d3dExData.dwInstructionOffset = (ULONG)((char*)lpInsStart - (char*)lpBufStart);
550 d3dExData.dwInstructionLength = (ULONG)((char*)D3D_ex_ptr - (char*)lpInsStart);
552 // if (end_of_frame==0) {
553 // mprintf(( "Flushing execute buffer in frame, %d verts, %d data size!\n", D3D_num_verts, d3dExData.dwInstructionLength ));
554 // } else if (end_of_frame==2) {
555 // mprintf(( "Flushing execute buffer in frame, because of VRAM flush!\n" ));
558 ddrval = lpExBuf->SetExecuteData(&d3dExData);
559 if (ddrval != DD_OK ) {
560 mprintf(( "Failed to SetExecuteData!\n" ));
564 ddrval = lpD3DDeviceEB->Execute( lpExBuf, lpViewport, D3DEXECUTE_UNCLIPPED );
565 if (ddrval != DD_OK ) {
566 mprintf(( "Failed to Execute! nverts=%d\n", D3D_num_verts));
567 mprintf(( "(%s)\n", d3d_error_string(ddrval) ));
572 memset( &debDesc, 0, sizeof( debDesc ) );
573 debDesc.dwSize = sizeof( debDesc );
574 ddrval = lpExBuf->Lock( &debDesc );
575 if ( ddrval != DD_OK ) {
576 mprintf(( "Failed to lock the execute buffer!\n" ));
580 lpPointer = lpBufStart = lpInsStart = debDesc.lpData;
582 lpPointer = (void *)((uint)lpPointer+sizeof(D3DTLVERTEX)*D3D_MAX_VERTS);
583 lpInsStart = lpPointer;
585 OP_PROCESS_VERTICES( 1, lpPointer );
586 PROCESSVERTICES_DATA( D3DPROCESSVERTICES_COPY, 0, 1, lpPointer );
589 D3D_ex_ptr = lpPointer;
590 D3D_ex_end = (void *)((uint)lpBufStart + Exb_size - 1024);
591 D3D_vertices = (D3DTLVERTEX *)lpBufStart;
609 HRESULT d3d_SetRenderState( D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState )
612 return lpD3DDevice->SetRenderState(dwRenderStateType, dwRenderState );
614 if ( (uint)D3D_ex_ptr > (uint)D3D_ex_end ) {
617 OP_STATE_RENDER(1, D3D_ex_ptr);
618 STATE_DATA(dwRenderStateType, dwRenderState, D3D_ex_ptr);
624 HRESULT d3d_DrawPrimitive( D3DPRIMITIVETYPE dptPrimitiveType, D3DVERTEXTYPE dvtVertexType, LPVOID lpvVertices, DWORD dwVertexCount, DWORD dwFlags )
627 return lpD3DDevice->DrawPrimitive(dptPrimitiveType, dvtVertexType, lpvVertices, dwVertexCount, dwFlags );
630 switch( dptPrimitiveType ) {
632 case D3DPT_TRIANGLEFAN:
633 if ( dvtVertexType == D3DVT_TLVERTEX ) {
635 D3DTLVERTEX *Verts = (D3DTLVERTEX *)lpvVertices;
637 if ( D3D_num_verts + dwVertexCount > D3D_MAX_VERTS ) gr_d3d_exb_flush(0);
638 if ( (uint)D3D_ex_ptr > (uint)D3D_ex_end ) gr_d3d_exb_flush(0);
640 D3DTLVERTEX *src_v = &D3D_vertices[D3D_num_verts];
643 for (i=0; i<(int)dwVertexCount; i++ ) {
647 // triangle data must be QWORD aligned, so we need to make sure
648 // that the OP_TRIANGLE_LIST is unaligned! Note that you MUST have
649 // the braces {} around the OP_NOP since the macro in D3DMACS.H will
650 // fail if you remove them.
652 if ( QWORD_ALIGNED( D3D_ex_ptr ) ) {
653 OP_NOP( D3D_ex_ptr );
656 OP_TRIANGLE_LIST( unsigned short(dwVertexCount-2), D3D_ex_ptr );
658 LPD3DTRIANGLE tri = ( LPD3DTRIANGLE )D3D_ex_ptr;
660 for (i=0; i<(int)dwVertexCount-2; i++ ) {
661 tri->v1 = unsigned short(D3D_num_verts+0);
662 tri->v2 = unsigned short(D3D_num_verts+i+1);
663 tri->v3 = unsigned short(D3D_num_verts+i+2);
664 tri->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
668 D3D_ex_ptr = ( LPVOID )tri;
669 D3D_num_verts += (int)dwVertexCount;
674 if ( dvtVertexType == D3DVT_TLVERTEX ) {
676 D3DTLVERTEX *Verts = (D3DTLVERTEX *)lpvVertices;
678 if ( D3D_num_verts + dwVertexCount > D3D_MAX_VERTS ) gr_d3d_exb_flush(0);
679 if ( (uint)D3D_ex_ptr > (uint)D3D_ex_end ) gr_d3d_exb_flush(0);
681 D3DTLVERTEX *src_v = &D3D_vertices[D3D_num_verts];
684 for (i=0; i<(int)dwVertexCount; i++ ) {
688 // triangle data must be QWORD aligned, so we need to make sure
689 // that the OP_TRIANGLE_LIST is unaligned! Note that you MUST have
690 // the braces {} around the OP_NOP since the macro in D3DMACS.H will
691 // fail if you remove them.
693 if ( QWORD_ALIGNED( D3D_ex_ptr ) ) {
694 OP_NOP( D3D_ex_ptr );
697 ushort nlines = ushort(dwVertexCount/2);
699 OP_LINE_LIST( nlines, D3D_ex_ptr );
701 for (i=0; i<(int)nlines; i++ ) {
702 LPD3DLINE line = (LPD3DLINE )D3D_ex_ptr;
703 line->v1 = unsigned short(D3D_num_verts);
704 line->v2 = unsigned short(D3D_num_verts+1);
705 D3D_ex_ptr = (void *)(((LPD3DLINE)D3D_ex_ptr) + 1);
708 D3D_num_verts += (int)dwVertexCount;
716 volatile int D3D_running = 0;
717 volatile int D3D_activate = 0;
718 volatile int D3D_deactivate = 0;
720 void gr_d3d_activate(int active)
722 if ( !D3D_running ) {
725 mprintf(( "Direct3D activate: %d\n", active ));
727 HWND hwnd = (HWND)os_get_window();
733 ClipCursor(&D3D_cursor_clip_rect);
734 ShowWindow(hwnd,SW_RESTORE);
741 ShowWindow(hwnd,SW_MINIMIZE);
747 void d3d_start_frame()
751 if (!D3D_inited) return;
753 if ( In_frame < 0 || In_frame > 1 ) {
754 mprintf(( "Start frame error! (%d)\n", In_frame ));
757 if ( In_frame == 1 ) return;
759 // gr_d3d_clear_surface(lpBackBuffer, 0.0f, 0.0f, 0.0f);
763 ddrval = lpD3DDevice->BeginScene();
764 if (ddrval != D3D_OK ) {
765 //mprintf(( "Failed to begin scene!\n%s\n", d3d_error_string(ddrval) ));
773 void d3d_stop_frame()
777 if (!D3D_inited) return;
779 if ( In_frame < 0 || In_frame > 1 ) {
780 mprintf(( "Stop frame error! (%d)\n", In_frame ));
784 if ( In_frame == 0 ) return;
790 ddrval = lpD3DDevice->EndScene();
791 if (ddrval != D3D_OK ) {
792 //mprintf(( "Failed to end scene!\n%s\n", d3d_error_string(ddrval) ));
804 static void d3d_dump_format(DDPIXELFORMAT *pf)
808 for (r = 0, m = pf->dwRBitMask; !(m & 1); r++, m >>= 1);
809 for (r = 0; m & 1; r++, m >>= 1);
810 for (g = 0, m = pf->dwGBitMask; !(m & 1); g++, m >>= 1);
811 for (g = 0; m & 1; g++, m >>= 1);
812 for (b = 0, m = pf->dwBBitMask; !(m & 1); b++, m >>= 1);
813 for (b = 0; m & 1; b++, m >>= 1);
814 if ( pf->dwFlags & DDPF_ALPHAPIXELS ) {
815 for (a = 0, m = pf->dwRGBAlphaBitMask; !(m & 1); a++, m >>= 1);
816 for (a = 0; m & 1; a++, m >>= 1);
817 mprintf(( "ARGB, %d:%d:%d:%d\n", a, r, g, b ));
820 mprintf(( "RGB, %d:%d:%d\n", r, g, b ));
824 int D3D_found_1555_tex = 0;
825 int D3D_found_565_tex = 0;
826 static HRESULT WINAPI EnumTextureFormatsCallback(LPDDSURFACEDESC lpDDSD, LPVOID lpContext)
828 if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXEDTO8) {
829 mprintf(( "Palettized to an 8 bpp palette\n" ));
832 if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
833 mprintf(( "Palettized 8 bpp\n" ));
834 // TextureFormat = *lpDDSD;
835 // mprintf(( " ^-- And I'm using this one!\n" ));
836 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
837 mprintf(( "Palettized 4 bpp\n" ));
839 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2) {
840 mprintf(( "Palettized 2 bpp\n" ));
842 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1) {
843 mprintf(( "Palettized 1 bpp\n" ));
844 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_ALPHA ) {
845 mprintf(( "Alpha something or other\n" ));
847 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_YUV ) {
848 mprintf(( "YUV?\n" ));
850 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_ZBUFFER ) {
851 mprintf(( "ZBUFFER?\n" ));
853 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_COMPRESSED ) {
854 mprintf(( "Compressed?\n" ));
856 } else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
857 mprintf(( "FourCC?\n" ));
862 for (r = 0, m = lpDDSD->ddpfPixelFormat.dwRBitMask; !(m & 1) && (r < 32); r++, m >>= 1);
863 for (r = 0; m & 1; r++, m >>= 1);
864 for (g = 0, m = lpDDSD->ddpfPixelFormat.dwGBitMask; !(m & 1) && (g < 32); g++, m >>= 1);
865 for (g = 0; m & 1; g++, m >>= 1);
866 for (b = 0, m = lpDDSD->ddpfPixelFormat.dwBBitMask; !(m & 1) && (b < 32); b++, m >>= 1);
867 for (b = 0; m & 1; b++, m >>= 1);
868 if ( lpDDSD->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS ) {
869 for (a = 0, m = lpDDSD->ddpfPixelFormat.dwRGBAlphaBitMask; !(m & 1) && (a < 32); a++, m >>= 1);
870 for (a = 0; m & 1; a++, m >>= 1);
871 mprintf(( "ARGB, %d:%d:%d:%d\n", a, r, g, b ));
874 mprintf(( "RGB, %d:%d:%d\n", r, g, b ));
877 // if we found a nice 1555 texture format
878 if( (r == 5) && (g == 5) && (b == 5) && (a == 1)){
880 NonAlphaTextureFormat_1555 = lpDDSD->ddpfPixelFormat;
881 NonAlphaTextureFormat = lpDDSD->ddpfPixelFormat;
882 D3D_found_1555_tex = 1;
885 else if ( (r == 5) && (g == 6) && (b == 5) ){
886 NonAlphaTextureFormat_565 = lpDDSD->ddpfPixelFormat;
887 D3D_found_565_tex = 1;
889 // otherwise keep looking
890 else if(!D3D_found_1555_tex) {
891 //if ( (r==4) && (g==4) && (b==4) && (a==4) && (lpDDSD->ddpfPixelFormat.dwRGBBitCount==16) ) {
892 if ( (r>0) && (g>0) && (b>0) && (lpDDSD->ddpfPixelFormat.dwRGBBitCount==16) ) {
893 if ( r+g+b > Largest_rgb ) {
895 NonAlphaTextureFormat = lpDDSD->ddpfPixelFormat;
900 // HACK!!! Some 3dfx cards (Allender, Whiteside, Johnson) choose
901 // ARGB=8:3:3:2 as a texture format but when you go to create a surface
902 // in system RAM with this format, it fails, saying invalid surface format...
903 // So I'll just force 4:4:4:4 which seems to work on all cards I've seen.
904 if ( (a>0) && (a<8) && (lpDDSD->ddpfPixelFormat.dwRGBBitCount<=16) ) {
905 if ( a > Largest_alpha ) {
907 AlphaTextureFormat = lpDDSD->ddpfPixelFormat;
915 HRESULT WINAPI gr_d3d_enum( LPGUID lpGUID,
916 LPSTR lpDeviceDescription,
918 LPD3DDEVICEDESC lpHWDesc,
919 LPD3DDEVICEDESC lpHELDesc,
924 // mprintf(( "Found 3d device %s: %s\n", lpDeviceName, lpDeviceDescription ));
926 if ( lpHWDesc && lpHWDesc->dwFlags != 0 ) {
928 } //else if ( lpHELDesc ) {
932 d3d_device *d2d = (d3d_device *)lpContext;
933 d3d_device *d3d = (d3d_device *)&D3D_devices[Num_d3d_devices++];
936 memmove( &d3d->guid_3d, lpGUID, sizeof(GUID) );
937 d3d->pguid_3d = &d3d->guid_3d;
939 memset( &d3d->guid_3d, 0, sizeof(GUID) );
940 d3d->pguid_3d = NULL;
943 memmove( &d3d->guid_2d, &d2d->guid_2d, sizeof(GUID) );
944 if ( d2d->pguid_2d ) {
945 d3d->pguid_2d = &d3d->guid_2d;
947 d3d->pguid_2d = NULL;
950 //strcpy( d3d->name, lpDeviceName );
951 //strcat( d3d->name, " - " );
952 strcpy( d3d->name, NOX("Direct 3D - ") );
953 strcat( d3d->name, d2d->name );
954 //strcat( d3d->name, lpDeviceDescription );
957 return D3DENUMRET_OK;
960 BOOL WINAPI gr_d2d_enum( LPGUID lpGUID,
961 LPSTR lpDeviceDescription,
965 d3d_device *d2d = (d3d_device *)&D2D_devices[Num_d2d_devices++];
967 // mprintf(( "Found 2d device %s: %s\n", lpDeviceName, lpDeviceDescription ));
970 memmove( &d2d->guid_2d, lpGUID, sizeof(GUID) );
971 d2d->pguid_2d = &d2d->guid_2d;
973 memset( &d2d->guid_2d, 0, sizeof(GUID) );
974 d2d->pguid_2d = NULL;
977 strcpy( d2d->name, lpDeviceDescription );
978 // strcat( d2d->name, lpDeviceName );
980 return D3DENUMRET_OK;
983 d3d_device *d3d_poll_devices()
991 ddrval = DirectDrawEnumerate( gr_d2d_enum, NULL );
992 if ( ddrval != DD_OK ) {
993 mprintf(( "GR_D3D_INIT: DirectDrawEnumerate failed.\n" ));
997 for ( i=0; i<Num_d2d_devices; i++) {
998 d3d_device *d2d = (d3d_device *)&D2D_devices[i];
1000 ddrval = DirectDrawCreate( d2d->pguid_2d, &lpDD1, NULL );
1001 if ( ddrval != DD_OK ) {
1002 mprintf(( "GR_D3D_INIT: DirectDrawCreate failed.\n" ));
1006 ddrval = lpDD1->QueryInterface( IID_IDirect3D2, ( LPVOID *) &lpD3D );
1007 if ( ddrval != DD_OK ) {
1008 mprintf(( "GR_D3D_INIT: QueryInterface failed.\n" ));
1012 ddrval = lpD3D->EnumDevices(gr_d3d_enum, d2d );
1013 if ( ddrval != DD_OK ) {
1014 mprintf(( "WIN_DD32: D3D enum devices failed. (0x%x)\n", ddrval ));
1024 for ( i=0; i<Num_d3d_devices; i++) {
1025 mprintf(( "D3D Device %d: %s\n", i, D3D_devices[i].name ));
1026 //mprint_guid(D3D_devices[i].pguid_2d);
1029 if ( Num_d3d_devices <= 0 ) {
1030 mprintf(( "No D3D device found!\n" ));
1035 if ( Num_d3d_devices > 0 ) {
1036 //mprintf(( "More than one D3D device found!\n" ));
1038 char *name = os_config_read_string( NULL, "VideoCard", NULL );
1040 if ( name && (strlen(name)>0) ) {
1041 for ( i=0; i<Num_d3d_devices; i++) {
1042 if ( strstr( name, D3D_devices[i].name ) ) {
1043 mprintf(( "Using one that matched Direct3D registry value '%s'.\n", name ));
1044 return &D3D_devices[i];
1047 mprintf(( "WARNING!!!! Couldn't find one that matched Direct3D registry value '%s'.\n", name ));
1050 mprintf(( "But no Direct3D registry key or no match, so use the last one.\n" ));
1052 // Use the last device.
1053 return &D3D_devices[Num_d3d_devices-1];
1059 mprintf(( "Direct3D Polling failed.\n" ));
1064 LPDIRECTDRAW gr_d3d_get_dd()
1070 LPDIRECTDRAWSURFACE gr_d3d_get_dd_surface()
1072 return lpBackBuffer;
1075 void gr_d3d_clip_cursor(int active)
1078 ClipCursor(&D3D_cursor_clip_rect);
1084 // front buffer, backbuffer, d3d device, viewport
1085 int gr_d3d_create_rendering_objects(int clear)
1093 memset( &ddsd, 0, sizeof( ddsd ));
1095 ddsd.dwSize = sizeof( ddsd );
1099 ddsd.dwFlags = DDSD_CAPS;
1100 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
1104 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1105 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX;
1106 ddsd.dwBackBufferCount = 1;
1109 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1110 if ( ddrval != DD_OK ) {
1111 // mprintf(( "GR_D3D_INIT: CreateSurface (Front) failed.\n" ));
1112 strcpy(Device_init_error, "CreateSurface (Front) failed.");
1116 // create a clipper and a backbuffer in windowed mode
1118 // create a clipper for windowed mode
1119 LPDIRECTDRAWCLIPPER pcClipper;
1120 HRESULT hr = lpDD->CreateClipper(0, &pcClipper, NULL);
1125 // Associate the clipper with our window.
1126 pcClipper->SetHWnd(0, (HWND)os_get_window());
1127 lpFrontBuffer->SetClipper(pcClipper);
1128 pcClipper->Release();
1131 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1132 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1133 ddsd.dwWidth = gr_screen.max_w;
1134 ddsd.dwHeight = gr_screen.max_h;
1135 hr = lpDD->CreateSurface(&ddsd, &lpBackBuffer, NULL);
1137 strcpy(Device_init_error, "Windowed backbuffer create failed.");
1141 // backbuffer is already created for us in fullscreen mode
1143 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
1144 ddrval = lpFrontBuffer->GetAttachedSurface( &ddscaps, &lpBackBuffer );
1145 if ( ddrval != DD_OK ) {
1146 // mprintf(( "GR_D3D_INIT: GetAttachedSurface (Back) failed.\n" ));
1147 strcpy(Device_init_error, "GetAttachedSurface (Back) failed.");
1153 // Create a z-buffer and attach it to the backbuffer
1157 memset( &ddsd, 0, sizeof( ddsd ) );
1158 ddsd.dwSize = sizeof(ddsd);
1159 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
1160 ddsd.dwWidth = gr_screen.max_w;
1161 ddsd.dwHeight = gr_screen.max_h;
1162 ddsd.dwZBufferBitDepth = 16;
1164 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
1165 if (lpDD->CreateSurface(&ddsd, &lpZBuffer, NULL) != DD_OK) {
1166 // mprintf(( "GR_D3D_INIT: Create Zbuffer failed.\n" ));
1167 strcpy(Device_init_error, "Create Zbuffer failed.");
1171 if (lpBackBuffer->AddAttachedSurface(lpZBuffer) != DD_OK) {
1172 // mprintf(( "GR_D3D_INIT: Attach Zbuffer failed.\n" ));
1173 strcpy(Device_init_error, "Attach Zbuffer failed.");
1178 // blit all the buffers clear
1180 // Clear the surface
1182 ddBltFx.dwSize = sizeof(DDBLTFX);
1183 ddBltFx.dwFillColor = 0;
1184 lpFrontBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
1185 lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
1188 // Create the D3D device
1190 ddrval = lpD3D->CreateDevice( D3D_device->guid_3d, lpBackBuffer, &lpD3DDevice );
1191 if ( ddrval != DD_OK ) {
1192 // mprintf(( "GR_D3D_INIT: Create D3D Device2 failed. %s\n", d3d_error_string(ddrval) ));
1193 sprintf(Device_init_error, "Create D3D Device2 failed. %s\n", d3d_error_string(ddrval));
1197 // Create and add viewport
1198 ddrval = lpD3D->CreateViewport( &lpViewport, NULL );
1199 if ( ddrval != DD_OK ) {
1200 // mprintf(( "GR_D3D_INIT: CreateViewport failed.\n" ));
1201 strcpy(Device_init_error, "CreateViewport failed.");
1205 ddrval = lpD3DDevice->AddViewport( lpViewport );
1206 if ( ddrval != DD_OK ) {
1207 // mprintf(( "GR_D3D_INIT: AddViewport failed.\n" ));
1208 strcpy(Device_init_error, "CreateViewport failed.");
1213 // Setup the viewport for a reasonable viewing area
1214 D3DVIEWPORT viewdata;
1217 memset( &viewdata, 0, sizeof( viewdata ) );
1219 // Compensate for aspect ratio
1220 if ( gr_screen.max_w > gr_screen.max_h ){
1221 largest_side = gr_screen.max_w;
1223 largest_side = gr_screen.max_h;
1226 // this sets up W data so the fogging can work
1227 extern float z_mult;
1228 set_wbuffer_planes(lpD3DDevice, 0.0f, z_mult);
1230 viewdata.dwSize = sizeof( viewdata );
1231 viewdata.dwX = viewdata.dwY = 0;
1232 viewdata.dwWidth = gr_screen.max_w;
1233 viewdata.dwHeight = gr_screen.max_h;
1234 viewdata.dvScaleX = largest_side / 2.0F;
1235 viewdata.dvScaleY = largest_side / 2.0F;
1236 viewdata.dvMaxX = ( float ) ( viewdata.dwWidth / ( 2.0F * viewdata.dvScaleX ) );
1237 viewdata.dvMaxY = ( float ) ( viewdata.dwHeight / ( 2.0F * viewdata.dvScaleY ) );
1238 viewdata.dvMinZ = 0.0f;
1239 viewdata.dvMaxZ = 1.0f; // choose something appropriate here!
1241 ddrval = lpViewport->SetViewport( &viewdata );
1242 if ( ddrval != DD_OK ) {
1243 // mprintf(( "GR_D3D_INIT: SetViewport failed.\n" ));
1244 strcpy(Device_init_error, "SetViewport failed.");
1248 ddrval = lpD3DDevice->SetCurrentViewport(lpViewport );
1249 if ( ddrval != DD_OK ) {
1250 // mprintf(( "GR_D3D_INIT: SetCurrentViewport failed.\n" ));
1251 strcpy(Device_init_error, "SetCurrentViewport failed.");
1258 void gr_d3d_release_rendering_objects()
1261 lpViewport->Release();
1265 if ( lpD3DDevice ) {
1266 lpD3DDevice->Release();
1271 lpZBuffer->Release();
1276 lpBackBuffer->Release();
1277 lpBackBuffer = NULL;
1280 if (lpFrontBuffer) {
1281 lpFrontBuffer->Release();
1282 lpFrontBuffer = NULL;
1286 void gr_d3d_set_initial_render_state()
1288 d3d_SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE );
1289 d3d_SetRenderState(D3DRENDERSTATE_TEXTUREMIN, D3DFILTER_LINEAR );
1290 d3d_SetRenderState(D3DRENDERSTATE_TEXTUREMAG, D3DFILTER_LINEAR );
1291 d3d_SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD );
1292 d3d_SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE );
1293 d3d_SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE );
1296 void gr_d3d_init_device(int screen_width, int screen_height)
1301 if ( os_config_read_uint( NULL, NOX("D3DUseExecuteBuffers"), 0 )) {
1308 d3d_device *dd = d3d_poll_devices();
1311 // Error( LOCATION, "No Direct3D devices found!\n" );
1312 strcpy(Device_init_error, "No Direct3D devices found!");
1316 // Let things catch up....
1319 hwnd = (HWND)os_get_window();
1321 // mprintf(( "gr_d3d_init_device: No window handle.\n" ));
1322 strcpy(Device_init_error, "Could not get application window handle");
1328 SetWindowPos(hwnd, HWND_TOP, 0, 0, gr_screen.max_w, gr_screen.max_h, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_DRAWFRAME);
1329 SetForegroundWindow(hwnd);
1330 SetActiveWindow(hwnd);
1332 D3D_cursor_clip_rect.left = 0;
1333 D3D_cursor_clip_rect.top = 0;
1334 D3D_cursor_clip_rect.right = gr_screen.max_w-1;
1335 D3D_cursor_clip_rect.bottom = gr_screen.max_h-1;
1337 // Prepare the window to go full screen
1339 mprintf(( "Window in debugging mode... mouse clicking may cause problems!\n" ));
1340 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1341 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1342 ShowWindow(hwnd, SW_SHOWNORMAL );
1344 SystemParametersInfo( SPI_GETWORKAREA, 0, &work_rect, 0 );
1345 SetWindowPos( hwnd, HWND_TOPMOST, work_rect.left, work_rect.top, gr_screen.max_w, gr_screen.max_h, 0 );
1346 SetActiveWindow(hwnd);
1347 SetForegroundWindow(hwnd);
1348 D3D_cursor_clip_rect.left = work_rect.left;
1349 D3D_cursor_clip_rect.top = work_rect.top;
1350 D3D_cursor_clip_rect.right = work_rect.left + gr_screen.max_w - 1;
1351 D3D_cursor_clip_rect.bottom = work_rect.top + gr_screen.max_h - 1;
1353 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1354 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1355 ShowWindow(hwnd, SW_SHOWNORMAL );
1356 // SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), 0 );
1357 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1358 SetActiveWindow(hwnd);
1359 SetForegroundWindow(hwnd);
1360 D3D_cursor_clip_rect.left = 0;
1361 D3D_cursor_clip_rect.top = 0;
1362 D3D_cursor_clip_rect.right = gr_screen.max_w-1;
1363 D3D_cursor_clip_rect.bottom = gr_screen.max_h-1;
1367 // active d3d device
1371 ddrval = DirectDrawCreate( dd->pguid_2d, &lpDD1, NULL );
1373 if ( ddrval != DD_OK ) {
1374 // mprintf(( "GR_D3D_INIT: DirectDrawCreate failed.\n" ));
1375 strcpy(Device_init_error, "DirectDrawCreate failed");
1379 ddrval = lpDD1->QueryInterface(IID_IDirectDraw2, (LPVOID *)&lpDD);
1380 if(ddrval != DD_OK) {
1381 // mprintf(( "GR_D3D_INIT: DirectDrawCreate2 failed.\n" ));
1382 strcpy(Device_init_error, "DirectDrawCreate2 failed");
1387 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
1389 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES );
1391 if ( ddrval != DD_OK ) {
1392 // mprintf(( "GR_D3D_INIT: SetCooperativeLevel EXCLUSIVE failed.\n" ));
1393 strcpy(Device_init_error, "SetCooperativeLevel EXCLUSIVE failed.");
1397 // Go to full screen!
1400 ddrval = lpDD->SetDisplayMode( screen_width, screen_height, gr_screen.bits_per_pixel, 0, 0 );
1402 if ( ddrval != DD_OK ) {
1403 // mprintf(( "GR_D3D_INIT: SetDisplayMode failed.\n" ));
1404 strcpy(Device_init_error, "SetDisplayMode failed.");
1409 gr_d3d_clip_cursor(1);
1411 ddrval = lpDD->QueryInterface( IID_IDirect3D2, ( LPVOID *) &lpD3D );
1412 if ( ddrval != DD_OK ) {
1413 // mprintf(( "GR_D3D_INIT: QueryInterface failed.\n" ));
1414 strcpy(Device_init_error, "QueryInterface failed.");
1418 // create all surfaces here
1419 if(!gr_d3d_create_rendering_objects(1)){
1424 extern void dd_get_shift_masks( DDSURFACEDESC *ddsd );
1426 memset( &ddsd, 0, sizeof( ddsd ) );
1427 ddsd.dwSize = sizeof(ddsd);
1428 lpBackBuffer->GetSurfaceDesc(&ddsd);
1429 dd_get_shift_masks( &ddsd );
1430 ScreenFormat = ddsd.ddpfPixelFormat;
1433 // if we're in windowed mode, fill in bits per pixel and bytes per pixel here
1435 gr_screen.bits_per_pixel = ScreenFormat.dwRGBBitCount;
1436 gr_screen.bytes_per_pixel = gr_screen.bits_per_pixel / 8;
1439 // Init values so we can choose the largest of each format
1442 D3D_found_1555_tex = 0;
1443 D3D_found_565_tex = 0;
1444 ddrval = lpD3DDevice->EnumTextureFormats(EnumTextureFormatsCallback, NULL );
1445 if ( ddrval != DD_OK ) {
1446 // mprintf(( "GR_D3D_INIT: EnumTextureFormats failed.\n" ));
1447 strcpy(Device_init_error, "EnumTextureFormats failed.");
1451 // if we found our ideal texture, set the global pixel format
1452 if(D3D_found_1555_tex){
1453 Bm_pixel_format = BM_PIXEL_FORMAT_ARGB_D3D;
1456 if ( Largest_alpha == 0 ) {
1458 MessageBox( NULL, XSTR("Alpha channel textures",620), XSTR("Missing Features",621), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
1461 if ( Largest_rgb == 0 ) {
1463 MessageBox( NULL, XSTR("16-bpp RGB textures",622), XSTR("Missing Features",621), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
1467 // setup texture pixel formats
1469 DDPIXELFORMAT *surface_desc;
1474 // Determine the red, green and blue masks' shift and scale.
1475 surface_desc = &NonAlphaTextureFormat;
1476 for (s = 0, m = surface_desc->dwRBitMask; !(m & 1); s++, m >>= 1);
1477 Gr_t_red.mask = surface_desc->dwRBitMask;
1479 Gr_t_red.scale = 255 / (surface_desc->dwRBitMask >> s);
1480 for (s = 0, m = surface_desc->dwGBitMask; !(m & 1); s++, m >>= 1);
1481 Gr_t_green.mask = surface_desc->dwRBitMask;
1482 Gr_t_green.shift = s;
1483 Gr_t_green.scale = 255 / (surface_desc->dwGBitMask >> s);
1484 for (s = 0, m = surface_desc->dwBBitMask; !(m & 1); s++, m >>= 1);
1485 Gr_t_blue.mask = surface_desc->dwRBitMask;
1486 Gr_t_blue.shift = s;
1487 Gr_t_blue.scale = 255 / (surface_desc->dwBBitMask >> s);
1488 Gr_t_alpha.mask = surface_desc->dwRGBAlphaBitMask;
1489 if ( surface_desc->dwFlags & DDPF_ALPHAPIXELS ) {
1490 for (s = 0, m = surface_desc->dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
1491 Gr_t_alpha.shift = s;
1492 Gr_t_alpha.scale = 255 / (surface_desc->dwRGBAlphaBitMask >> s);
1494 Gr_t_alpha.shift = 0;
1495 Gr_t_alpha.scale = 256;
1498 // Determine the red, green and blue masks' shift and scale.
1499 surface_desc = &AlphaTextureFormat;
1500 for (s = 0, m = surface_desc->dwRBitMask; !(m & 1); s++, m >>= 1);
1501 Gr_ta_red.mask = surface_desc->dwRBitMask;
1502 Gr_ta_red.shift = s;
1503 Gr_ta_red.scale = 255 / (surface_desc->dwRBitMask >> s);
1504 for (s = 0, m = surface_desc->dwGBitMask; !(m & 1); s++, m >>= 1);
1505 Gr_ta_green.mask = surface_desc->dwRBitMask;
1506 Gr_ta_green.shift = s;
1507 Gr_ta_green.scale = 255 / (surface_desc->dwGBitMask >> s);
1508 for (s = 0, m = surface_desc->dwBBitMask; !(m & 1); s++, m >>= 1);
1509 Gr_ta_blue.mask = surface_desc->dwRBitMask;
1510 Gr_ta_blue.shift = s;
1511 Gr_ta_blue.scale = 255 / (surface_desc->dwBBitMask >> s);
1512 Gr_ta_alpha.mask = surface_desc->dwRGBAlphaBitMask;
1513 if ( surface_desc->dwFlags & DDPF_ALPHAPIXELS ) {
1514 for (s = 0, m = surface_desc->dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
1515 Gr_ta_alpha.shift = s;
1516 Gr_ta_alpha.scale = 255 / (surface_desc->dwRGBAlphaBitMask >> s);
1518 Gr_ta_alpha.shift = 0;
1519 Gr_ta_alpha.scale = 256;
1523 mprintf(( "Alpha texture format = " ));
1524 d3d_dump_format(&AlphaTextureFormat);
1526 mprintf(( "Non-alpha texture format = " ));
1527 d3d_dump_format(&NonAlphaTextureFormat);
1529 mprintf(( "Screen format = " ));
1530 d3d_dump_format(&ScreenFormat);
1534 // gr_d3d_exb_init();
1536 memset( &D3DHWDevDesc, 0, sizeof( D3DHWDevDesc ) );
1537 D3DHWDevDesc.dwSize = sizeof(D3DHELDevDesc);
1539 memset( &D3DHELDevDesc, 0, sizeof( D3DHELDevDesc ) );
1540 D3DHELDevDesc.dwSize = sizeof(D3DHELDevDesc);
1542 ddrval = lpD3DDevice->GetCaps( &D3DHWDevDesc, &D3DHELDevDesc );
1543 if ( ddrval != DD_OK ) {
1544 mprintf(( "GR_D3D_INIT: 3DDevice->GetCaps failed.\n" ));
1547 lpDevDesc = &D3DHWDevDesc;
1549 lpDD->GetCaps(&DD_driver_caps,&DD_hel_caps);
1554 char missing_features[128*1024];
1556 strcpy( missing_features, XSTR("Your video card is missing the following features required by FreeSpace:\r\n\r\n",623) );
1559 if ( !(lpDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX) && !(lpDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)){
1560 strcat( missing_features, XSTR("Vertex fog or Table fog\r\n", 1499) );
1564 // Texture blending values
1565 if ( !(lpDevDesc->dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_MODULATE )) {
1566 strcat( missing_features, XSTR("Texture blending mode = Modulate\r\n", 624) );
1570 // Source blending values
1571 // if ( !(lpDevDesc->dpcTriCaps.dwSrcBlendCaps & D3DPBLENDCAPS_ONE) ) {
1572 // strcat( missing_features, "Source blending mode = ONE\r\n" );
1576 if ( !(lpDevDesc->dpcTriCaps.dwSrcBlendCaps & (D3DPBLENDCAPS_SRCALPHA|D3DPBLENDCAPS_BOTHSRCALPHA)) ) {
1577 strcat( missing_features, XSTR("Source blending mode = SRCALPHA or BOTHSRCALPHA\r\n", 625) );
1581 // if ( !(lpDevDesc->dpcTriCaps.dwDestBlendCaps & D3DPBLENDCAPS_ZERO ) ) {
1582 // strcat( missing_features, "Destination blending mode = ZERO\r\n" );
1586 // if ( !(lpDevDesc->dpcTriCaps.dwDestBlendCaps & D3DPBLENDCAPS_ONE ) ) {
1587 // strcat( missing_features, "Destination blending mode = ONE\r\n" );
1591 // Dest blending values
1592 if ( !(lpDevDesc->dpcTriCaps.dwDestBlendCaps & (D3DPBLENDCAPS_INVSRCALPHA|D3DPBLENDCAPS_BOTHINVSRCALPHA)) ) {
1593 strcat( missing_features, XSTR("Destination blending mode = INVSRCALPHA or BOTHINVSRCALPHA\r\n",626) );
1597 // If card is Mystique 220, turn off modulaalpha since it doesn't work...
1598 if ( Largest_alpha < 4 ) {
1599 lpDevDesc->dpcTriCaps.dwTextureBlendCaps &= (~D3DPTBLENDCAPS_MODULATEALPHA);
1604 MessageBox( NULL, missing_features, XSTR("Missing Features",621), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
1609 // fog info - for now we'll prefer table fog over vertex fog
1611 // if the user wants to force w-fog, maybe do it
1612 if(os_config_read_uint(NULL, "ForceWFOG", 0) && (lpDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)){
1615 // if the card does not have vertex fog, but has table fog, let it go
1616 if(!(lpDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX) && (lpDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)){
1622 DWORD dwFree, dwTotal;
1624 memset(&ddsCaps,0,sizeof(ddsCaps) );
1625 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1626 HRESULT ddrval = lpDD->GetAvailableVidMem(&ddsCaps, &dwTotal, &dwFree);
1627 if ( ddrval != DD_OK ) {
1628 mprintf(( "GR_D3D_INIT: GetAvailableVidMem failed.\n" ));
1632 if ( dwFree < (1024*1024) ) {
1634 MessageBox( NULL, XSTR("At least 1 MB of available video memory required.",627), XSTR("Missing Features",621), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
1639 // setup proper render state
1640 gr_d3d_set_initial_render_state();
1642 mprintf(( "Direct3D Initialized OK!\n" ));
1648 mprintf(( "Direct3D Initialization failed.\n" ));
1654 int Gr_d3d_mouse_saved = 0;
1655 int Gr_d3d_mouse_saved_x1 = 0;
1656 int Gr_d3d_mouse_saved_y1 = 0;
1657 int Gr_d3d_mouse_saved_x2 = 0;
1658 int Gr_d3d_mouse_saved_y2 = 0;
1659 int Gr_d3d_mouse_saved_w = 0;
1660 int Gr_d3d_mouse_saved_h = 0;
1661 #define MAX_SAVE_SIZE (32*32)
1662 ushort Gr_d3d_mouse_saved_data[MAX_SAVE_SIZE];
1664 // Clamps X between R1 and R2
1665 #define CLAMP(x,r1,r2) do { if ( (x) < (r1) ) (x) = (r1); else if ((x) > (r2)) (x) = (r2); } while(0)
1667 void gr_d3d_save_mouse_area(int x, int y, int w, int h )
1674 Gr_d3d_mouse_saved_x1 = x;
1675 Gr_d3d_mouse_saved_y1 = y;
1676 Gr_d3d_mouse_saved_x2 = x+w-1;
1677 Gr_d3d_mouse_saved_y2 = y+h-1;
1679 CLAMP(Gr_d3d_mouse_saved_x1, gr_screen.clip_left, gr_screen.clip_right );
1680 CLAMP(Gr_d3d_mouse_saved_x2, gr_screen.clip_left, gr_screen.clip_right );
1681 CLAMP(Gr_d3d_mouse_saved_y1, gr_screen.clip_top, gr_screen.clip_bottom );
1682 CLAMP(Gr_d3d_mouse_saved_y2, gr_screen.clip_top, gr_screen.clip_bottom );
1684 Gr_d3d_mouse_saved_w = Gr_d3d_mouse_saved_x2 - Gr_d3d_mouse_saved_x1 + 1;
1685 Gr_d3d_mouse_saved_h = Gr_d3d_mouse_saved_y2 - Gr_d3d_mouse_saved_y1 + 1;
1687 if ( Gr_d3d_mouse_saved_w < 1 ) return;
1688 if ( Gr_d3d_mouse_saved_h < 1 ) return;
1690 // Make sure we're not saving too much!
1691 SDL_assert( (Gr_d3d_mouse_saved_w*Gr_d3d_mouse_saved_h) <= MAX_SAVE_SIZE );
1696 memset( &ddsd, 0, sizeof( ddsd ) );
1697 ddsd.dwSize = sizeof( ddsd );
1699 ddrval = lpBackBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
1700 if ( ddrval == DD_OK ) {
1703 int short_per_row=ddsd.lPitch/2;
1705 rptr = (ushort *)ddsd.lpSurface;
1707 ushort *sptr, *dptr;
1709 dptr = Gr_d3d_mouse_saved_data;
1711 for (int i=0; i<Gr_d3d_mouse_saved_h; i++ ) {
1712 sptr = &rptr[(Gr_d3d_mouse_saved_y1+i)*short_per_row+Gr_d3d_mouse_saved_x1];
1714 for(int j=0; j<Gr_d3d_mouse_saved_w; j++ ) {
1720 lpBackBuffer->Unlock( NULL );
1722 Gr_d3d_mouse_saved = 1;
1725 mprintf(( "Couldn't get read-only lock to backbuffer for d3d mouse save\n" ));
1739 mouse_eval_deltas();
1741 Gr_d3d_mouse_saved = 0; // assume not saved
1743 if(!Gr_bitmap_poly){
1747 if ( mouse_is_visible() ) {
1749 mouse_get_pos( &mx, &my );
1751 gr_d3d_save_mouse_area(mx,my,32,32);
1752 if ( Gr_cursor == -1 ) {
1754 gr_set_color(255,255,255);
1755 gr_line( mx, my, mx+7, my + 7 );
1756 gr_line( mx, my, mx+5, my );
1757 gr_line( mx, my, mx, my+5 );
1760 gr_set_bitmap(Gr_cursor);
1761 gr_bitmap( mx, my );
1765 // Move stop frame before drawing cursor so cursor always appears on PowerVR.
1770 // ddrval = lpFrontBuffer->Flip( NULL, 1 );
1771 // if (ddrval != DD_OK ) {
1772 // mprintf(( "Fullscreen flip failed!\n" ));
1778 RECT rect, view_rect;
1779 GetClientRect( (HWND)os_get_window(), &rect);
1780 ClientToScreen( (HWND)os_get_window(), (POINT*)&rect.left );
1781 ClientToScreen( (HWND)os_get_window(), (POINT*)&rect.right );
1784 view_rect.right = gr_screen.max_w - 1;
1785 view_rect.bottom = gr_screen.max_h - 1;
1788 lpFrontBuffer->Blt(&rect, lpBackBuffer, &view_rect, 0, NULL );
1789 while(lpFrontBuffer->GetBltStatus(DDGBS_ISBLTDONE) != DD_OK){}
1792 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
1793 lpFrontBuffer->Restore();
1795 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
1796 lpBackBuffer->Restore();
1798 if ( lpZBuffer->IsLost() == DDERR_SURFACELOST ) {
1799 lpZBuffer->Restore();
1801 ddrval = lpFrontBuffer->Flip( NULL, DDFLIP_WAIT );
1802 if ( ddrval == DDERR_SURFACELOST ) {
1803 mprintf(( "Front surface lost... attempting to restore...\n" ));
1804 os_sleep(1000); // Wait a second
1812 } else if (ddrval != DD_OK ) {
1813 mprintf(( "Fullscreen flip failed!\n" ));
1819 int cnt = D3D_activate;
1823 gr_d3d_clip_cursor(1);
1826 cnt = D3D_deactivate;
1828 D3D_deactivate-=cnt;
1829 gr_d3d_clip_cursor(0);
1835 void gr_d3d_flip_cleanup()
1839 if (lpFrontBuffer->Flip( NULL, 1 ) != DD_OK ) {
1840 mprintf(( "Flip failed!\n" ));
1846 void gr_d3d_flip_window(uint _hdc, int x, int y, int w, int h )
1850 void gr_d3d_cleanup()
1852 if (!D3D_inited) return;
1854 d3d_tcache_cleanup();
1857 gr_d3d_release_rendering_objects();
1867 HWND hwnd = (HWND)os_get_window();
1869 ddrval = lpDD->RestoreDisplayMode();
1870 if( ddrval != DD_OK ) {
1871 mprintf(( "WIN_DD32: RestoreDisplayMode failed (0x%x)\n", ddrval ));
1874 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
1875 if( ddrval != DD_OK ) {
1876 mprintf(( "WIN_DD32: SetCooperativeLevel W Failed (0x%x)\n", ddrval ));
1879 // restore windows clipping rectangle
1882 // SetWindowLong( hwnd, GWL_STYLE, WS_CAPTION | WS_SYSMENU );
1883 // SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1884 // SetWindowPos( hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE );
1886 // gr_d3d_clip_cursor(0);
1898 void gr_d3d_fade_in(int instantaneous)
1902 void gr_d3d_fade_out(int instantaneous)
1908 void gr_d3d_force_windowed()
1910 HWND hwnd = (HWND)os_get_window();
1913 PostMessage(hwnd,WM_SYSKEYUP, 0x9, 0xa00f0001 );
1914 PostMessage(hwnd,WM_SYSKEYUP, 0x12, 0xc0380001 );
1916 gr_d3d_clip_cursor(0);
1918 // Wait a second to give things a change to settle down.
1922 static char *Gr_saved_screen = NULL;
1924 int gr_d3d_save_screen()
1928 if ( Gr_saved_screen ) {
1929 mprintf(( "Screen alread saved!\n" ));
1933 Gr_saved_screen = (char*)malloc( gr_screen.max_w * gr_screen.max_h * gr_screen.bytes_per_pixel );
1934 if (!Gr_saved_screen) {
1935 mprintf(( "Couldn't get memory for saved screen!\n" ));
1942 memset( &ddsd, 0, sizeof( ddsd ) );
1943 ddsd.dwSize = sizeof( ddsd );
1945 ddrval = lpFrontBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
1946 if ( ddrval != DD_OK ) {
1947 free(Gr_saved_screen);
1948 Gr_saved_screen = NULL;
1949 mprintf(( "Error locking surface for save_screen, %s\n", d3d_error_string(ddrval) ));
1955 uint *dptr = (uint*)ddsd.lpSurface;
1957 for (i=0; i<gr_screen.max_h; i++ ) {
1958 memcpy( &Gr_saved_screen[gr_screen.max_w * i * gr_screen.bytes_per_pixel], dptr, gr_screen.max_w * gr_screen.bytes_per_pixel );
1960 dptr = (uint *)((uint)dptr + ddsd.lPitch);
1963 ushort *dptr = (ushort *)ddsd.lpSurface;
1965 for (i=0; i<gr_screen.max_h; i++ ) {
1966 memcpy( &Gr_saved_screen[gr_screen.max_w * i * gr_screen.bytes_per_pixel], dptr, gr_screen.max_w * gr_screen.bytes_per_pixel );
1968 dptr = (ushort *)((uint)dptr + ddsd.lPitch);
1972 // Unlock the front buffer
1973 lpFrontBuffer->Unlock( NULL );
1975 if ( Gr_d3d_mouse_saved && !D3D_32bit) {
1976 ushort *sptr, *dptr;
1978 sptr = Gr_d3d_mouse_saved_data;
1980 for (int i=0; i<Gr_d3d_mouse_saved_h; i++ ) {
1981 dptr = &((ushort*)Gr_saved_screen)[(Gr_d3d_mouse_saved_y1 + i) * gr_screen.max_w + Gr_d3d_mouse_saved_x1];
1983 for(int j=0; j<Gr_d3d_mouse_saved_w; j++ ) {
1992 void gr_d3d_restore_screen(int id)
1996 if ( !Gr_saved_screen ) {
2004 memset( &ddsd, 0, sizeof( ddsd ) );
2005 ddsd.dwSize = sizeof( ddsd );
2007 ddrval = lpBackBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
2008 if ( ddrval != DD_OK ) {
2009 free(Gr_saved_screen);
2010 Gr_saved_screen = NULL;
2011 mprintf(( "Error locking surface for restore_screen, %s\n", d3d_error_string(ddrval) ));
2017 uint *dptr = (uint *)ddsd.lpSurface;
2019 for (i=0; i<gr_screen.max_h; i++ ) {
2020 memcpy( dptr, &Gr_saved_screen[gr_screen.max_w * i * gr_screen.bytes_per_pixel], gr_screen.max_w * gr_screen.bytes_per_pixel );
2022 dptr = (uint *)((uint)dptr + ddsd.lPitch);
2025 ushort *dptr = (ushort *)ddsd.lpSurface;
2027 for (i=0; i<gr_screen.max_h; i++ ) {
2028 memcpy( dptr, &Gr_saved_screen[gr_screen.max_w * i * gr_screen.bytes_per_pixel], gr_screen.max_w * gr_screen.bytes_per_pixel );
2030 dptr = (ushort *)((uint)dptr + ddsd.lPitch);
2034 // Unlock the back buffer
2035 lpBackBuffer->Unlock( NULL );
2038 void gr_d3d_free_screen(int id)
2040 if ( Gr_saved_screen ) {
2041 free( Gr_saved_screen );
2042 Gr_saved_screen = NULL;
2046 static int D3d_dump_frames = 0;
2047 static ubyte *D3d_dump_buffer = NULL;
2048 static int D3d_dump_frame_number = 0;
2049 static int D3d_dump_frame_count = 0;
2050 static int D3d_dump_frame_count_max = 0;
2051 static int D3d_dump_frame_size = 0;
2052 void gr_d3d_dump_frame_start(int first_frame, int frames_between_dumps)
2054 if ( D3d_dump_frames ) {
2055 Int3(); // We're already dumping frames. See John.
2058 D3d_dump_frames = 1;
2059 D3d_dump_frame_number = first_frame;
2060 D3d_dump_frame_count = 0;
2061 D3d_dump_frame_count_max = frames_between_dumps;
2062 D3d_dump_frame_size = gr_screen.max_w * gr_screen.max_h * 2;
2064 if ( !D3d_dump_buffer ) {
2065 int size = D3d_dump_frame_count_max * D3d_dump_frame_size;
2066 D3d_dump_buffer = (ubyte *)malloc(size);
2067 if ( !D3d_dump_buffer ) {
2068 Error(LOCATION, "Unable to malloc %d bytes for dump buffer", size );
2073 extern int tga_compress(char *out, char *in, int bytecount);
2074 void gr_d3d_flush_frame_dump()
2077 char filename[MAX_PATH_LEN], *movie_path = ".\\";
2078 ubyte outrow[1024*3*4];
2080 if ( gr_screen.max_w > 1024) {
2081 mprintf(( "Screen too wide for frame_dump\n" ));
2085 for (i = 0; i < D3d_dump_frame_count; i++) {
2087 int w = gr_screen.max_w;
2088 int h = gr_screen.max_h;
2090 sprintf(filename, NOX("%sfrm%04d.tga"), movie_path, D3d_dump_frame_number );
2091 D3d_dump_frame_number++;
2093 CFILE *f = cfopen(filename, "wb");
2095 // Write the TGA header
2096 cfwrite_ubyte( 0, f ); // IDLength;
2097 cfwrite_ubyte( 0, f ); // ColorMapType;
2098 cfwrite_ubyte( 10, f ); // ImageType; // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
2099 cfwrite_ushort( 0, f ); // CMapStart;
2100 cfwrite_ushort( 0, f ); // CMapLength;
2101 cfwrite_ubyte( 0, f ); // CMapDepth;
2102 cfwrite_ushort( 0, f ); // XOffset;
2103 cfwrite_ushort( 0, f ); // YOffset;
2104 cfwrite_ushort( (ushort)w, f ); // Width;
2105 cfwrite_ushort( (ushort)h, f ); // Height;
2106 cfwrite_ubyte( 24, f ); //PixelDepth;
2107 cfwrite_ubyte( 0, f ); //ImageDesc;
2109 // Go through and write our pixels
2111 ubyte *src_ptr = D3d_dump_buffer+(i*D3d_dump_frame_size)+(j*w*2);
2113 int len = tga_compress( (char *)outrow, (char *)src_ptr, w*sizeof(short) );
2115 cfwrite(outrow,len,1,f);
2122 D3d_dump_frame_count = 0;
2125 void gr_d3d_dump_frame_stop()
2128 if ( !D3d_dump_frames ) {
2129 Int3(); // We're not dumping frames. See John.
2133 // dump any remaining frames
2134 gr_d3d_flush_frame_dump();
2136 D3d_dump_frames = 0;
2137 if ( D3d_dump_buffer ) {
2138 free(D3d_dump_buffer);
2139 D3d_dump_buffer = NULL;
2143 void gr_d3d_dump_screen_hack( ushort * dst )
2147 LPDIRECTDRAWSURFACE surf = lpBackBuffer;
2151 // don't dump in 32 bit
2157 BM_SELECT_SCREEN_FORMAT();
2158 memset( &ddsd, 0, sizeof( ddsd ) );
2159 ddsd.dwSize = sizeof( ddsd );
2161 // try and lock the buffer
2162 ddrval = surf->Lock( NULL, &ddsd, DDLOCK_WAIT | DDLOCK_READONLY, NULL );
2163 if ( ddrval != DD_OK ) {
2164 mprintf(( "Error locking surface for get_region, %s\n", d3d_error_string(ddrval) ));
2169 ubyte *rptr = (ubyte*)ddsd.lpSurface;
2171 for (int i=0; i<gr_screen.max_h; i++ ) {
2172 sptr = (ushort*)&rptr[(gr_screen.max_h-i-1)*ddsd.lPitch];
2174 for(int j=0; j<gr_screen.max_w; j++ ) {
2177 bm_get_components((ubyte*)pixel, &r, &g, &b, NULL);
2179 // bash to 565, hackity hack
2181 pixel |= ((r >> 3) << 11);
2182 pixel |= ((g >> 2) << 5);
2189 // Unlock the buffer
2190 surf->Unlock( NULL );
2193 void gr_d3d_dump_frame()
2195 // A hacked function to dump the frame buffer contents
2196 gr_d3d_dump_screen_hack( (ushort *)(D3d_dump_buffer+(D3d_dump_frame_count*D3d_dump_frame_size)) );
2198 D3d_dump_frame_count++;
2200 if ( D3d_dump_frame_count == D3d_dump_frame_count_max ) {
2201 gr_d3d_flush_frame_dump();
2210 void gr_d3d_unlock()
2214 void gr_d3d_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
2218 SDL_assert((r >= 0) && (r < 256));
2219 SDL_assert((g >= 0) && (g < 256));
2220 SDL_assert((b >= 0) && (b < 256));
2223 if(fog_mode == GR_FOGMODE_NONE){
2224 // only change state if we need to
2225 if(gr_screen.current_fog_mode != fog_mode){
2226 d3d_SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE );
2228 gr_screen.current_fog_mode = fog_mode;
2230 // to prevent further state changes
2234 // maybe switch fogging on
2235 if(gr_screen.current_fog_mode != fog_mode){
2236 d3d_SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE);
2238 // if we're using table fog, enable table fogging
2239 if(D3D_fog_mode == 2){
2240 d3d_SetRenderState( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR );
2243 gr_screen.current_fog_mode = fog_mode;
2246 // is color changing?
2247 if( (gr_screen.current_fog_color.red != r) || (gr_screen.current_fog_color.green != g) || (gr_screen.current_fog_color.blue != b) ){
2249 gr_d3d_init_color( &gr_screen.current_fog_color, r, g, b );
2251 color = RGB_MAKE(r, g, b);
2252 d3d_SetRenderState(D3DRENDERSTATE_FOGCOLOR, color);
2256 if( (fog_near >= 0.0f) && (fog_far >= 0.0f) && ((fog_near != gr_screen.fog_near) || (fog_far != gr_screen.fog_far)) ){
2257 gr_screen.fog_near = fog_near;
2258 gr_screen.fog_far = fog_far;
2260 // only generate a new fog table if we have to (wfog/table fog mode)
2261 if(D3D_fog_mode == 2){
2262 d3d_SetRenderState( D3DRENDERSTATE_FOGTABLESTART, *((DWORD *)(&fog_near)));
2263 d3d_SetRenderState( D3DRENDERSTATE_FOGTABLEEND, *((DWORD *)(&fog_far)));
2268 void gr_d3d_set_gamma(float gamma)
2271 Gr_gamma_int = int(Gr_gamma*100);
2273 // Create the Gamma lookup table
2275 for (i=0; i<256; i++ ) {
2276 int v = fl2i(pow(i2fl(i)/255.0f, 1.0f/Gr_gamma)*255.0f);
2279 } else if ( v < 0 ) {
2282 Gr_gamma_lookup[i] = v;
2285 // Flush any existing textures
2289 void d3d_get_pixel(int x, int y, ubyte *pixel)
2294 memset( &ddsd, 0, sizeof( ddsd ) );
2295 ddsd.dwSize = sizeof( ddsd );
2297 ddrval = lpFrontBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
2298 if ( ddrval != DD_OK ) {
2299 mprintf(( "Error locking surface for uv test, %s\n", d3d_error_string(ddrval) ));
2303 ubyte *dptr = (ubyte *)((uint)ddsd.lpSurface + y*ddsd.lPitch + (x * gr_screen.bytes_per_pixel));
2304 memcpy(pixel, dptr, gr_screen.bytes_per_pixel);
2306 // Unlock the buffer
2307 lpFrontBuffer->Unlock( NULL );
2310 void gr_d3d_get_pixel(int x, int y, int *r, int *g, int *b)
2314 // resolution checking
2315 int gr_d3d_supports_res_interface(int res)
2320 int gr_d3d_supports_res_ingame(int res)
2325 void gr_d3d_set_cull(int cull)
2327 // switch culling on or off
2329 d3d_SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW );
2331 d3d_SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
2336 void gr_d3d_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
2339 gr_set_bitmap(bmap1);
2342 gr_set_bitmap(bmap2);
2348 void gr_d3d_filter_set(int filter)
2353 void gr_d3d_set_clear_color(int r, int g, int b)
2355 gr_init_color(&gr_screen.current_clear_color, r, g, b);
2358 // JAS: Need to turn optimizations off or Alan's machine, with 3dfx direct3d hangs...
2359 #pragma optimize("",off)
2361 void d3d_detect_texture_origin_32()
2369 mprintf(( "Detecting uv type...\n" ));
2372 gr_init_alphacolor(&ac,255,255,255,255);
2374 memset( data, 0, 32*32 );
2375 data[15*32+15] = 14;
2377 test_bmp = bm_create( 8, 32, 32, data, BMP_AABITMAP );
2379 mprintf(( "Trial #1\n" ));
2380 D3d_rendition_uvs = 0;
2383 gr_set_color_fast(&ac);
2384 gr_set_bitmap( test_bmp );
2385 gr_aabitmap_ex(0, 0, 32, 32, 15, 15);
2388 d3d_get_pixel(0, 0, (ubyte*)&pix1a);
2389 d3d_get_pixel(1, 1, (ubyte*)&pix1b);
2395 mprintf(( "Trial #2\n" ));
2396 D3d_rendition_uvs = 1;
2399 gr_set_color_fast(&ac);
2400 gr_set_bitmap( test_bmp );
2401 gr_aabitmap_ex(0, 0, 32, 32, 15, 15);
2404 d3d_get_pixel(0, 0, (ubyte*)&pix2a);
2405 d3d_get_pixel(1, 1, (ubyte*)&pix2b);
2411 bm_release(test_bmp);
2413 mprintf(( "Pixel 1 = %x , %x\n", pix1a, pix1b ));
2414 mprintf(( "Pixel 2 = %x , %x\n", pix2a, pix2b ));
2416 if ( (pix1b!=0) || (pix2b!=0) ) {
2417 D3d_rendition_uvs = 1;
2419 D3d_rendition_uvs = 0;
2422 mprintf(( "Rendition uvs: %d\n", D3d_rendition_uvs ));
2425 void d3d_detect_texture_origin_16()
2430 ushort pix1a, pix2a;
2431 ushort pix1b, pix2b;
2433 mprintf(( "Detecting uv type...\n" ));
2436 gr_init_alphacolor(&ac,255,255,255,255);
2438 memset( data, 0, 32*32 );
2439 data[15*32+15] = 14;
2441 test_bmp = bm_create( 8, 32, 32, data, BMP_AABITMAP );
2443 mprintf(( "Trial #1\n" ));
2444 D3d_rendition_uvs = 0;
2447 gr_set_color_fast(&ac);
2448 gr_set_bitmap( test_bmp );
2449 gr_aabitmap_ex(0, 0, 32, 32, 15, 15);
2452 d3d_get_pixel(0, 0, (ubyte*)&pix1a);
2453 d3d_get_pixel(1, 1, (ubyte*)&pix1b);
2459 mprintf(( "Trial #2\n" ));
2460 D3d_rendition_uvs = 1;
2463 gr_set_color_fast(&ac);
2464 gr_set_bitmap( test_bmp );
2465 gr_aabitmap_ex(0, 0, 32, 32, 15, 15);
2468 d3d_get_pixel(0, 0, (ubyte*)&pix2a);
2469 d3d_get_pixel(1, 1, (ubyte*)&pix2b);
2475 bm_release(test_bmp);
2477 mprintf(( "Pixel 1 = %x , %x\n", pix1a, pix1b ));
2478 mprintf(( "Pixel 2 = %x , %x\n", pix2a, pix2b ));
2480 if ( (pix1b!=0) || (pix2b!=0) ) {
2481 D3d_rendition_uvs = 1;
2483 D3d_rendition_uvs = 0;
2486 mprintf(( "Rendition uvs: %d\n", D3d_rendition_uvs ));
2489 void gr_d3d_get_region(int front, int w, int h, ubyte *data)
2493 LPDIRECTDRAWSURFACE surf = front ? lpFrontBuffer : lpBackBuffer;
2495 memset( &ddsd, 0, sizeof( ddsd ) );
2496 ddsd.dwSize = sizeof( ddsd );
2498 // try and lock the buffer
2499 ddrval = surf->Lock( NULL, &ddsd, DDLOCK_WAIT | DDLOCK_READONLY, NULL );
2500 if ( ddrval != DD_OK ) {
2501 mprintf(( "Error locking surface for get_region, %s\n", d3d_error_string(ddrval) ));
2507 ubyte *rptr = (ubyte*)ddsd.lpSurface;
2509 for (int i=0; i<h; i++ ) {
2510 sptr = (ubyte*)&rptr[ i * ddsd.lPitch ];
2512 // don't think we need to swizzle here ...
2513 for(int j=0; j<w; j++ ) {
2514 memcpy(dptr, sptr, gr_screen.bytes_per_pixel);
2515 dptr += gr_screen.bytes_per_pixel;
2516 sptr += gr_screen.bytes_per_pixel;
2520 // Unlock the buffer
2521 surf->Unlock( NULL );
2524 extern float D3D_line_offset;
2526 void d3d_detect_line_offset_32()
2532 mprintf(( "Detecting line offset...\n" ));
2535 gr_init_alphacolor(&ac, 255,255, 255, 255);
2537 mprintf(( "Trial #1\n" ));
2538 D3D_line_offset = 0.0f;
2541 gr_set_color_fast(&ac);
2545 d3d_get_pixel(0, 0, (ubyte*)&pix1a);
2546 d3d_get_pixel(1, 1, (ubyte*)&pix1b);
2552 mprintf(( "Trial #2\n" ));
2553 D3D_line_offset = 0.5f;
2556 gr_set_color_fast(&ac);
2560 d3d_get_pixel(0, 0, (ubyte*)&pix2a);
2561 d3d_get_pixel(1, 1, (ubyte*)&pix2b);
2567 mprintf(( "Pixel 1 = %x , %x\n", pix1a, pix1b ));
2568 mprintf(( "Pixel 2 = %x , %x\n", pix2a, pix2b ));
2570 if ( (pix1a!=0) && (pix2a==0) ) {
2571 D3D_line_offset = 0.0f;
2572 } else if ( (pix1a==0) && (pix2a!=0) ) {
2573 D3D_line_offset = 0.5f;
2575 D3D_line_offset = 0.0f;
2578 mprintf(( "Line offset: %.1f\n", D3D_line_offset ));
2581 void d3d_detect_line_offset_16()
2584 ushort pix1a, pix2a;
2585 ushort pix1b, pix2b;
2587 mprintf(( "Detecting line offset...\n" ));
2590 gr_init_alphacolor(&ac, 255,255, 255, 255);
2592 mprintf(( "Trial #1\n" ));
2593 D3D_line_offset = 0.0f;
2596 gr_set_color_fast(&ac);
2600 d3d_get_pixel(0, 0, (ubyte*)&pix1a);
2601 d3d_get_pixel(1, 1, (ubyte*)&pix1b);
2607 mprintf(( "Trial #2\n" ));
2608 D3D_line_offset = 0.5f;
2611 gr_set_color_fast(&ac);
2615 d3d_get_pixel(0, 0, (ubyte*)&pix2a);
2616 d3d_get_pixel(1, 1, (ubyte*)&pix2b);
2622 mprintf(( "Pixel 1 = %x , %x\n", pix1a, pix1b ));
2623 mprintf(( "Pixel 2 = %x , %x\n", pix2a, pix2b ));
2625 if ( (pix1a!=0) && (pix2a==0) ) {
2626 D3D_line_offset = 0.0f;
2627 } else if ( (pix1a==0) && (pix2a!=0) ) {
2628 D3D_line_offset = 0.5f;
2630 D3D_line_offset = 0.0f;
2633 mprintf(( "Line offset: %.1f\n", D3D_line_offset ));
2636 #pragma optimize("",on)
2640 D3D_enabled = 1; // Tell Freespace code that we're using Direct3D.
2643 SDL_assert( !D3D_inited );
2646 Bm_pixel_format = BM_PIXEL_FORMAT_D3D;
2649 D3D_window = Cmdline_window;
2653 gr_d3d_init_device(gr_screen.max_w, gr_screen.max_h);
2656 if(Cmdline_force_32bit){
2657 gr_screen.bits_per_pixel = 32;
2658 gr_screen.bytes_per_pixel = 4;
2659 gr_d3d_init_device(gr_screen.max_w, gr_screen.max_h);
2662 gr_screen.bits_per_pixel = 16;
2663 gr_screen.bytes_per_pixel = 2;
2664 gr_d3d_init_device(gr_screen.max_w, gr_screen.max_h);
2668 // determine 32 bit status
2669 D3D_32bit = gr_screen.bits_per_pixel == 32 ? 1 : 0;
2670 d3d_tcache_init(D3D_32bit ? 1 : 0);
2671 Gr_bitmap_poly = D3D_32bit ? 1 : 0;
2673 // did we initialize properly?
2679 if(os_config_read_uint(NULL, "DisableZbias", 0)){
2685 Gr_current_red = &Gr_red;
2686 Gr_current_blue = &Gr_blue;
2687 Gr_current_green = &Gr_green;
2688 Gr_current_alpha = &Gr_alpha;
2690 gr_screen.gf_flip = gr_d3d_flip;
2691 gr_screen.gf_flip_window = gr_d3d_flip_window;
2692 gr_screen.gf_set_clip = gr_d3d_set_clip;
2693 gr_screen.gf_reset_clip = gr_d3d_reset_clip;
2694 gr_screen.gf_set_font = grx_set_font;
2696 gr_screen.gf_get_color = gr_d3d_get_color;
2697 gr_screen.gf_init_color = gr_d3d_init_color;
2698 gr_screen.gf_set_color_fast = gr_d3d_set_color_fast;
2699 gr_screen.gf_set_color = gr_d3d_set_color;
2700 gr_screen.gf_init_color = gr_d3d_init_color;
2701 gr_screen.gf_init_alphacolor = gr_d3d_init_alphacolor;
2703 gr_screen.gf_set_bitmap = gr_d3d_set_bitmap;
2704 gr_screen.gf_create_shader = gr_d3d_create_shader;
2705 gr_screen.gf_set_shader = gr_d3d_set_shader;
2706 gr_screen.gf_clear = gr_d3d_clear;
2707 // gr_screen.gf_bitmap = gr_d3d_bitmap;
2708 // gr_screen.gf_bitmap_ex = gr_d3d_bitmap_ex;
2709 gr_screen.gf_aabitmap = gr_d3d_aabitmap;
2710 gr_screen.gf_aabitmap_ex = gr_d3d_aabitmap_ex;
2712 gr_screen.gf_rect = gr_d3d_rect;
2713 gr_screen.gf_shade = gr_d3d_shade;
2714 gr_screen.gf_string = gr_d3d_string;
2715 gr_screen.gf_circle = gr_d3d_circle;
2717 gr_screen.gf_line = gr_d3d_line;
2718 gr_screen.gf_aaline = gr_d3d_aaline;
2719 gr_screen.gf_pixel = gr_d3d_pixel;
2720 gr_screen.gf_scaler = gr_d3d_scaler;
2721 gr_screen.gf_aascaler = gr_d3d_aascaler;
2722 gr_screen.gf_tmapper = gr_d3d_tmapper;
2724 gr_screen.gf_gradient = gr_d3d_gradient;
2726 gr_screen.gf_set_palette = gr_d3d_set_palette;
2727 gr_screen.gf_print_screen = gr_d3d_print_screen;
2729 gr_screen.gf_fade_in = gr_d3d_fade_in;
2730 gr_screen.gf_fade_out = gr_d3d_fade_out;
2731 gr_screen.gf_flash = gr_d3d_flash;
2733 gr_screen.gf_zbuffer_get = gr_d3d_zbuffer_get;
2734 gr_screen.gf_zbuffer_set = gr_d3d_zbuffer_set;
2735 gr_screen.gf_zbuffer_clear = gr_d3d_zbuffer_clear;
2737 gr_screen.gf_save_screen = gr_d3d_save_screen;
2738 gr_screen.gf_restore_screen = gr_d3d_restore_screen;
2739 gr_screen.gf_free_screen = gr_d3d_free_screen;
2741 // Screen dumping stuff
2742 gr_screen.gf_dump_frame_start = gr_d3d_dump_frame_start;
2743 gr_screen.gf_dump_frame_stop = gr_d3d_dump_frame_stop;
2744 gr_screen.gf_dump_frame = gr_d3d_dump_frame;
2746 gr_screen.gf_set_gamma = gr_d3d_set_gamma;
2748 // Lock/unlock stuff
2749 gr_screen.gf_lock = gr_d3d_lock;
2750 gr_screen.gf_unlock = gr_d3d_unlock;
2753 gr_screen.gf_get_region = gr_d3d_get_region;
2756 gr_screen.gf_fog_set = gr_d3d_fog_set;
2759 gr_screen.gf_get_pixel = gr_d3d_get_pixel;
2762 gr_screen.gf_set_cull = gr_d3d_set_cull;
2765 gr_screen.gf_cross_fade = gr_d3d_cross_fade;
2768 gr_screen.gf_filter_set = gr_d3d_filter_set;
2771 gr_screen.gf_tcache_set = d3d_tcache_set;
2774 gr_screen.gf_set_clear_color = gr_d3d_set_clear_color;
2776 uint tmp = os_config_read_uint( NULL, "D3DTextureOrigin", 0xFFFF );
2778 if ( tmp != 0xFFFF ) {
2780 D3d_rendition_uvs = 1;
2782 D3d_rendition_uvs = 0;
2786 d3d_detect_texture_origin_32();
2788 d3d_detect_texture_origin_16();
2792 tmp = os_config_read_uint( NULL, "D3DLineOffset", 0xFFFF );
2794 if ( tmp != 0xFFFF ) {
2796 D3D_line_offset = 0.5f;
2798 D3D_line_offset = 0.0f;
2802 d3d_detect_line_offset_32();
2804 d3d_detect_line_offset_16();
2817 char* d3d_error_string(HRESULT error)
2822 return "No error.\0";
2823 case DDERR_ALREADYINITIALIZED:
2824 return "This object is already initialized.\0";
2825 case DDERR_BLTFASTCANTCLIP:
2826 return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
2827 case DDERR_CANNOTATTACHSURFACE:
2828 return "This surface can not be attached to the requested surface.\0";
2829 case DDERR_CANNOTDETACHSURFACE:
2830 return "This surface can not be detached from the requested surface.\0";
2831 case DDERR_CANTCREATEDC:
2832 return "Windows can not create any more DCs.\0";
2833 case DDERR_CANTDUPLICATE:
2834 return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
2835 case DDERR_CLIPPERISUSINGHWND:
2836 return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
2837 case DDERR_COLORKEYNOTSET:
2838 return "No src color key specified for this operation.\0";
2839 case DDERR_CURRENTLYNOTAVAIL:
2840 return "Support is currently not available.\0";
2841 case DDERR_DIRECTDRAWALREADYCREATED:
2842 return "A DirectDraw object representing this driver has already been created for this process.\0";
2843 case DDERR_EXCEPTION:
2844 return "An exception was encountered while performing the requested operation.\0";
2845 case DDERR_EXCLUSIVEMODEALREADYSET:
2846 return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
2848 return "Generic failure.\0";
2849 case DDERR_HEIGHTALIGN:
2850 return "Height of rectangle provided is not a multiple of reqd alignment.\0";
2851 case DDERR_HWNDALREADYSET:
2852 return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
2853 case DDERR_HWNDSUBCLASSED:
2854 return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
2855 case DDERR_IMPLICITLYCREATED:
2856 return "This surface can not be restored because it is an implicitly created surface.\0";
2857 case DDERR_INCOMPATIBLEPRIMARY:
2858 return "Unable to match primary surface creation request with existing primary surface.\0";
2859 case DDERR_INVALIDCAPS:
2860 return "One or more of the caps bits passed to the callback are incorrect.\0";
2861 case DDERR_INVALIDCLIPLIST:
2862 return "DirectDraw does not support the provided cliplist.\0";
2863 case DDERR_INVALIDDIRECTDRAWGUID:
2864 return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
2865 case DDERR_INVALIDMODE:
2866 return "DirectDraw does not support the requested mode.\0";
2867 case DDERR_INVALIDOBJECT:
2868 return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
2869 case DDERR_INVALIDPARAMS:
2870 return "One or more of the parameters passed to the function are incorrect.\0";
2871 case DDERR_INVALIDPIXELFORMAT:
2872 return "The pixel format was invalid as specified.\0";
2873 case DDERR_INVALIDPOSITION:
2874 return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
2875 case DDERR_INVALIDRECT:
2876 return "Rectangle provided was invalid.\0";
2877 case DDERR_LOCKEDSURFACES:
2878 return "Operation could not be carried out because one or more surfaces are locked.\0";
2880 return "There is no 3D present.\0";
2881 case DDERR_NOALPHAHW:
2882 return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
2884 return "No blitter hardware present.\0";
2885 case DDERR_NOCLIPLIST:
2886 return "No cliplist available.\0";
2887 case DDERR_NOCLIPPERATTACHED:
2888 return "No clipper object attached to surface object.\0";
2889 case DDERR_NOCOLORCONVHW:
2890 return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
2891 case DDERR_NOCOLORKEY:
2892 return "Surface doesn't currently have a color key\0";
2893 case DDERR_NOCOLORKEYHW:
2894 return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
2895 case DDERR_NOCOOPERATIVELEVELSET:
2896 return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
2898 return "No DC was ever created for this surface.\0";
2899 case DDERR_NODDROPSHW:
2900 return "No DirectDraw ROP hardware.\0";
2901 case DDERR_NODIRECTDRAWHW:
2902 return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
2903 case DDERR_NOEMULATION:
2904 return "Software emulation not available.\0";
2905 case DDERR_NOEXCLUSIVEMODE:
2906 return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
2907 case DDERR_NOFLIPHW:
2908 return "Flipping visible surfaces is not supported.\0";
2910 return "There is no GDI present.\0";
2912 return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
2913 case DDERR_NOMIRRORHW:
2914 return "Operation could not be carried out because there is no hardware present or available.\0";
2915 case DDERR_NOOVERLAYDEST:
2916 return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
2917 case DDERR_NOOVERLAYHW:
2918 return "Operation could not be carried out because there is no overlay hardware present or available.\0";
2919 case DDERR_NOPALETTEATTACHED:
2920 return "No palette object attached to this surface.\0";
2921 case DDERR_NOPALETTEHW:
2922 return "No hardware support for 16 or 256 color palettes.\0";
2923 case DDERR_NORASTEROPHW:
2924 return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
2925 case DDERR_NOROTATIONHW:
2926 return "Operation could not be carried out because there is no rotation hardware present or available.\0";
2927 case DDERR_NOSTRETCHHW:
2928 return "Operation could not be carried out because there is no hardware support for stretching.\0";
2929 case DDERR_NOT4BITCOLOR:
2930 return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
2931 case DDERR_NOT4BITCOLORINDEX:
2932 return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
2933 case DDERR_NOT8BITCOLOR:
2934 return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
2935 case DDERR_NOTAOVERLAYSURFACE:
2936 return "Returned when an overlay member is called for a non-overlay surface.\0";
2937 case DDERR_NOTEXTUREHW:
2938 return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
2939 case DDERR_NOTFLIPPABLE:
2940 return "An attempt has been made to flip a surface that is not flippable.\0";
2941 case DDERR_NOTFOUND:
2942 return "Requested item was not found.\0";
2943 case DDERR_NOTLOCKED:
2944 return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
2945 case DDERR_NOTPALETTIZED:
2946 return "The surface being used is not a palette-based surface.\0";
2947 case DDERR_NOVSYNCHW:
2948 return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
2949 case DDERR_NOZBUFFERHW:
2950 return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
2951 case DDERR_NOZOVERLAYHW:
2952 return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
2953 case DDERR_OUTOFCAPS:
2954 return "The hardware needed for the requested operation has already been allocated.\0";
2955 case DDERR_OUTOFMEMORY:
2956 return "DirectDraw does not have enough memory to perform the operation.\0";
2957 case DDERR_OUTOFVIDEOMEMORY:
2958 return "DirectDraw does not have enough memory to perform the operation.\0";
2959 case DDERR_OVERLAYCANTCLIP:
2960 return "The hardware does not support clipped overlays.\0";
2961 case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
2962 return "Can only have ony color key active at one time for overlays.\0";
2963 case DDERR_OVERLAYNOTVISIBLE:
2964 return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
2965 case DDERR_PALETTEBUSY:
2966 return "Access to this palette is being refused because the palette is already locked by another thread.\0";
2967 case DDERR_PRIMARYSURFACEALREADYEXISTS:
2968 return "This process already has created a primary surface.\0";
2969 case DDERR_REGIONTOOSMALL:
2970 return "Region passed to Clipper::GetClipList is too small.\0";
2971 case DDERR_SURFACEALREADYATTACHED:
2972 return "This surface is already attached to the surface it is being attached to.\0";
2973 case DDERR_SURFACEALREADYDEPENDENT:
2974 return "This surface is already a dependency of the surface it is being made a dependency of.\0";
2975 case DDERR_SURFACEBUSY:
2976 return "Access to this surface is being refused because the surface is already locked by another thread.\0";
2977 case DDERR_SURFACEISOBSCURED:
2978 return "Access to surface refused because the surface is obscured.\0";
2979 case DDERR_SURFACELOST:
2980 return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
2981 case DDERR_SURFACENOTATTACHED:
2982 return "The requested surface is not attached.\0";
2983 case DDERR_TOOBIGHEIGHT:
2984 return "Height requested by DirectDraw is too large.\0";
2985 case DDERR_TOOBIGSIZE:
2986 return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
2987 case DDERR_TOOBIGWIDTH:
2988 return "Width requested by DirectDraw is too large.\0";
2989 case DDERR_UNSUPPORTED:
2990 return "Action not supported.\0";
2991 case DDERR_UNSUPPORTEDFORMAT:
2992 return "FOURCC format requested is unsupported by DirectDraw.\0";
2993 case DDERR_UNSUPPORTEDMASK:
2994 return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
2995 case DDERR_VERTICALBLANKINPROGRESS:
2996 return "Vertical blank is in progress.\0";
2997 case DDERR_WASSTILLDRAWING:
2998 return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
2999 case DDERR_WRONGMODE:
3000 return "This surface can not be restored because it was created in a different mode.\0";
3002 return "Rectangle provided was not horizontally aligned on required boundary.\0";
3003 case D3DERR_BADMAJORVERSION:
3004 return "D3DERR_BADMAJORVERSION\0";
3005 case D3DERR_BADMINORVERSION:
3006 return "D3DERR_BADMINORVERSION\0";
3007 case D3DERR_EXECUTE_LOCKED:
3008 return "D3DERR_EXECUTE_LOCKED\0";
3009 case D3DERR_EXECUTE_NOT_LOCKED:
3010 return "D3DERR_EXECUTE_NOT_LOCKED\0";
3011 case D3DERR_EXECUTE_CREATE_FAILED:
3012 return "D3DERR_EXECUTE_CREATE_FAILED\0";
3013 case D3DERR_EXECUTE_DESTROY_FAILED:
3014 return "D3DERR_EXECUTE_DESTROY_FAILED\0";
3015 case D3DERR_EXECUTE_LOCK_FAILED:
3016 return "D3DERR_EXECUTE_LOCK_FAILED\0";
3017 case D3DERR_EXECUTE_UNLOCK_FAILED:
3018 return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
3019 case D3DERR_EXECUTE_FAILED:
3020 return "D3DERR_EXECUTE_FAILED\0";
3021 case D3DERR_EXECUTE_CLIPPED_FAILED:
3022 return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
3023 case D3DERR_TEXTURE_NO_SUPPORT:
3024 return "D3DERR_TEXTURE_NO_SUPPORT\0";
3025 case D3DERR_TEXTURE_NOT_LOCKED:
3026 return "D3DERR_TEXTURE_NOT_LOCKED\0";
3027 case D3DERR_TEXTURE_LOCKED:
3028 return "D3DERR_TEXTURELOCKED\0";
3029 case D3DERR_TEXTURE_CREATE_FAILED:
3030 return "D3DERR_TEXTURE_CREATE_FAILED\0";
3031 case D3DERR_TEXTURE_DESTROY_FAILED:
3032 return "D3DERR_TEXTURE_DESTROY_FAILED\0";
3033 case D3DERR_TEXTURE_LOCK_FAILED:
3034 return "D3DERR_TEXTURE_LOCK_FAILED\0";
3035 case D3DERR_TEXTURE_UNLOCK_FAILED:
3036 return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
3037 case D3DERR_TEXTURE_LOAD_FAILED:
3038 return "D3DERR_TEXTURE_LOAD_FAILED\0";
3039 case D3DERR_MATRIX_CREATE_FAILED:
3040 return "D3DERR_MATRIX_CREATE_FAILED\0";
3041 case D3DERR_MATRIX_DESTROY_FAILED:
3042 return "D3DERR_MATRIX_DESTROY_FAILED\0";
3043 case D3DERR_MATRIX_SETDATA_FAILED:
3044 return "D3DERR_MATRIX_SETDATA_FAILED\0";
3045 case D3DERR_SETVIEWPORTDATA_FAILED:
3046 return "D3DERR_SETVIEWPORTDATA_FAILED\0";
3047 case D3DERR_MATERIAL_CREATE_FAILED:
3048 return "D3DERR_MATERIAL_CREATE_FAILED\0";
3049 case D3DERR_MATERIAL_DESTROY_FAILED:
3050 return "D3DERR_MATERIAL_DESTROY_FAILED\0";
3051 case D3DERR_MATERIAL_SETDATA_FAILED:
3052 return "D3DERR_MATERIAL_SETDATA_FAILED\0";
3053 case D3DERR_LIGHT_SET_FAILED:
3054 return "D3DERR_LIGHT_SET_FAILED\0";
3056 return "Unrecognized error value.\0";