00001 /* 00002 * Copyright (c) 2007 by Tech Soft 3D, LLC. 00003 * The information contained herein is confidential and proprietary to 00004 * Tech Soft 3D, LLC., and considered a trade secret as defined under 00005 * civil and criminal statutes. Tech Soft 3D shall pursue its civil 00006 * and criminal remedies in the event of unauthorized use or misappropriation 00007 * of its trade secrets. Use of this information by anyone other than 00008 * authorized employees of Tech Soft 3D, LLC. is granted only under a 00009 * written non-disclosure agreement, expressly prescribing the scope and 00010 * manner of such use. 00011 * 00012 * $Id: dx9drive_8h-source.html,v 1.29 2008-03-10 07:09:28 stage Exp $ 00013 */ 00014 00015 00016 #ifndef __DX9DRIVE_H_DEFINED__ 00017 #define __DX9DRIVE_H_DEFINED__ 00018 00019 // SIL: This provides a lot of additional debugging information - e.g. inspecting surfaces, etc. 00020 #ifdef _DEBUG 00021 #define D3D_DEBUG_INFO 00022 #endif // _DEBUG 00023 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 /*D3D includes*/ 00027 #include <D3D9.h> 00028 #include <d3dx9math.h> 00029 00030 #include "adt.h" 00031 #include "database.h" 00032 #include "driver.h" 00033 #include "hpserror.h" 00034 #include "patterns.h" 00035 #include "phedron.h" 00036 #include "please.h" 00037 #include "searchh.h" 00038 #include "tandt.h" 00039 #include "hversion.h" 00040 #include "d3dutil.h" 00041 00042 /*forward declarations*/ 00043 class HD3DEnumeration; 00044 class HD3DSettings; 00045 class HDX9VertexBufferCache; 00046 class HDX9IndexBufferCache; 00047 class HDX9Shader; 00048 class H3DShaderID; 00049 class HDX9Post; 00050 00051 # ifndef WIN32_LEAN_AND_MEAN 00052 # define WIN32_LEAN_AND_MEAN 00053 # endif 00054 #include <windows.h> 00055 #include <Pbt.h> 00056 #include "msw.h" 00057 00058 #pragma warning(disable : 4710) 00059 00060 // SIL: Enable for PRT demo build 00061 //#define PRT_DEMO 00062 00063 // D3DPOOL_MANAGED or D3DPOOL_DEFAULT, 00064 #define HDX9_MANAGED_POOL 00065 #ifdef HDX9_MANAGED_POOL 00066 # define HDX9_POOL_TYPE D3DPOOL_MANAGED 00067 #else 00068 # define HDX9_POOL_TYPE D3DPOOL_DEFAULT 00069 #endif 00070 00071 00072 typedef struct dx9region_t { 00073 LPDIRECT3DSURFACE9 pCurrentSurface; // the current image/z region 00074 LPDIRECT3DSURFACE9 pSavedSurface; // saved image/z region 00075 HT_Int_Rectangle original_area; 00076 struct dx9region_t * next; // pointer to next region - required during Reset of device 00077 } dx9region; 00078 00079 00080 00081 D3DPRIMITIVETYPE d3dprimitive(H3DPRIMITIVETYPE type) 00082 { 00083 switch (type) { 00084 case H3DPT_POINTLIST: return D3DPT_POINTLIST; 00085 case H3DPT_LINELIST: return D3DPT_LINELIST; 00086 case H3DPT_LINESTRIP: return D3DPT_LINESTRIP; 00087 case H3DPT_TRIANGLELIST: return D3DPT_TRIANGLELIST; 00088 case H3DPT_TRIANGLESTRIP: return D3DPT_TRIANGLESTRIP; 00089 case H3DPT_TRIANGLEFAN: return D3DPT_TRIANGLEFAN; 00090 case H3DPT_FORCE_DWORD: return D3DPT_FORCE_DWORD; 00091 default: 00092 HE_ERROR(HEC_INTERNAL_ERROR, HEC_INTERNAL_ERROR, 00093 "Internal error: Unhandled primitive type mapping."); 00094 return D3DPT_FORCE_DWORD; 00095 } 00096 } 00097 00098 D3DBLEND d3dblend(H3DBLEND type) 00099 { 00100 switch (type) { 00101 case H3DBLEND_ZERO: return D3DBLEND_ZERO; 00102 case H3DBLEND_ONE: return D3DBLEND_ONE; 00103 case H3DBLEND_SRCCOLOR: return D3DBLEND_SRCCOLOR; 00104 case H3DBLEND_INVSRCCOLOR: return D3DBLEND_INVSRCCOLOR; 00105 case H3DBLEND_SRCALPHA: return D3DBLEND_SRCALPHA; 00106 case H3DBLEND_INVSRCALPHA: return D3DBLEND_INVSRCALPHA; 00107 case H3DBLEND_DESTALPHA: return D3DBLEND_DESTALPHA; 00108 case H3DBLEND_INVDESTALPHA: return D3DBLEND_INVDESTALPHA; 00109 case H3DBLEND_DESTCOLOR: return D3DBLEND_DESTCOLOR; 00110 case H3DBLEND_INVDESTCOLOR: return D3DBLEND_INVDESTCOLOR; 00111 case H3DBLEND_SRCALPHASAT: return D3DBLEND_SRCALPHASAT; 00112 case H3DBLEND_BOTHSRCALPHA: return D3DBLEND_BOTHSRCALPHA; 00113 case H3DBLEND_BOTHINVSRCALPHA: return D3DBLEND_BOTHINVSRCALPHA; 00114 case H3DBLEND_BLENDFACTOR: return D3DBLEND_BLENDFACTOR; 00115 case H3DBLEND_INVBLENDFACTOR: return D3DBLEND_INVBLENDFACTOR; 00116 /* H3D9Ex only -- */ 00117 #if !defined(H3D_DISABLE_9EX) 00118 //case H3DBLEND_SRCCOLOR2: return D3DBLEND_SRCCOLOR2; 00119 //case H3DBLEND_INVSRCCOLOR2: return D3DBLEND_INVSRCCOLOR2; 00120 #endif // !H3D_DISABLE_9EX 00121 /* -- H3D9Ex only */ 00122 case H3DBLEND_FORCE_DWORD: return D3DBLEND_FORCE_DWORD; 00123 default: 00124 HE_ERROR(HEC_INTERNAL_ERROR, HEC_INTERNAL_ERROR, 00125 "Internal error: Unhandled blend type mapping."); 00126 return D3DBLEND_FORCE_DWORD; 00127 } 00128 } 00129 00130 00131 00132 DWORD d3dclear(int flags) 00133 { 00134 DWORD clear_flags = 0; 00135 if (BIT(flags, H3DCLEAR_TARGET)) 00136 clear_flags |= D3DCLEAR_TARGET; 00137 if (BIT(flags, H3DCLEAR_ZBUFFER)) 00138 clear_flags |= D3DCLEAR_ZBUFFER; 00139 if (BIT(flags, H3DCLEAR_STENCIL)) 00140 clear_flags |= D3DCLEAR_STENCIL; 00141 return clear_flags; 00142 } 00143 00144 D3DSHADEMODE d3dshademode(H3DSHADEMODE type) 00145 { 00146 switch (type) { 00147 case H3DSHADE_FLAT: return D3DSHADE_FLAT; 00148 case H3DSHADE_GOURAUD: return D3DSHADE_GOURAUD; 00149 case H3DSHADE_PHONG: return D3DSHADE_PHONG; 00150 case H3DSHADE_FORCE_DWORD: return D3DSHADE_FORCE_DWORD; 00151 default: 00152 HE_ERROR(HEC_INTERNAL_ERROR, HEC_INTERNAL_ERROR, 00153 "Internal error: Unhandled shade mode mapping."); 00154 return D3DSHADE_FORCE_DWORD; 00155 } 00156 } 00157 00158 D3DCULL d3dcull(H3DCULL type) 00159 { 00160 switch (type) { 00161 case H3DCULL_NONE: return D3DCULL_NONE; 00162 case H3DCULL_CW: return D3DCULL_CW; 00163 case H3DCULL_CCW: return D3DCULL_CCW; 00164 case H3DCULL_FORCE_DWORD: return D3DCULL_FORCE_DWORD; 00165 default: 00166 HE_ERROR(HEC_INTERNAL_ERROR, HEC_INTERNAL_ERROR, 00167 "Internal error: Unhandled cull mode mapping."); 00168 return D3DCULL_FORCE_DWORD; 00169 } 00170 } 00171 00172 D3DFORMAT d3dformat(H3DFORMAT type) 00173 { 00174 switch (type) { 00175 case H3DFMT_INDEX16: return D3DFMT_INDEX16; 00176 case H3DFMT_INDEX32: return D3DFMT_INDEX32; 00177 default: 00178 HE_ERROR(HEC_INTERNAL_ERROR, HEC_INTERNAL_ERROR, 00179 "Internal error: Unhandled format mapping."); 00180 return D3DFMT_INDEX32; 00181 } 00182 } 00183 00184 D3DVIEWPORT9 d3dviewport(H3DVIEWPORT const *hvp) 00185 { 00186 D3DVIEWPORT9 vp; 00187 vp.X = hvp->X; 00188 vp.Y = hvp->Y; 00189 vp.Width = hvp->Width; 00190 vp.Height = hvp->Height; 00191 vp.MinZ = hvp->MinZ; 00192 vp.MaxZ = hvp->MaxZ; 00193 return vp; 00194 } 00195 00196 H3DVIEWPORT h3dviewport(D3DVIEWPORT9 const *vp) 00197 { 00198 H3DVIEWPORT hvp; 00199 hvp.X = vp->X; 00200 hvp.Y = vp->Y; 00201 hvp.Width = vp->Width; 00202 hvp.Height = vp->Height; 00203 hvp.MinZ = vp->MinZ; 00204 hvp.MaxZ = vp->MaxZ; 00205 return hvp; 00206 } 00207 /***************************************************************************** 00208 ***************************************************************************** 00209 H3DVertexFormat helper functions 00210 ***************************************************************************** 00211 *****************************************************************************/ 00212 00213 H3DVertexFormat fvf2vf(DWORD fvf) 00214 { 00215 H3DVertexFormat vf; 00216 int i = 0; 00217 00218 if (BIT(fvf, D3DFVF_XYZ)) vf.set_position(); 00219 if (BIT(fvf, D3DFVF_NORMAL)) vf.set_normals(); 00220 if (BIT(fvf, D3DFVF_DIFFUSE)) vf.set_diffuse(); 00221 if (BIT(fvf, D3DFVF_SPECULAR)) vf.set_specular(); 00222 vf.set_tex_count((fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); 00223 00224 for(i = 0; i < vf.get_tex_count(); i++) { 00225 int texcoordsize = fvf & D3DFVF_TEXCOORDSIZE1(i); 00226 00227 if (D3DFVF_TEXCOORDSIZE1(i) == texcoordsize) vf.set_tex_size(i,1); 00228 else if (D3DFVF_TEXCOORDSIZE2(i) == texcoordsize) vf.set_tex_size(i,2); 00229 else if (D3DFVF_TEXCOORDSIZE3(i) == texcoordsize) vf.set_tex_size(i,3); 00230 else if (D3DFVF_TEXCOORDSIZE4(i) == texcoordsize) vf.set_tex_size(i,4); 00231 } 00232 return vf; 00233 } 00234 00235 local DWORD vf2fvf(H3DVertexFormat vf) 00236 { 00237 int i = 0; 00238 DWORD fvf = 0; 00239 00240 if (vf.get_position()) fvf |= D3DFVF_XYZ; 00241 if (vf.get_normals()) fvf |= D3DFVF_NORMAL; 00242 if (vf.get_diffuse()) fvf |= D3DFVF_DIFFUSE; 00243 if (vf.get_specular()) fvf |= D3DFVF_SPECULAR; 00244 00245 for(i = 0; i < vf.get_tex_count(); i++) { 00246 fvf += D3DFVF_TEX1; 00247 00248 if (vf.get_tex_size(i) == 1) fvf |= D3DFVF_TEXCOORDSIZE1(i); 00249 else if (vf.get_tex_size(i) == 2) fvf |= D3DFVF_TEXCOORDSIZE2(i); 00250 else if (vf.get_tex_size(i) == 3) fvf |= D3DFVF_TEXCOORDSIZE3(i); 00251 else if (vf.get_tex_size(i) == 4) fvf |= D3DFVF_TEXCOORDSIZE4(i); 00252 00253 } 00254 00255 return fvf; 00256 } 00257 00258 00259 typedef struct dx9data_s : h3ddata_s 00260 { 00261 HD3DEnumeration *enumeration; // available D3D settings: adapters, devices, modes, etc 00262 HD3DSettings *settings; // current D3D settings: adapter, device, mode, formats, etc 00263 D3DPRESENT_PARAMETERS presentation_params; // presentation parameters for the device to be created 00264 LPDIRECT3DDEVICE9 pDevice; // The D3D rendering device 00265 00266 LPDIRECT3DSURFACE9 render_target; 00267 LPDIRECT3DSURFACE9 depth_stencil; 00268 00269 #define REGION_SHARING 00270 #ifdef REGION_SHARING 00271 LPDIRECT3DSURFACE9 saved_render_target; 00272 LPDIRECT3DSURFACE9 saved_depth_stencil; 00273 #endif // REGION_SHARING 00274 00275 HDX9Post *post; 00276 00277 #define INVALID_CACHE (-1) 00278 #define INVALID_TEXTURE_CACHE (LPDIRECT3DTEXTURE9)(-1) 00279 #define INVALID_CUBE_TEXTURE_CACHE (LPDIRECT3DCUBETEXTURE9)(-1) 00280 #define INVALID_GEOMETRY_CACHE (void*)(-1) 00281 00282 00283 //spriting 00284 dx9region * image_regions; 00285 dx9region * z_regions; 00286 00287 D3DCAPS9 capabilities; //Caps for the device 00288 00289 HRESULT hr; 00290 } DX9Data; 00291 00292 00293 #ifndef DX9DATA_ONLY 00294 00295 00296 #define Debug_NO_TWO_SIDED_LIGHTING 0x00000001 00297 #define Debug_ENABLE_NVPERFHUD 0x00000002 00298 #define Debug_UNUSED3 0x00000004 00299 #define Debug_UNUSED4 0x00000008 00300 #define Debug_UNUSED5 0x00000010 00301 #define Debug_UNUSED6 0x00000020 00302 #define Debug_NO_WINDOWS_HOOK 0x00000040 00303 #define Debug_UNUSED8 0x00000080 00304 #define Debug_UNUSED9 0x00000100 00305 #define Debug_UNUSED10 0x00000200 00306 #define Debug_UNUSED11 0x00000400 00307 #define Debug_UNUSED12 0x00000800 00308 #define Debug_UNUSED13 0x00001000 00309 #define Debug_UNUSED14 0x00002000 00310 #define DEBUG_STARTUP_CLEAR_BLACK 0x00004000 00311 #define Debug_UNUSED16 0x00008000 00312 #define Debug_UNUSED17 0x00010000 00313 #define Debug_UNUSED18 0x00020000 00314 #define Debug_UNUSED19 0x00040000 00315 #define Debug_UNUSED20 0x00080000 00316 #define Debug_USE_WINDOW_IS_IMAGE 0x00100000 00317 #define Debug_UNUSED22 0x00200000 00318 #define Debug_UNUSED23 0x00400000 00319 #define Debug_UNUSED24 0x00800000 00320 #define Debug_FORCE_SOFTWARE 0x01000000 00321 #define Debug_UNUSED26 0x02000000 00322 #define Debug_UNUSED27 0x04000000 00323 #define Debug_UNUSED28 0x08000000 00324 #define Debug_UNUSED29 0x10000000 00325 #define Debug_UNUSED30 0x20000000 00326 #define Debug_UNUSED31 0x40000000 00327 #define Debug_UNUSED32 0x80000000 00328 00329 /* XBIT STUFF */ 00330 #define XBIT_NONE 0L 00331 #define XBIT_NO_INDEXED_PRIMITIVES 1L 00332 00333 00334 typedef struct dx9_system_data 00335 { 00336 int ref_count; // reference count 00337 LPDIRECT3D9 pD3D; // the main D3D object 00338 } DX9_System_Data; 00339 00340 #define DX9D(dc) ((DX9Data alter *)((dc)->data2)) 00341 #define DX9NRD(nr) (DX9D((nr)->display_context)) 00342 00343 /* SIL: No longer used? 00344 #define ENSURE_RGB32_SHADER(dx9data,nr,ppShader) SEMI_PROTECT(\ 00345 H3DShaderID _id_; \ 00346 HDX9Shader *_shader_; \ 00347 _id_.InitRGB32 (nr); \ 00348 _shader_ = dx9data->ShaderHash->Lookup (_id_); \ 00349 if (!_shader_) { \ 00350 _shader_ = new HDX9Shader(_id_); \ 00351 _shader_->Create(dx9data->pDevice); \ 00352 dx9data->ShaderHash->Insert (_id_, _shader_); \ 00353 } \ 00354 _shader_->Activate(); \ 00355 dx9data->cache.Shader = _shader_; \ 00356 *(ppShader) = dx9data->cache.Shader; \ 00357 ) 00358 */ 00359 00360 #define BEGIN_SCENE(dx9data) SEMI_PROTECT( \ 00361 if (!dx9data->has_scene_began) { \ 00362 dx9data->pDevice->BeginScene(); \ 00363 dx9data->has_scene_began = true; \ 00364 } \ 00365 ) 00366 #define END_SCENE(dx9data) SEMI_PROTECT( \ 00367 if (dx9data->has_scene_began) { \ 00368 dx9data->pDevice->EndScene(); \ 00369 dx9data->has_scene_began = false; \ 00370 } \ 00371 ) 00372 00373 #define D3DXMatrix_2_floats(d3d_mat_in, floats_out) \ 00374 floats_out[0][0] = d3d_mat_in._11; \ 00375 floats_out[0][1] = d3d_mat_in._12; \ 00376 floats_out[0][2] = d3d_mat_in._13; \ 00377 floats_out[0][3] = d3d_mat_in._14; \ 00378 \ 00379 floats_out[1][0] = d3d_mat_in._21; \ 00380 floats_out[1][1] = d3d_mat_in._22; \ 00381 floats_out[1][2] = d3d_mat_in._23; \ 00382 floats_out[1][3] = d3d_mat_in._24; \ 00383 \ 00384 floats_out[2][0] = d3d_mat_in._31; \ 00385 floats_out[2][1] = d3d_mat_in._32; \ 00386 floats_out[2][2] = d3d_mat_in._33; \ 00387 floats_out[2][3] = d3d_mat_in._34; \ 00388 \ 00389 floats_out[3][0] = d3d_mat_in._41; \ 00390 floats_out[3][1] = d3d_mat_in._42; \ 00391 floats_out[3][2] = d3d_mat_in._43; \ 00392 floats_out[3][3] = d3d_mat_in._44; 00393 00394 00395 /* 00396 * SCISSORING 00397 */ 00398 #define INVALIDATE_SCISSOR_SET(dx9data) SEMI_PROTECT(\ 00399 dx9data->cache.scissor_rect.left = INVALID_CACHE; \ 00400 dx9data->cache.scissor_rect.top = INVALID_CACHE; \ 00401 dx9data->cache.scissor_rect.right = INVALID_CACHE; \ 00402 dx9data->cache.scissor_rect.bottom = INVALID_CACHE; \ 00403 ) 00404 #define FORCE_SCISSOR_OFF(dx9data) SEMI_PROTECT(\ 00405 if (dx9data->can_scissor) {\ 00406 INVALIDATE_SCISSOR_SET(dx9data); \ 00407 dx9data->cache.scissoring = false; \ 00408 dx9data->pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);/*glDisable (GL_SCISSOR_TEST);*/ \ 00409 }\ 00410 ) 00411 #define ENSURE_SCISSOR_OFF(dx9data) SEMI_PROTECT(\ 00412 if (dx9data->cache.scissoring) \ 00413 FORCE_SCISSOR_OFF (dx9data); \ 00414 ) 00415 00416 #define ENSURE_SCISSOR_SET(dx9data, left, bottom, right, top) SEMI_PROTECT( \ 00417 RECT scr_rect; \ 00418 SetRect(&scr_rect, left, dx9data->yfudge - top , right + 1, dx9data->yfudge - bottom + 1); \ 00419 if (!EqualRect(&scr_rect, &dx9data->cache.scissor_rect)) { \ 00420 CopyRect(&dx9data->cache.scissor_rect, &scr_rect); \ 00421 dx9data->pDevice->SetScissorRect(&scr_rect); \ 00422 } \ 00423 ) 00424 00425 /* update the ref_matrix_negative_3x3 boolean, and make sure handedness stays 00426 * in synch. (ref_matrix_negative_3x3 tracks whether geometry has been put 00427 * through a geometry reference with a negative scale matrix */ 00428 #define ENSURE_NEG3X3(dx9data, tr, val) SEMI_PROTECT(\ 00429 if (val != dx9data->ref_matrix_negative_3x3) { \ 00430 dx9data->ref_matrix_negative_3x3 = val; \ 00431 set_handedness (dx9data, tr, FALSE); \ 00432 } \ 00433 else \ 00434 dx9data->ref_matrix_negative_3x3 = val; \ 00435 ) 00436 00437 /* 00438 * BLEND 00439 */ 00440 #define FORCE_BLEND(dx9data, src, dest) SEMI_PROTECT(\ 00441 dx9data->cache.src_blend = src; \ 00442 dx9data->pDevice->SetRenderState(D3DRS_SRCBLEND, src); \ 00443 dx9data->cache.dest_blend = dest; \ 00444 dx9data->pDevice->SetRenderState(D3DRS_DESTBLEND, dest); \ 00445 ) 00446 #define ENSURE_BLEND(dx9data, src, dest) SEMI_PROTECT(\ 00447 if (dx9data->cache.src_blend != src || dx9data->cache.dest_blend != dest) \ 00448 FORCE_BLEND(dx9data, src, dest); \ 00449 ) 00450 00451 00452 /* 00453 * STENCIL 00454 */ 00455 #define FORCE_STENCILLING(dx9data, onoff) SEMI_PROTECT(\ 00456 dx9data->cache.stencilling = onoff; \ 00457 dx9data->pDevice->SetRenderState(D3DRS_STENCILENABLE, onoff); \ 00458 ) 00459 #define ENSURE_STENCILLING(dx9data, onoff) SEMI_PROTECT(\ 00460 if (dx9data->cache.stencilling != onoff) { \ 00461 FORCE_STENCILLING(dx9data, onoff); \ 00462 } \ 00463 ) 00464 00465 00466 #define FORCE_STENCIL_MASK(dx9data, val) SEMI_PROTECT( \ 00467 dx9data->cache.stencil_mask = val; \ 00468 dx9data->pDevice->SetRenderState(D3DRS_STENCILMASK, val); \ 00469 ) 00470 #define ENSURE_STENCIL_MASK(dx9data, val) SEMI_PROTECT(\ 00471 if (dx9data->cache.stencil_mask != val) { \ 00472 FORCE_STENCIL_MASK(dx9data, val); \ 00473 } \ 00474 ) 00475 00476 #define FORCE_STENCIL_WRITE_MASK(dx9data, val) SEMI_PROTECT( \ 00477 dx9data->cache.stencil_write_mask = val; \ 00478 dx9data->pDevice->SetRenderState(D3DRS_STENCILWRITEMASK, val); \ 00479 ) 00480 #define ENSURE_STENCIL_WRITE_MASK(dx9data, val) SEMI_PROTECT(\ 00481 if (dx9data->cache.stencil_write_mask != val) { \ 00482 FORCE_STENCIL_WRITE_MASK(dx9data, val); \ 00483 } \ 00484 ) 00485 00486 #define FORCE_STENCIL_REF(dx9data, val) SEMI_PROTECT( \ 00487 dx9data->cache.stencil_ref = val; \ 00488 dx9data->pDevice->SetRenderState(D3DRS_STENCILREF, val); \ 00489 ) 00490 #define ENSURE_STENCIL_REF(dx9data, val) SEMI_PROTECT(\ 00491 if (dx9data->cache.stencil_ref != val) { \ 00492 FORCE_STENCIL_REF(dx9data, val); \ 00493 } \ 00494 ) 00495 00496 #define FORCE_STENCIL_FUNC(dx9data, val) SEMI_PROTECT( \ 00497 dx9data->cache.stencil_func = val; \ 00498 dx9data->pDevice->SetRenderState(D3DRS_STENCILFUNC, val); \ 00499 ) 00500 #define ENSURE_STENCIL_FUNC(dx9data, val) SEMI_PROTECT(\ 00501 if (dx9data->cache.stencil_func != val) { \ 00502 FORCE_STENCIL_FUNC(dx9data, val); \ 00503 } \ 00504 ) 00505 00506 00507 #define FORCE_STENCIL_OP(dx9data, fail, zfail, pass) SEMI_PROTECT( \ 00508 dx9data->cache.stencil_fail = fail; \ 00509 dx9data->cache.stencil_zfail = zfail; \ 00510 dx9data->cache.stencil_pass = pass; \ 00511 dx9data->pDevice->SetRenderState(D3DRS_STENCILFAIL, fail); \ 00512 dx9data->pDevice->SetRenderState(D3DRS_STENCILZFAIL, zfail); \ 00513 dx9data->pDevice->SetRenderState(D3DRS_STENCILPASS, pass); \ 00514 ) 00515 #define ENSURE_STENCIL_OP(dx9data, fail, zfail, pass) SEMI_PROTECT(\ 00516 if (dx9data->cache.stencil_fail != fail || \ 00517 dx9data->cache.stencil_zfail != zfail || \ 00518 dx9data->cache.stencil_pass != pass) { \ 00519 FORCE_STENCIL_OP(dx9data, fail, zfail, pass); \ 00520 } \ 00521 ) 00522 00523 #define STENCIL_BIT ((DWORD)(0x0080)) 00524 #define SET_STENCIL_FUNC(dx9data, cmp, ref, mask, writemask) SEMI_PROTECT(\ 00525 ENSURE_STENCIL_FUNC(dx9data, cmp); \ 00526 ENSURE_STENCIL_REF(dx9data, ref); \ 00527 ENSURE_STENCIL_MASK(dx9data, mask); \ 00528 ENSURE_STENCIL_WRITE_MASK(dx9data, writemask); \ 00529 ) 00530 00531 #define SET_STENCIL_OP(dx9data, fail, zfail, pass) SEMI_PROTECT(\ 00532 ENSURE_STENCIL_OP(dx9data, fail, zfail, pass); \ 00533 ) 00534 00535 /* 00536 * TEXTURE STATES 00537 */ 00538 #define FORCE_TEXTURE_WRAP_S(dx9data, unit, mode) SEMI_PROTECT(\ 00539 dx9data->cache.texture_wrap_s[unit] = mode; \ 00540 dx9data->pDevice->SetSamplerState(unit, D3DSAMP_ADDRESSU, mode); \ 00541 ) 00542 00543 #define ENSURE_TEXTURE_WRAP_S(dx9data, unit, mode) SEMI_PROTECT(\ 00544 if (dx9data->cache.texture_wrap_s[unit] != mode) \ 00545 FORCE_TEXTURE_WRAP_S(dx9data, unit, mode); \ 00546 ) 00547 00548 #define FORCE_TEXTURE_WRAP_T(dx9data, unit, mode) SEMI_PROTECT(\ 00549 dx9data->cache.texture_wrap_t[unit] = mode; \ 00550 dx9data->pDevice->SetSamplerState(unit, D3DSAMP_ADDRESSV, mode); \ 00551 ) 00552 00553 #define ENSURE_TEXTURE_WRAP_T(dx9data, unit, mode) SEMI_PROTECT(\ 00554 if (dx9data->cache.texture_wrap_t[unit] != mode) \ 00555 FORCE_TEXTURE_WRAP_T(dx9data, unit, mode); \ 00556 ) 00557 00558 #define FORCE_TEXTURE_MIN_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00559 dx9data->cache.texture_min_filter[unit] = mode; \ 00560 dx9data->pDevice->SetSamplerState(unit, D3DSAMP_MINFILTER, mode); \ 00561 ) 00562 00563 #define ENSURE_TEXTURE_MIN_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00564 if (dx9data->cache.texture_min_filter[unit] != mode) \ 00565 FORCE_TEXTURE_MIN_FILTER(dx9data, unit, mode); \ 00566 ) 00567 00568 #define FORCE_TEXTURE_MAG_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00569 dx9data->cache.texture_mag_filter[unit] = mode; \ 00570 dx9data->pDevice->SetSamplerState(unit, D3DSAMP_MAGFILTER, mode); \ 00571 ) 00572 00573 #define ENSURE_TEXTURE_MAG_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00574 if (dx9data->cache.texture_mag_filter[unit] != mode) \ 00575 FORCE_TEXTURE_MAG_FILTER(dx9data, unit, mode); \ 00576 ) 00577 00578 #define FORCE_TEXTURE_MIP_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00579 dx9data->cache.texture_mip_filter[unit] = mode; \ 00580 dx9data->pDevice->SetSamplerState(unit, D3DSAMP_MIPFILTER, mode); \ 00581 ) 00582 00583 #define ENSURE_TEXTURE_MIP_FILTER(dx9data, unit, mode) SEMI_PROTECT(\ 00584 if (dx9data->cache.texture_mip_filter[unit] != mode) \ 00585 FORCE_TEXTURE_MIP_FILTER(dx9data, unit, mode); \ 00586 ) 00587 00588 #define ENSURE_SAMPLER_STATE(dx9data, unit, filter, mip_filter, wrap) SEMI_PROTECT(\ 00589 ENSURE_TEXTURE_MIN_FILTER(dx9data, unit, filter); \ 00590 ENSURE_TEXTURE_MAG_FILTER(dx9data, unit, filter); \ 00591 ENSURE_TEXTURE_MIP_FILTER(dx9data, unit, mip_filter); \ 00592 ENSURE_TEXTURE_WRAP_S(dx9data, unit, wrap); \ 00593 ENSURE_TEXTURE_WRAP_T(dx9data, unit, wrap); \ 00594 ) 00595 00596 #define INVALIDATE_TEXTURE_SETTING_CACHE(dx9data) SEMI_PROTECT(\ 00597 { \ 00598 int _unit_; \ 00599 for (_unit_ = 0; _unit_ < MAX_TEXTURE_UNIT; ++_unit_) { \ 00600 (dx9data)->cache.texture_wrap_s[_unit_] = INVALID_CACHE; \ 00601 (dx9data)->cache.texture_wrap_t[_unit_] = INVALID_CACHE; \ 00602 (dx9data)->cache.texture_mag_filter[_unit_] = INVALID_CACHE; \ 00603 (dx9data)->cache.texture_min_filter[_unit_] = INVALID_CACHE; \ 00604 (dx9data)->cache.texture_mip_filter[_unit_] = INVALID_CACHE; \ 00605 } \ 00606 } \ 00607 ) 00608 00609 00610 /* 00611 * ATMOSPHERIC ATTENUATION 00612 */ 00613 #define ENSURE_FOG_OFF(dx9data, nr) SEMI_PROTECT(\ 00614 if ((dx9data)->cache.fog_on != false) { \ 00615 (dx9data)->cache.fog_on = false; \ 00616 (dx9data)->pDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); \ 00617 } \ 00618 ) 00619 00620 #define ENSURE_FOG_ON(dx9data, nr) SEMI_PROTECT (\ 00621 dx9data->cache.fog_on = true; \ 00622 dx9data->pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE); /*glEnable (GL_FOG);*/ \ 00623 if (nr->visualization_rendition->incarnation != dx9data->fog_incarnation) { \ 00624 /*float fog_color[4];*/ \ 00625 dx9data->fog_incarnation = nr->misc_rendition->incarnation; \ 00626 /* do not do pixel fog calculations */ \ 00627 dx9data->pDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); \ 00628 dx9data->pDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); \ 00629 dx9data->pDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB(nr->window_rendition->window_color.direct_rgb.r, nr->window_rendition->window_color.direct_rgb.g, nr->window_rendition->window_color.direct_rgb.r)); \ 00630 } \ 00631 ) 00632 00633 00634 //stores a substrip of an HT_Tristrip or HT_Polyedge 00635 struct hdx9_indexed_primitive 00636 { 00637 H3DPRIMITIVETYPE type; //e.g. H3DPT_TRIANGLESTRIP or H3DPT_TRIANGLEFAN 00638 unsigned int size; 00639 unsigned int count; 00640 IDirect3DIndexBuffer9 *idx_buff; 00641 }; 00642 00643 00644 #define HDX9_PER_OBJECT_PENALTY 128 00645 00646 00647 00648 class HDX9Mesh : public H3DIndexedBufferObject 00649 { 00650 public: 00651 ID3DXMesh *m_d3dxmesh; 00652 00653 HDX9Mesh() 00654 { 00655 OUR(display_list_vram_usage) += HDX9_PER_OBJECT_PENALTY; 00656 } 00657 ~HDX9Mesh() 00658 { 00659 m_d3dxmesh->Release(); 00660 } 00661 00662 //called once per HT_Tristrip 00663 bool CreateMesh (H3DData *h3ddata, 00664 UINT point_count, 00665 UINT face_count, 00666 H3DVertexFormat VF) 00667 { 00668 DX9Data *dx9data = (DX9Data *) h3ddata; 00669 HRESULT hr; 00670 00671 m_point_count = point_count; 00672 m_stride = VF.get_size(); 00673 m_VF = VF; 00674 00675 do { 00676 hr = D3DXCreateMeshFVF( 00677 face_count, 00678 point_count, 00679 D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM, 00680 vf2fvf(VF), 00681 dx9data->pDevice, 00682 &m_d3dxmesh); 00683 } while (hr == D3DERR_NOTAVAILABLE); 00684 return SUCCEEDED(hr); 00685 } 00686 00687 00688 bool LockIndexBuffer(UINT OffsetToLock, UINT SizeToLock, H3DIndexBuffer *ib, DWORD Flags) 00689 { 00690 UNREFERENCED(OffsetToLock); 00691 UNREFERENCED(SizeToLock); 00692 void *p; 00693 00694 m_format = H3DFMT_INDEX32; 00695 00696 HRESULT hr = m_d3dxmesh->LockIndexBuffer(Flags, (void**)&p); 00697 ib->Init(m_format, p); 00698 return SUCCEEDED(hr); 00699 } 00700 00701 bool LockVertexBuffer(UINT OffsetToLock, UINT SizeToLock, H3DVertexBuffer *pv, DWORD Flags) 00702 { 00703 UNREFERENCED(OffsetToLock); 00704 UNREFERENCED(SizeToLock); 00705 float *data; 00706 HRESULT hr = m_d3dxmesh->LockVertexBuffer(Flags, (void**)&data); 00707 pv->Init(data, m_VF); 00708 return SUCCEEDED(hr); 00709 } 00710 00711 void UnlockIndexBuffer() 00712 { 00713 m_d3dxmesh->UnlockIndexBuffer(); 00714 } 00715 00716 void UnlockVertexBuffer() 00717 { 00718 m_d3dxmesh->UnlockVertexBuffer(); 00719 } 00720 00721 bool CreateVertexBuffer (H3DData *h3ddata, 00722 UINT point_count, 00723 H3DVertexFormat VF) 00724 { 00725 UNREFERENCED(h3ddata); 00726 UNREFERENCED(point_count); 00727 UNREFERENCED(VF); 00728 return false; 00729 }; 00730 bool CreateIndexBuffer (H3DData *h3ddata, 00731 H3DPRIMITIVETYPE type, 00732 UINT size, 00733 UINT count) 00734 { 00735 UNREFERENCED(h3ddata); 00736 UNREFERENCED(type); 00737 UNREFERENCED(size); 00738 UNREFERENCED(count); 00739 return false; 00740 }; 00741 void Draw(H3DData *h3ddata, HT_Test *cull_results = null) 00742 { 00743 UNREFERENCED(h3ddata); 00744 UNREFERENCED(cull_results); 00745 } 00746 }; 00747 00748 00749 // this is the buffer object data structure which caches the vertex and index buffers 00750 // Stores an entire HT_Tristrip or HT_Polyedge 00751 class HDX9IndexedBufferObject : public H3DIndexedBufferObject 00752 { 00753 public: 00754 IDirect3DVertexBuffer9 *m_vtx_buff; 00755 hdx9_indexed_primitive *m_primitives; 00756 00757 HDX9IndexedBufferObject() 00758 { 00759 OUR(display_list_vram_usage) += HDX9_PER_OBJECT_PENALTY; 00760 m_primitives = null; 00761 } 00762 ~HDX9IndexedBufferObject() 00763 { 00764 H_SAFE_RELEASE(m_vtx_buff); 00765 OUR(display_list_vram_usage) -= HDX9_PER_OBJECT_PENALTY; 00766 OUR(display_list_vram_usage) -= (m_stride * m_point_count); 00767 00768 if (m_format == H3DFMT_INDEX16) 00769 OUR(display_list_vram_usage) -= (m_primitives->size * sizeof(short)); 00770 else 00771 OUR(display_list_vram_usage) -= (m_primitives->size * sizeof(int)); 00772 H_SAFE_RELEASE(m_primitives->idx_buff); 00773 H_SAFE_DELETE(m_primitives); 00774 } 00775 00776 //called once per HT_Tristrip 00777 bool CreateVertexBuffer (H3DData *h3ddata, 00778 UINT point_count, 00779 H3DVertexFormat VF) 00780 { 00781 DX9Data *dx9data = (DX9Data *) h3ddata; 00782 m_point_count = point_count; 00783 m_stride = VF.get_size(); 00784 m_VF = VF; //the flexible vertex format 00785 HRESULT hr; 00786 do { 00787 hr = dx9data->pDevice->CreateVertexBuffer( 00788 point_count*m_stride, 00789 D3DUSAGE_WRITEONLY, 00790 vf2fvf(VF), 00791 HDX9_POOL_TYPE, 00792 &m_vtx_buff, 00793 NULL); 00794 } while (hr == D3DERR_NOTAVAILABLE); 00795 00796 OUR(display_list_vram_usage) += (m_stride * m_point_count); 00797 return SUCCEEDED(hr); 00798 } 00799 00800 //called ts->strips times per HT_Tristrip 00801 bool CreateIndexBuffer (H3DData *h3ddata, 00802 H3DPRIMITIVETYPE type, 00803 UINT size, 00804 UINT count) 00805 { 00806 DX9Data *dx9data = (DX9Data *) h3ddata; 00807 IDirect3DIndexBuffer9* pIndexBuffer; 00808 D3DCAPS9 caps; 00809 dx9data->pDevice->GetDeviceCaps(&caps); 00810 00811 hdx9_indexed_primitive * ip = new hdx9_indexed_primitive(); 00812 ip->type = type; 00813 ip->size = size; 00814 ip->count = count; 00815 m_primitives = ip; 00816 00817 if (m_point_count > caps.MaxVertexIndex) 00818 HE_ERROR(HEC_DX9_DRIVER, HEC_DX9_DRIVER, 00819 "Internal error: point count exceeds maximum vertex index."); 00820 00821 if (m_point_count <= 0x0000ffff && count <= 0x0000ffff) 00822 m_format = H3DFMT_INDEX16; 00823 else 00824 m_format = H3DFMT_INDEX32; 00825 00826 HRESULT hr; 00827 do { 00828 hr = dx9data->pDevice->CreateIndexBuffer( 00829 size, 00830 D3DUSAGE_WRITEONLY, 00831 d3dformat(m_format), 00832 HDX9_POOL_TYPE, 00833 &pIndexBuffer, 00834 NULL); 00835 } while (hr == D3DERR_NOTAVAILABLE); 00836 ip->idx_buff = pIndexBuffer; 00837 00838 if (m_format == D3DFMT_INDEX16) 00839 OUR(display_list_vram_usage) += (ip->size * sizeof(short)); 00840 else 00841 OUR(display_list_vram_usage) += (ip->size * sizeof(int)); 00842 return SUCCEEDED(hr); 00843 } 00844 00845 bool LockIndexBuffer(UINT OffsetToLock, UINT SizeToLock, H3DIndexBuffer *ib, DWORD Flags) 00846 { 00847 void *p; 00848 HRESULT hr = m_primitives->idx_buff->Lock(OffsetToLock, SizeToLock, &p, Flags); 00849 ib->Init(m_format, p); 00850 return SUCCEEDED(hr); 00851 } 00852 00853 bool LockVertexBuffer(UINT OffsetToLock, UINT SizeToLock, H3DVertexBuffer *pv, DWORD Flags) 00854 { 00855 float *data; 00856 HRESULT hr = m_vtx_buff->Lock(OffsetToLock, SizeToLock, (void **) &data, Flags); 00857 00858 pv->Init(data, m_VF); 00859 return SUCCEEDED(hr); 00860 } 00861 00862 void UnlockIndexBuffer() 00863 { 00864 if (m_primitives) 00865 m_primitives->idx_buff->Unlock(); 00866 } 00867 00868 void UnlockVertexBuffer() 00869 { 00870 m_vtx_buff->Unlock(); 00871 } 00872 00873 void Draw(H3DData *h3ddata, HT_Test *cull_results = null) 00874 { 00875 DX9Data *dx9data = (DX9Data *) h3ddata; 00876 ENSURE_VF(dx9data, m_VF); 00877 dx9data->pDevice->SetStreamSource (0, m_vtx_buff, 0, m_stride); 00878 dx9data->pDevice->SetIndices(m_primitives->idx_buff); 00879 00880 if (cull_results == null) { 00881 dx9data->pDevice->DrawIndexedPrimitive ( 00882 d3dprimitive(m_primitives->type), 00883 0, 00884 0, 00885 m_point_count, 00886 0, 00887 m_primitives->count); 00888 } 00889 else { 00890 int prev = 0; 00891 int len = 0; 00892 int k = 0; 00893 int primitive_count = 0; 00894 00895 for (;;) { 00896 while (k < m_tristrip_count && 00897 CULL_ACCEPT(cull_results[k + m_tristrip_first])) { 00898 len = m_tristrip_offsets[k] - prev; 00899 k++; 00900 } 00901 00902 // Either we failed on a culling test, or we successfully finished. In both cases, we 00903 // need to figure out what length of the last tristrip to be drawn, and add to the 00904 // total length. 00905 if (k == m_tristrip_count) { 00906 // since we only store the first index of each tristrip, we need to calculate 00907 // the length of the last one (as it's not readily stored in the offsets array) 00908 00909 int bytes_per_index = 0; 00910 if (m_format == H3DFMT_INDEX32) 00911 bytes_per_index = sizeof(int); 00912 else 00913 bytes_per_index = sizeof(short); 00914 00915 len += ((m_primitives->size / bytes_per_index) - m_tristrip_offsets[k-1]); 00916 } 00917 else 00918 len = m_tristrip_offsets[k] - prev; 00919 00920 00921 if (len > 0) { 00922 switch (m_primitives->type) { 00923 case H3DPT_TRIANGLELIST: 00924 primitive_count = len / 3; 00925 break; 00926 case H3DPT_TRIANGLESTRIP: 00927 primitive_count = len - 2; 00928 break; 00929 default: 00930 ASSERT(0); 00931 break; 00932 } 00933 00934 dx9data->pDevice->DrawIndexedPrimitive ( 00935 d3dprimitive(m_primitives->type), 00936 0, 00937 0, 00938 m_point_count, 00939 prev, 00940 primitive_count); 00941 } 00942 while (k < m_tristrip_count && 00943 !CULL_ACCEPT(cull_results[k + m_tristrip_first])) { 00944 prev = m_tristrip_offsets[k]; 00945 k++; 00946 } 00947 if (k == m_tristrip_count) 00948 break; 00949 } 00950 } 00951 } 00952 }; 00953 00954 00955 // this is the global vertex buffer cache, being used for view dependent geometry 00956 class HDX9VertexBufferCache : public H3DVertexBufferCache 00957 { 00958 public: 00959 HDX9VertexBufferCache() 00960 { 00961 OUR(display_list_vram_usage) += HDX9_PER_OBJECT_PENALTY; 00962 m_pVertexBuffer = 0; 00963 m_nMaxPoints = 0; 00964 m_nNextVertexData = 0; 00965 m_nCurVertexData = 0; 00966 } 00967 00968 ~HDX9VertexBufferCache() 00969 { 00970 OUR(display_list_vram_usage) -= HDX9_PER_OBJECT_PENALTY; 00971 H_SAFE_RELEASE(m_pVertexBuffer); 00972 OUR(display_list_vram_usage) -= (m_nMaxPoints * m_nVertexStride); 00973 } 00974 00975 bool CreateVertexBuffer(H3DData *h3ddata, UINT max_points, 00976 H3DVertexFormat VF) 00977 { 00978 H_SAFE_RELEASE(m_pVertexBuffer); 00979 DX9Data *dx9data = (DX9Data *) h3ddata; 00980 00981 m_nMaxPoints = max_points; 00982 m_nVertexStride = VF.get_size(); 00983 m_VF = VF; 00984 HRESULT hr = dx9data->pDevice->CreateVertexBuffer(m_nMaxPoints*m_nVertexStride, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 00985 vf2fvf(VF), D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL); 00986 00987 OUR(display_list_vram_usage) += (m_nMaxPoints * m_nVertexStride); 00988 return !FAILED(hr); 00989 } 00990 00991 bool Reset() 00992 { 00993 H_SAFE_RELEASE(m_pVertexBuffer); 00994 OUR(display_list_vram_usage) -= (m_nMaxPoints * m_nVertexStride); 00995 00996 m_nMaxPoints = 0; 00997 m_nNextVertexData = 0; 00998 m_nCurVertexData = 0; 00999 return true; 01000 } 01001 01002 bool Discard() 01003 { 01004 m_nNextVertexData = 0; 01005 m_nCurVertexData = 0; 01006 void * pData; 01007 m_pVertexBuffer->Lock((UINT)m_nNextVertexData, 0, &pData, D3DLOCK_DISCARD); 01008 m_pVertexBuffer->Unlock(); 01009 return true; 01010 } 01011 01012 bool Lock(UINT count, H3DVertexBuffer *pv) 01013 { 01014 float *pvbuf = null; 01015 01016 // Determine the size of data to be moved into the vertex buffer. 01017 UINT data_size = count * m_nVertexStride; 01018 01019 // No overwrite will be used if the vertices can fit into 01020 // the space remaining in the vertex buffer. 01021 DWORD dwLockFlags = D3DLOCK_NOOVERWRITE; 01022 01023 // Check to see if the entire vertex buffer has been used up yet. 01024 if (m_nNextVertexData > (m_nMaxPoints*m_nVertexStride - data_size)) 01025 { 01026 // No space remains. Start over from the beginning 01027 // of the vertex buffer. 01028 dwLockFlags = D3DLOCK_DISCARD; 01029 m_nCurVertexData = 0; 01030 m_nNextVertexData = 0; 01031 } 01032 01033 // Lock the vertex buffer. 01034 HRESULT hr; 01035 if (FAILED(hr = m_pVertexBuffer->Lock((UINT)m_nNextVertexData, data_size, 01036 (void **) &pvbuf, dwLockFlags))) 01037 return false; 01038 01039 pv->Init(pvbuf, m_VF); 01040 01041 // Advance to the next position in the vertex buffer. 01042 m_nNextVertexData += data_size; 01043 01044 return true; 01045 } 01046 01047 bool Unlock(VOID) 01048 { 01049 return !FAILED(m_pVertexBuffer->Unlock()); 01050 } 01051 01052 bool Draw(H3DData *h3ddata , H3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount) 01053 { 01054 // Render the primitives. 01055 bool result = DrawRepeatable(h3ddata, PrimitiveType, PrimitiveCount); 01056 DrawComplete(); 01057 return result; 01058 } 01059 01060 bool DrawRepeatable(H3DData *h3ddata , H3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount) 01061 { 01062 // Render the primitives. 01063 DX9Data *dx9data = (DX9Data *) h3ddata; 01064 ENSURE_VF(dx9data, m_VF); 01065 dx9data->pDevice->SetStreamSource(0, m_pVertexBuffer, 0, m_nVertexStride); 01066 HRESULT hr = dx9data->pDevice->DrawPrimitive(d3dprimitive(PrimitiveType), m_nCurVertexData/m_nVertexStride, PrimitiveCount); 01067 return !FAILED(hr); 01068 } 01069 01070 void DrawComplete() 01071 { 01072 m_nCurVertexData = m_nNextVertexData; 01073 } 01074 01075 IDirect3DVertexBuffer9 *m_pVertexBuffer; 01076 }; 01077 01078 01079 // an index buffer, used in conjunction with a HDX9VertexBufferCache class. Can use any HDX9VertexBufferCache 01080 class HDX9IndexBufferCache : public H3DIndexBufferCache 01081 { 01082 public: 01083 HDX9IndexBufferCache() 01084 { 01085 OUR(display_list_vram_usage) += HDX9_PER_OBJECT_PENALTY; 01086 m_pIndexBuffer = 0; 01087 m_nNextIndexData = 0; 01088 m_nCurIndexData = 0; 01089 } 01090 01091 ~HDX9IndexBufferCache() 01092 { 01093 OUR(display_list_vram_usage) -= HDX9_PER_OBJECT_PENALTY; 01094 OUR(display_list_vram_usage) -= (VB_CACHE_MAX_SIZE * sizeof(short)); 01095 H_SAFE_RELEASE(m_pIndexBuffer); 01096 } 01097 01098 bool CreateIndexBuffer(H3DData *h3ddata) 01099 { 01100 HRESULT hr = S_OK; 01101 DX9Data *dx9data = (DX9Data *) h3ddata; 01102 LPDIRECT3DDEVICE9 pDevice = dx9data->pDevice; 01103 01104 ASSERT(VB_CACHE_MAX_SIZE < 0x0000ffff); //index buffer cache does not support 32 bit indices 01105 if (m_pIndexBuffer == NULL) 01106 hr = pDevice->CreateIndexBuffer ( 01107 VB_CACHE_MAX_SIZE * sizeof(short), 01108 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 01109 D3DFMT_INDEX16, 01110 D3DPOOL_DEFAULT, 01111 &m_pIndexBuffer, 01112 NULL); 01113 01114 OUR(display_list_vram_usage) += (VB_CACHE_MAX_SIZE * sizeof(short)); 01115 return SUCCEEDED(hr); 01116 } 01117 01118 bool Lock(short count, VOID **ppbData) 01119 { 01120 HRESULT hr; 01121 int sizetolock = count * sizeof(short); 01122 if (m_nNextIndexData > (VB_CACHE_MAX_SIZE * sizeof(short) - sizetolock)) { 01123 m_nCurIndexData = m_nNextIndexData = 0; 01124 hr = m_pIndexBuffer->Lock(0, sizetolock, ppbData, D3DLOCK_DISCARD); 01125 } 01126 else { 01127 hr = m_pIndexBuffer->Lock(m_nNextIndexData, sizetolock, ppbData, D3DLOCK_NOOVERWRITE); 01128 } 01129 m_nNextIndexData += sizetolock; 01130 01131 return SUCCEEDED(hr); 01132 } 01133 01134 bool Unlock(VOID) 01135 { 01136 return SUCCEEDED(m_pIndexBuffer->Unlock()); 01137 } 01138 01139 bool Draw(H3DData *h3ddata , H3DPRIMITIVETYPE PrimitiveType, 01140 UINT VertexCount, 01141 UINT PrimitiveCount) 01142 { 01143 DX9Data *dx9data = (DX9Data *) h3ddata; 01144 // Render the primitives. 01145 ENSURE_VF(dx9data, m_pVertexBufferCache->m_VF); 01146 dx9data->pDevice->SetStreamSource (0, 01147 (IDirect3DVertexBuffer9 *) m_pVertexBufferCache->m_pVertexBuffer, 01148 m_pVertexBufferCache->m_nCurVertexData, 01149 m_pVertexBufferCache->m_nVertexStride); 01150 dx9data->pDevice->SetIndices (m_pIndexBuffer); 01151 HRESULT hr = dx9data->pDevice->DrawIndexedPrimitive ( 01152 d3dprimitive(PrimitiveType), 01153 0, 01154 0, 01155 VertexCount, 01156 m_nCurIndexData/sizeof(short), 01157 PrimitiveCount); 01158 return SUCCEEDED(hr); 01159 } 01160 01161 void DrawComplete() 01162 { 01163 m_nCurIndexData = m_nNextIndexData; 01164 m_pVertexBufferCache->m_nCurVertexData = m_pVertexBufferCache->m_nNextVertexData; 01165 } 01166 01167 void SetVertexBufferCache (H3DVertexBufferCache *vbcache) 01168 { 01169 m_pVertexBufferCache = (HDX9VertexBufferCache *) vbcache; 01170 } 01171 01172 IDirect3DIndexBuffer9 *m_pIndexBuffer; 01173 HDX9VertexBufferCache *m_pVertexBufferCache; 01174 UINT m_nCurIndexData; 01175 UINT m_nNextIndexData; 01176 }; 01177 01178 01179 /***************************************************************************** 01180 ***************************************************************************** 01181 HDX9Shader Class 01182 ***************************************************************************** 01183 *****************************************************************************/ 01184 class HDX9Shader : public H3DShader 01185 { 01186 protected: 01187 virtual void ComposeDumpFilename (H3DShaderID &id, bool isVS, char alter *dump_filename); 01188 virtual bool DumpHLSL (char const *filename, char const *contents); 01189 virtual char alter *ComposePreamble (H3DShaderID &id, char alter *ptr, char const *end, int model, char const *dump_filename); 01190 virtual char alter *AppendBaseHLSL (const char *filename, const char *string, char alter *ptr, char const *end); 01191 01192 public: 01193 IDirect3DDevice9 *m_pDevice; 01194 IDirect3DVertexShader9 *m_pVS; 01195 IDirect3DPixelShader9 *m_pPS; 01196 ID3DXConstantTable *m_pVSConstantTable; 01197 ID3DXConstantTable *m_pPSConstantTable; 01198 01199 #define INVALID_HANDLE (D3DXHANDLE)(-1) 01200 struct Cache { 01201 // 3D constants 01202 D3DXHANDLE model; 01203 D3DXHANDLE modelview; 01204 D3DXHANDLE projection; 01205 D3DXHANDLE normalizedmodelview; 01206 01207 D3DXHANDLE materialgloss_ps; 01208 D3DXHANDLE materialgloss_vs; 01209 D3DXHANDLE colormapsize; 01210 D3DXHANDLE mirror; 01211 D3DXHANDLE camerapos; 01212 01213 D3DXHANDLE ambient; 01214 D3DXHANDLE *distantlight_direction; 01215 D3DXHANDLE *distantlight_diffuse; 01216 D3DXHANDLE *distantlight_specular; 01217 D3DXHANDLE *distantlight_halfway; 01218 D3DXHANDLE *pointlight_position; 01219 D3DXHANDLE *pointlight_diffuse; 01220 D3DXHANDLE *pointlight_specular; 01221 D3DXHANDLE *spotlight_position; 01222 D3DXHANDLE *spotlight_direction; 01223 D3DXHANDLE *spotlight_angles; 01224 D3DXHANDLE *spotlight_diffuse; 01225 D3DXHANDLE *spotlight_specular; 01226 01227 D3DXHANDLE shadow_maps[H3D_MAX_SHADOW_MAPS]; 01228 01229 #ifdef SHADOW_DISTORTION_DEMO 01230 D3DXHANDLE create_shadow_distortion; 01231 D3DXHANDLE shadow_distortion[H3D_MAX_SHADOW_MAPS]; 01232 #endif // SHADOW_DISTORTION_DEMO 01233 01234 D3DXHANDLE modulationcolor[H3D_MAX_TEXTURES]; 01235 01236 D3DXHANDLE atmosphericattenuation_hither; 01237 D3DXHANDLE atmosphericattenuation_yon; 01238 D3DXHANDLE atmosphericattenuation_color; 01239 01240 D3DXHANDLE reflection_plane; 01241 01242 // DC constants 01243 D3DXHANDLE worldviewproj; 01244 D3DXHANDLE color; 01245 D3DXHANDLE lineweight; 01246 D3DXHANDLE circlesubimagestart; 01247 D3DXHANDLE cosjoincutoffangle; 01248 01249 //constants that apply to both DC and 3D 01250 D3DXHANDLE viewport_scale_and_bias; 01251 D3DXHANDLE jitter_scale_and_bias; 01252 D3DXHANDLE window_width; 01253 D3DXHANDLE window_height; 01254 D3DXHANDLE facecontrastcolor; 01255 D3DXHANDLE linecontrastcolor; 01256 D3DXHANDLE facedisplacement; 01257 D3DXHANDLE generaldisplacement; 01258 D3DXHANDLE texture[H3D_MAX_TEXTURES]; 01259 D3DXHANDLE diffuse_ps; 01260 D3DXHANDLE materialdiffuse_ps; 01261 D3DXHANDLE materialdiffuse_vs; 01262 D3DXHANDLE cuttingplane[H3D_MAX_CUTTING_PLANES]; 01263 } cache; 01264 01265 HDX9Shader (const H3DShaderID& id); 01266 ~HDX9Shader (); 01267 01268 bool Create (H3DData *h3ddata); 01269 bool Activate (void); 01270 01271 void Force2DTransform (float *matrix); 01272 void Ensure3DTransform (HT_Net_Rendition const *nr); 01273 void EnsureDCTransform (HT_Net_Rendition const *nr); 01274 void EnsureColor (HT_Direct_RGB const *color); 01275 void EnsureLights ( 01276 HT_Net_Rendition const *nr, 01277 HT_Light_Rendition const *lr, 01278 HT_Material_Rendition const *mr, 01279 HT_Driver_Color const *color); 01280 void EnsureLineStyle ( 01281 HT_Net_Rendition const *nr, 01282 HT_Line_Rendition const *er); 01283 void EnsureCuttingPlanes (HT_Net_Rendition const *nr, HT_Cutting_Plane_Set const *cutset); 01284 void EnsureDCCuttingPlanes (HT_Cutting_Plane_Set const *cutset); 01285 void EnsureReflectionPlane (H3DData::ReflectionPlaneConstants const & constants); 01286 void EnsureDepthPeeling (H3DTexture *texture, H3DData *h3ddata); 01287 }; 01288 01289 01290 #define ENSURE_CONSTANT_HANDLE(const_table, cache, parent, constant) SEMI_PROTECT (\ 01291 if (cache == null) { \ 01292 cache = const_table->GetConstantByName(parent, constant); \ 01293 if (cache == null) \ 01294 cache = INVALID_HANDLE; \ 01295 } \ 01296 ); 01297 #define SET_CONSTANT(device, const_table, cache, parent, constant, value, action) SEMI_PROTECT (\ 01298 ENSURE_CONSTANT_HANDLE(const_table, cache, parent, constant); \ 01299 if (cache != INVALID_HANDLE) \ 01300 const_table->action(device, cache, value); \ 01301 ); 01302 #define SET_CONSTANT_ARRAY(device, const_table, cache, parent, constant, value, size, action) SEMI_PROTECT (\ 01303 ENSURE_CONSTANT_HANDLE(const_table, cache, parent, constant); \ 01304 if (cache != INVALID_HANDLE) \ 01305 const_table->action(device, cache, value, size); \ 01306 ); 01307 01308 #define SET_CONSTANT_FLOAT(device, const_table, cache, parent, constant, value) \ 01309 SET_CONSTANT(device, const_table, cache, parent, constant, value, SetFloat); 01310 01311 #define SET_CONSTANT_FLOAT_ARRAY(device, const_table, cache, parent, constant, value, size) \ 01312 SET_CONSTANT_ARRAY(device, const_table, cache, parent, constant, value, size, SetFloatArray); 01313 01314 #define SET_CONSTANT_INT(device, const_table, cache, parent, constant, value) \ 01315 SET_CONSTANT(device, const_table, cache, parent, constant, value, SetInt); 01316 01317 #define SET_CONSTANT_INT_ARRAY(device, const_table, cache, parent, constant, value, size) \ 01318 SET_CONSTANT_ARRAY(device, const_table, cache, parent, constant, value, size, SetIntArray); 01319 01320 #define SET_CONSTANT_MATRIX(device, const_table, cache, parent, constant, value) \ 01321 SET_CONSTANT(device, const_table, cache, parent, constant, value, SetMatrix); 01322 01323 #define SET_CONSTANT_MATRIX_ARRAY(device, const_table, cache, parent, constant, value, size) \ 01324 SET_CONSTANT_ARRAY(device, const_table, cache, parent, constant, value, size, SetMatrixArray); 01325 01326 #define SET_CONSTANT_VECTOR(device, const_table, cache, parent, constant, value) \ 01327 SET_CONSTANT(device, const_table, cache, parent, constant, value, SetVector) 01328 01329 #define SET_CONSTANT_VECTOR_ARRAY(device, const_table, cache, parent, constant, value, size) \ 01330 SET_CONSTANT_ARRAY(device, const_table, cache, parent, constant, value, size, SetVectorArray); 01331 01332 01333 01334 local void depth_peeling_hardware(HT_Display_Context alter * dc); 01335 local void depth_peeling_float(HT_Display_Context alter * dc); 01336 01337 01338 01339 01340 /***************************************************************************** 01341 ***************************************************************************** 01342 HDX9Texture Class 01343 ***************************************************************************** 01344 *****************************************************************************/ 01345 class HDX9Texture : public H3DTexture 01346 { 01347 private: 01348 LPDIRECT3DTEXTURE9 m_id; 01349 D3DLOCKED_RECT m_rect; 01350 01351 public: 01352 HRESULT hr; 01353 01354 public: 01355 HDX9Texture(H3DData *h3ddata, 01356 unsigned int width, 01357 unsigned int height, 01358 unsigned int levels, 01359 unsigned int usage, 01360 H3DFORMAT z_format) 01361 { 01362 DX9Data *dx9data = (DX9Data *) h3ddata; 01363 m_h3ddata = h3ddata; 01364 D3DFORMAT format = D3DFMT_A8R8G8B8; 01365 D3DPOOL pool = D3DPOOL_DEFAULT; 01366 unsigned int tex_usage = 0; 01367 01368 if (BIT(usage, H3DTEXUSAGE_RENDERTARGET)) 01369 tex_usage = D3DUSAGE_RENDERTARGET; 01370 else if (BIT(usage, H3DTEXUSAGE_DEPTHSTENCIL)) 01371 tex_usage = D3DUSAGE_DEPTHSTENCIL; 01372 else 01373 pool = D3DPOOL_MANAGED; 01374 01375 if (BIT(usage, H3DTEXUSAGE_AUTOGENMIPMAP)) 01376 tex_usage |= D3DUSAGE_AUTOGENMIPMAP; 01377 01378 switch (z_format) 01379 { 01380 case H3DFMT_A8R8G8B8: 01381 format = D3DFMT_A8R8G8B8; 01382 break; 01383 case H3DFMT_R32F: 01384 format = D3DFMT_R32F; 01385 break; 01386 default: 01387 HE_ERROR(HEC_DX9_DRIVER, HEC_DX9_DRIVER, 01388 "Internal error: unhandled DX9 texture format!"); 01389 } 01390 01391 hr = dx9data->pDevice->CreateTexture(width, height, levels, tex_usage, 01392 format, pool, &m_id, NULL); 01393 } 01394 01395 ~HDX9Texture() 01396 { 01397 H_SAFE_RELEASE(m_id); 01398 }; 01399 01400 bool Lock(H3DRect *h3drect, void ** data, int * pitch = null) 01401 { 01402 HRESULT hr; 01403 RECT rect; 01404 if (h3drect) 01405 { 01406 rect.top = h3drect->top; 01407 rect.bottom = h3drect->bottom; 01408 rect.right = h3drect->right; 01409 rect.left = h3drect->left; 01410 hr = m_id->LockRect(0, &m_rect, &rect, 0); 01411 } 01412 else 01413 hr = m_id->LockRect(0, &m_rect, 0, 0); 01414 *data = m_rect.pBits; 01415 if (pitch) 01416 *pitch = m_rect.Pitch; 01417 return SUCCEEDED(hr); 01418 } 01419 01420 void Unlock() 01421 { 01422 m_id->UnlockRect(0); 01423 ZERO_STRUCT(&m_rect, D3DLOCKED_RECT); 01424 } 01425 01426 void GenerateMipMaps() 01427 { 01428 m_id->GenerateMipSubLevels(); 01429 } 01430 01431 01432 /* HDX9Texture specific methods */ 01433 /********************************/ 01434 HRESULT GetSurfaceLevel(unsigned int level, LPDIRECT3DSURFACE9 *surface) 01435 { 01436 return m_id->GetSurfaceLevel(level, surface); 01437 } 01438 01439 HRESULT GetLevelDesc(unsigned int level, D3DSURFACE_DESC *desc) 01440 { 01441 return m_id->GetLevelDesc(level, desc); 01442 } 01443 01444 LPDIRECT3DTEXTURE9 GetTexture() 01445 { 01446 return m_id; 01447 } 01448 }; 01449 01450 01451 01452 /***************************************************************************** 01453 ***************************************************************************** 01454 HDX9Actions Class 01455 ***************************************************************************** 01456 *****************************************************************************/ 01457 class HDX9Actions : public H3DActions 01458 { 01459 private: 01460 DX9Data *m_dx9data; 01461 01462 public: 01463 HDX9Actions(){}; 01464 HDX9Actions(DX9Data *dx9data) : 01465 H3DActions(dx9data), 01466 m_dx9data(dx9data) {}; 01467 ~HDX9Actions(){}; 01468 01469 void Begin_Trace(wchar_t *string) { 01470 D3DPERF_BeginEvent(0,string); 01471 }; 01472 void End_Trace() {D3DPERF_EndEvent();}; 01473 01474 H3DVertexBufferCache *CreateVertexBufferCache() {return new HDX9VertexBufferCache();} 01475 H3DIndexBufferCache *CreateIndexBufferCache() {return new HDX9IndexBufferCache();} 01476 H3DIndexedBufferObject* CreateIndexedBufferObject() {return new HDX9IndexedBufferObject();} 01477 H3DIndexedBufferObject* CreateMesh() {return new HDX9Mesh();} 01478 01479 void Clear(int flags, int color, float z_value, int stencil_value) 01480 { 01481 DWORD clearflags = d3dclear(flags); 01482 m_dx9data->pDevice->Clear(0, NULL, clearflags, color, z_value, stencil_value); 01483 } 01484 01485 void SetViewport(H3DVIEWPORT const *hvp) 01486 { 01487 D3DVIEWPORT9 vp = d3dviewport(hvp); 01488 m_dx9data->pDevice->SetViewport(&vp); 01489 } 01490 01491 /************************/ 01492 /* Define/Bind Textures */ 01493 /************************/ 01494 void define_face_pattern (HT_Display_Context alter * dc, int face_pattern, int user_pattern = 0, int transparency_stipple = 0); 01495 bool bind_texture(const HT_Net_Rendition *nr, HT_Texture *txr, int usage, H3DTexture *id, int texture_unit); 01496 01497 01498 /*****************************/ 01499 /* Texture Creation/Deletion */ 01500 /*****************************/ 01501 bool CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned int usage, H3DFORMAT z_format, H3DTexture **id); 01502 void SetTexture(int unit, H3DTexture *id) 01503 { 01504 if (id) 01505 m_dx9data->pDevice->SetTexture(unit, ((HDX9Texture *) id)->GetTexture()); 01506 else 01507 m_dx9data->pDevice->SetTexture(unit, 0); 01508 } 01509 01510 01511 /****************************/ 01512 /* Shader Creation/Deletion */ 01513 /****************************/ 01514 H3DShader *CreateShader(H3DShaderID id) 01515 { 01516 return new HDX9Shader(id); 01517 }; 01518 void DeleteShader(H3DShader *shader) 01519 { 01520 delete (HDX9Shader *) shader; 01521 }; 01522 01523 /************************/ 01524 /* Device state "force" */ 01525 /************************/ 01526 void force_vf(H3DVertexFormat vf) 01527 { 01528 m_dx9data->h3dcache.vf = vf; 01529 m_dx9data->pDevice->SetFVF(vf2fvf(vf)); 01530 } 01531 01532 void force_scissor(bool mode) 01533 { 01534 if (m_dx9data->can_scissor) { 01535 INVALIDATE_SCISSOR_SET(m_dx9data); 01536 m_dx9data->cache.scissoring = mode; 01537 if (mode) 01538 m_dx9data->pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 01539 else 01540 m_dx9data->pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 01541 } 01542 } 01543 01544 void force_shade_mode(H3DSHADEMODE mode) 01545 { 01546 m_dx9data->cache.shade_mode = mode; 01547 m_dx9data->pDevice->SetRenderState(D3DRS_SHADEMODE, d3dshademode(mode)); 01548 } 01549 01550 void force_culling(H3DCULL mode) 01551 { 01552 if (mode == H3DCULL_NONE) 01553 m_dx9data->culling = false; 01554 else 01555 m_dx9data->culling = true; 01556 m_dx9data->cache.cull_mode = mode; 01557 m_dx9data->pDevice->SetRenderState(D3DRS_CULLMODE, d3dcull(mode)); 01558 } 01559 01560 void force_zbuffering(bool mode) 01561 { 01562 if (!mode) 01563 m_dx9data->pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 01564 else { 01565 if (m_dx9data->cache.depth_test_reversed) 01566 m_dx9data->pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER); 01567 else 01568 m_dx9data->pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); 01569 } 01570 m_dx9data->cache.zbuffering = mode; 01571 } 01572 01573 void force_depth_mask(bool mode) 01574 { 01575 m_dx9data->cache.depth_mask = mode; 01576 if (mode) 01577 m_dx9data->pDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE); 01578 else 01579 m_dx9data->pDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE); 01580 } 01581 01582 void force_depth_range_set(float zmin, float zmax) 01583 { 01584 D3DVIEWPORT9 vp; 01585 vp.X = m_dx9data->cache.viewport.X; 01586 vp.Y = m_dx9data->cache.viewport.Y; 01587 vp.Width = m_dx9data->cache.viewport.Width; 01588 vp.Height = m_dx9data->cache.viewport.Height; 01589 vp.MinZ = m_dx9data->cache.z_range[0] = zmin; 01590 vp.MaxZ = m_dx9data->cache.z_range[1] = zmax; 01591 m_dx9data->pDevice->SetViewport(&vp); 01592 } 01593 01594 void force_anti_alias(bool mode) 01595 { 01596 m_dx9data->cache.antialias = mode; 01597 m_dx9data->pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, mode); 01598 } 01599 01600 void force_color_mask(bool mode) 01601 { 01602 if (!mode) \ 01603 m_dx9data->pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000); /*glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);*/ \ 01604 else \ 01605 m_dx9data->pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA); /*glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);*/ \ 01606 m_dx9data->cache.color_mask = mode; \ 01607 } 01608 01609 void force_transparency(bool mode) 01610 { 01611 if (mode) { 01612 m_dx9data->cache.transparency_on = true; 01613 m_dx9data->pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 01614 } 01615 else { 01616 m_dx9data->cache.transparency_on = false; 01617 m_dx9data->pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 01618 } 01619 } 01620 01621 01622 01623 void set_dc_xform (HT_Net_Rendition const * nr); 01624 void set_3d_xform (HT_Net_Rendition const * nr); 01625 }; // HDX9Actions 01626 01627 01628 #endif // DX9DATA_ONLY 01629 01630 #pragma warning(default : 4710) 01631 01632 #endif // __DX9DRIVE_H_DEFINED__ 01633 01634