00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "dxGraphicsStateGuardian8.h"
00020 #include "config_dxgsg8.h"
00021 #include <d3dx8.h>
00022 #include "displayRegion.h"
00023 #include "renderBuffer.h"
00024 #include "geom.h"
00025 #include "geomSphere.h"
00026 #include "geomIssuer.h"
00027 #include "graphicsWindow.h"
00028 #include "graphicsChannel.h"
00029 #include "lens.h"
00030 #include "perspectiveLens.h"
00031 #include "ambientLight.h"
00032 #include "directionalLight.h"
00033 #include "pointLight.h"
00034 #include "spotlight.h"
00035 #include "textureAttrib.h"
00036 #include "lightAttrib.h"
00037 #include "cullFaceAttrib.h"
00038 #include "transparencyAttrib.h"
00039 #include "alphaTestAttrib.h"
00040 #include "depthTestAttrib.h"
00041 #include "depthWriteAttrib.h"
00042 #include "colorWriteAttrib.h"
00043 #include "texMatrixAttrib.h"
00044 #include "materialAttrib.h"
00045 #include "renderModeAttrib.h"
00046 #include "fogAttrib.h"
00047 #include "depthOffsetAttrib.h"
00048 #include "fog.h"
00049
00050 #ifdef DO_PSTATS
00051 #include "pStatTimer.h"
00052 #include "pStatCollector.h"
00053 #endif
00054
00055
00056 #pragma warning (disable : 4201)
00057
00058 #include <mmsystem.h>
00059
00060
00061
00062
00063
00064
00065 #define DISABLE_POLYGON_OFFSET_DECALING
00066
00067
00068
00069
00070
00071
00072
00073
00074 const int VERT_BUFFER_SIZE = (32*6*1024L);
00075
00076
00077
00078 #define NO_MULTIPLE_DISPLAY_REGIONS
00079
00080 TypeHandle DXGraphicsStateGuardian8::_type_handle;
00081
00082
00083
00084 typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly,
00085 Normal_TexCoord,Color_TexCoord,Normal_Color_TexCoord
00086 } DrawLoopFlags;
00087
00088 #define PER_NORMAL NormalOnly
00089 #define PER_COLOR ColorOnly
00090 #define PER_TEXCOORD TexCoordOnly
00091
00092
00093 #define VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART 4
00094
00095 static D3DMATRIX matIdentity;
00096
00097 #define __D3DLIGHT_RANGE_MAX ((float)sqrt(FLT_MAX)) //for some reason this is missing in dx8 hdrs
00098
00099 #ifdef COUNT_DRAWPRIMS
00100
00101 static DWORD cDPcount=0;
00102 static DWORD cVertcount=0;
00103 static DWORD cTricount=0;
00104 static DWORD cGeomcount=0;
00105
00106 static IDirect3DTexture8 *pLastTexture=NULL;
00107 static DWORD cDP_noTexChangeCount=0;
00108 static LPDIRECT3DDEVICE8 global_pD3DDevice = NULL;
00109
00110 static void CountDPs(DWORD nVerts,DWORD nTris) {
00111 cDPcount++;
00112 cVertcount+=nVerts;
00113 cTricount+=nTris;
00114
00115 if(_pCurDeviceTexture==pLastTexture) {
00116 cDP_noTexChangeCount++;
00117 } else pLastTexture = _pCurDeviceTexture;
00118 }
00119 #else
00120 #define CountDPs(nv,nt)
00121 #endif
00122
00123 #define MY_D3DRGBA(r,g,b,a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r,g,b,a))
00124
00125 #if defined(DO_PSTATS) || defined(PRINT_RESOURCESTATS)
00126 static bool bTexStatsRetrievalImpossible=false;
00127 #endif
00128
00129
00130
00131 INLINE DWORD
00132 Colorf_to_D3DCOLOR(const Colorf &cColorf) {
00133
00134 #if defined(_M_IX86) || defined(_X86_)
00135 DWORD d3dcolor,tempcolorval=255;
00136
00137
00138
00139
00140 __asm {
00141 push ebx ; want to save this in case this fn is inlined
00142 push ecx
00143 mov ecx, cColorf
00144 fild tempcolorval
00145 fld DWORD PTR [ecx]
00146 fmul ST(0),ST(1)
00147 fistp tempcolorval ; no way to store directly to int register
00148 mov eax, tempcolorval
00149 shl eax, 16
00150
00151 fld DWORD PTR [ecx+4] ;grn
00152 fmul ST(0),ST(1)
00153 fistp tempcolorval
00154 mov ebx,tempcolorval
00155 shl ebx, 8
00156 or eax,ebx
00157
00158 fld DWORD PTR [ecx+8] ;blue
00159 fmul ST(0),ST(1)
00160 fistp tempcolorval
00161 or eax,tempcolorval
00162
00163 fld DWORD PTR [ecx+12] ;alpha
00164 fmul ST(0),ST(1)
00165 fistp tempcolorval
00166 ; simulate pop 255.0 off FP stack w/o store, mark top as empty and increment stk ptr
00167 ffree ST(0)
00168 fincstp
00169 mov ebx,tempcolorval
00170 shl ebx, 24
00171 or eax,ebx
00172 mov d3dcolor,eax
00173 pop ecx
00174 pop ebx
00175 }
00176
00177
00178 return d3dcolor;
00179 #else
00180 return MY_D3DRGBA(cColorf[0], cColorf[1], cColorf[2], cColorf[3]);
00181 #endif
00182 }
00183
00184 void DXGraphicsStateGuardian8::
00185 set_color_clear_value(const Colorf& value) {
00186 _color_clear_value = value;
00187 _d3dcolor_clear_value = Colorf_to_D3DCOLOR(value);
00188 }
00189
00190 DXShaderHandle DXGraphicsStateGuardian8::
00191 read_pixel_shader(string &filename) {
00192 HRESULT hr;
00193 DXShaderHandle hShader=NULL;
00194 HANDLE hFile=NULL;
00195 BYTE *pShaderBytes=NULL;
00196 LPD3DXBUFFER pD3DXBuf_Constants=NULL,pD3DXBuf_CompiledShader=NULL,pD3DXBuf_CompilationErrors=NULL;
00197
00198 assert(_pD3DDevice!=NULL);
00199 assert(_pScrn->bCanUsePixelShaders);
00200 bool bIsCompiledShader=(filename.find(".pso")!=string::npos);
00201
00202 if(bIsCompiledShader) {
00203 hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
00204 if(hFile == INVALID_HANDLE_VALUE) {
00205 dxgsg8_cat.error() << "Could not find shader file '"<< filename << "'\n";
00206 return NULL;
00207 }
00208
00209 UINT BytesRead,FileSize = GetFileSize(hFile, NULL);
00210
00211 pShaderBytes = new BYTE[FileSize];
00212 if (pShaderBytes==NULL) {
00213 dxgsg8_cat.error() << "MemAlloc failed for shader file '"<< filename << "'\n";
00214 goto exit_create_pshader;
00215 }
00216
00217 ReadFile(hFile, (void*)pShaderBytes, FileSize, (LPDWORD)&BytesRead, NULL);
00218 assert(BytesRead==FileSize);
00219 } else {
00220 #if defined(NDEBUG) && !defined(COMPILE_TEXT_SHADERFILES)
00221
00222 dxgsg8_cat.error() << "publish build only reads .vso compiled shaders!\n";
00223 exit(1);
00224 #else
00225
00226 WIN32_FIND_DATA Junk;
00227 HANDLE FindFileHandle = FindFirstFile(filename.c_str(),&Junk);
00228 if ( FindFileHandle == INVALID_HANDLE_VALUE ) {
00229 dxgsg8_cat.error() << "Could not find shader file '"<< filename << "'\n";
00230 return NULL;
00231 }
00232 FindClose(FindFileHandle);
00233
00234 hr = D3DXAssembleShaderFromFile(filename.c_str(),D3DXASM_DEBUG,NULL,&pD3DXBuf_CompiledShader,&pD3DXBuf_CompilationErrors);
00235 if(FAILED(hr)) {
00236 dxgsg8_cat.error() << "D3DXAssembleShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
00237 if(pD3DXBuf_CompilationErrors!=NULL) {
00238 dxgsg8_cat.error() << "Compilation Errors: " << (char*) pD3DXBuf_CompilationErrors->GetBufferPointer() << endl;
00239 }
00240 exit(1);
00241 }
00242 assert(pD3DXBuf_CompilationErrors==NULL);
00243 #endif
00244 }
00245
00246 hr = _pD3DDevice->CreatePixelShader((DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes),
00247 &hShader);
00248 if (FAILED(hr)) {
00249 dxgsg8_cat.error() << "CreatePixelShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
00250 hShader=NULL;
00251 }
00252
00253 assert(hShader!=NULL);
00254
00255 #ifdef _DEBUG
00256 dxgsg8_cat.debug() << "CreatePixelShader succeeded for "<< filename << endl;
00257 #endif
00258
00259 exit_create_pshader:
00260 SAFE_RELEASE(pD3DXBuf_CompiledShader);
00261 if(hFile!=NULL)
00262 CloseHandle(hFile);
00263 SAFE_DELETE(pShaderBytes);
00264 return hShader;
00265 }
00266
00267
00268 DXShaderHandle DXGraphicsStateGuardian8::
00269 read_vertex_shader(string &filename) {
00270 #ifndef USE_VERTEX_SHADERS
00271 return NULL;
00272 #else
00273 HRESULT hr;
00274 DXShaderHandle hShader=NULL;
00275 HANDLE hFile=NULL;
00276 BYTE *pShaderBytes=NULL;
00277 LPD3DXBUFFER pD3DXBuf_Constants=NULL,pD3DXBuf_CompiledShader=NULL,pD3DXBuf_CompilationErrors=NULL;
00278 #define VSDDECL_BUFSIZE 1024
00279 UINT ShaderDeclHeader[VSDDECL_BUFSIZE];
00280
00281
00282
00283 UINT Predefined_DeclArray[] = {
00284 D3DVSD_STREAM(0),
00285 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),
00286 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR ),
00287
00288 };
00289
00290 memcpy(ShaderDeclHeader,Predefined_DeclArray,sizeof(Predefined_DeclArray));
00291
00292
00293 UINT ShaderDeclHeader_UINTSize=sizeof(Predefined_DeclArray)/sizeof(UINT);
00294
00295 assert(_pD3DDevice!=NULL);
00296 bool bIsCompiledShader=(filename.find(".vso")!=string::npos);
00297
00298 if(bIsCompiledShader) {
00299 hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
00300 if(hFile == INVALID_HANDLE_VALUE) {
00301 dxgsg8_cat.error() << "Could not find shader file '"<< filename << "'\n";
00302 return NULL;
00303 }
00304
00305 UINT BytesRead,FileSize = GetFileSize(hFile, NULL);
00306
00307 pShaderBytes = new BYTE[FileSize];
00308 if (pShaderBytes==NULL) {
00309 dxgsg8_cat.error() << "MemAlloc failed for shader file '"<< filename << "'\n";
00310 goto exit_create_vshader;
00311 }
00312
00313 ReadFile(hFile, (void*)pShaderBytes, FileSize, (LPDWORD)&BytesRead, NULL);
00314 assert(BytesRead==FileSize);
00315 } else {
00316 #if defined(NDEBUG) && !defined(COMPILE_TEXT_SHADERFILES)
00317
00318 dxgsg8_cat.error() << "publish build only reads .vso compiled shaders!\n";
00319 exit(1);
00320 #else
00321
00322 WIN32_FIND_DATA Junk;
00323 HANDLE FindFileHandle = FindFirstFile(filename.c_str(),&Junk);
00324 if ( FindFileHandle == INVALID_HANDLE_VALUE ) {
00325 dxgsg8_cat.error() << "Could not find shader file '"<< filename << "'\n";
00326 return NULL;
00327 }
00328 FindClose(FindFileHandle);
00329
00330 hr = D3DXAssembleShaderFromFile(filename.c_str(),D3DXASM_DEBUG,&pD3DXBuf_Constants,&pD3DXBuf_CompiledShader,&pD3DXBuf_CompilationErrors);
00331 if(FAILED(hr)) {
00332 dxgsg8_cat.error() << "D3DXAssembleShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
00333 if(pD3DXBuf_CompilationErrors!=NULL) {
00334 dxgsg8_cat.error() << "Compilation Errors: " << (char*) pD3DXBuf_CompilationErrors->GetBufferPointer() << endl;
00335 }
00336 exit(1);
00337 }
00338 assert(pD3DXBuf_CompilationErrors==NULL);
00339
00340 if(pD3DXBuf_Constants!=NULL) {
00341
00342 memcpy(&ShaderDeclHeader[ShaderDeclHeader_UINTSize],pD3DXBuf_Constants->GetBufferPointer(),pD3DXBuf_Constants->GetBufferSize());
00343 ShaderDeclHeader_UINTSize+=pD3DXBuf_Constants->GetBufferSize()/sizeof(UINT);
00344 pD3DXBuf_Constants->Release();
00345 }
00346 #endif
00347 }
00348
00349 assert(VSDDECL_BUFSIZE >= (ShaderDeclHeader_UINTSize+1));
00350 ShaderDeclHeader[ShaderDeclHeader_UINTSize]=D3DVSD_END();
00351
00352 UINT UsageFlags = (_pScrn->bCanUseHWVertexShaders ? 0x0 : D3DUSAGE_SOFTWAREPROCESSING);
00353 hr = _pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader,
00354 (DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes),
00355 &hShader, UsageFlags);
00356 if(FAILED(hr)) {
00357 dxgsg8_cat.error() << "CreateVertexShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
00358 hShader=NULL;
00359 }
00360
00361 assert(hShader!=NULL);
00362
00363 #ifdef _DEBUG
00364 dxgsg8_cat.debug() << "CreateVertexShader succeeded for "<< filename << endl;
00365 #endif
00366
00367 exit_create_vshader:
00368 SAFE_RELEASE(pD3DXBuf_CompiledShader);
00369 if(hFile!=NULL)
00370 CloseHandle(hFile);
00371 SAFE_DELETE(pShaderBytes);
00372 return hShader;
00373 #endif
00374 }
00375
00376 void DXGraphicsStateGuardian8::
00377 reset_panda_gsg(void) {
00378 GraphicsStateGuardian::reset();
00379
00380
00381
00382
00383 _buffer_mask = (RenderBuffer::T_color |
00384 RenderBuffer::T_back
00385
00386
00387
00388 );
00389
00390
00391
00392
00393 }
00394
00395
00396
00397
00398
00399
00400 DXGraphicsStateGuardian8::
00401 DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
00402 GraphicsStateGuardian(properties) {
00403
00404 reset_panda_gsg();
00405
00406 _pScrn = NULL;
00407
00408 _bDXisReady = false;
00409 _overlay_windows_supported = false;
00410
00411 _pFvfBufBasePtr = NULL;
00412 _index_buf=NULL;
00413
00414
00415 _CurVertexShader = _CurPixelShader = NULL;
00416 _pGlobalTexture = NULL;
00417
00418
00419
00420
00421
00422
00423
00424 ZeroMemory(&matIdentity,sizeof(D3DMATRIX));
00425 matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f;
00426
00427 _cur_read_pixel_buffer=RenderBuffer::T_front;
00428 set_color_clear_value(_color_clear_value);
00429 }
00430
00431
00432
00433
00434
00435
00436 DXGraphicsStateGuardian8::
00437 ~DXGraphicsStateGuardian8() {
00438 if (IS_VALID_PTR(_pD3DDevice))
00439 _pD3DDevice->SetTexture(0, NULL);
00440 _pCurTexContext = NULL;
00441
00442
00443
00444 free_nondx_resources();
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 void DXGraphicsStateGuardian8::
00457 reset() {
00458 reset_panda_gsg();
00459 dxgsg8_cat.error() << "DXGSG reset() not implemented properly yet!\n";
00460
00461
00462
00463
00464 }
00465
00466
00467 void DXGraphicsStateGuardian8::
00468 free_d3d_device(void) {
00469
00470 set_state(RenderState::make_empty());
00471
00472
00473 _bDXisReady = false;
00474
00475 if(_pD3DDevice!=NULL)
00476 for(int i=0;i<D3D_MAXTEXTURESTAGES;i++)
00477 _pD3DDevice->SetTexture(i,NULL);
00478
00479 DeleteAllDeviceObjects();
00480
00481 if (_pD3DDevice!=NULL)
00482 RELEASE(_pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO);
00483
00484 free_nondx_resources();
00485
00486
00487 }
00488
00489
00490
00491
00492
00493
00494
00495 void DXGraphicsStateGuardian8::
00496 free_nondx_resources() {
00497
00498
00499 SAFE_DELETE_ARRAY(_index_buf);
00500 SAFE_DELETE_ARRAY(_pFvfBufBasePtr);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void DXGraphicsStateGuardian8::
00510 dx_init(void) {
00511 HRESULT hr;
00512
00513
00514 set_state(RenderState::make_empty());
00515
00516
00517 assert(_pScrn->pD3D8!=NULL);
00518 assert(_pD3DDevice!=NULL);
00519
00520 ZeroMemory(&_lmodel_ambient,sizeof(Colorf));
00521 _pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0x0);
00522
00523 if(_pFvfBufBasePtr==NULL)
00524 _pFvfBufBasePtr = new BYTE[VERT_BUFFER_SIZE];
00525 if(_index_buf==NULL)
00526 _index_buf = new WORD[PANDA_MAXNUMVERTS];
00527
00528 _pCurFvfBufPtr = NULL;
00529
00530 _clip_plane_bits = 0;
00531 _pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0);
00532
00533 _pD3DDevice->SetRenderState(D3DRS_CLIPPING, true);
00534 _clipping_enabled = true;
00535
00536
00537 _color_writemask = 0xFFFFFFFF;
00538 _CurFVFType = 0x0;
00539
00540 _bGouraudShadingOn = false;
00541 _pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
00542
00543
00544
00545
00546
00547 _depth_test_enabled = true;
00548 _pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, _depth_test_enabled);
00549
00550 _pCurTexContext = NULL;
00551
00552 _line_smooth_enabled = false;
00553 _pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, false);
00554
00555 _color_material_enabled = false;
00556 _normals_enabled = false;
00557
00558 _depth_test_enabled = D3DZB_FALSE;
00559 _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
00560
00561 _blend_enabled = false;
00562 _pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)_blend_enabled);
00563
00564
00565 _pD3DDevice->GetRenderState(D3DRS_SRCBLEND, (DWORD*)&_blend_source_func);
00566 _pD3DDevice->GetRenderState(D3DRS_DESTBLEND, (DWORD*)&_blend_dest_func);
00567
00568 _fog_enabled = false;
00569 _pD3DDevice->SetRenderState(D3DRS_FOGENABLE, _fog_enabled);
00570
00571 _current_projection_mat = LMatrix4f::ident_mat();
00572 _projection_mat_stack_count = 0;
00573 _has_scene_graph_color = false;
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 #ifdef COUNT_DRAWPRIMS
00587 global_pD3DDevice = pDevice;
00588 #endif
00589 _pCurrentGeomContext = NULL;
00590 _bDrawPrimDoSetupVertexBuffer = false;
00591
00592 _last_testcooplevel_result = D3D_OK;
00593
00594 #if 0
00595
00596
00597 _panda_gfx_channel = _win->get_channel(0);
00598 #endif
00599
00600 for(int i=0;i<MAX_POSSIBLE_TEXFMTS;i++) {
00601
00602 D3DFORMAT_FLAG fmtflag=D3DFORMAT_FLAG(1<<i);
00603 hr = _pScrn->pD3D8->CheckDeviceFormat(_pScrn->CardIDNum,D3DDEVTYPE_HAL,_pScrn->DisplayMode.Format,
00604 0x0,D3DRTYPE_TEXTURE,g_D3DFORMATmap[fmtflag]);
00605 if(SUCCEEDED(hr)){
00606 _pScrn->SupportedTexFmtsMask|=fmtflag;
00607 }
00608 }
00609
00610
00611 if(_pScrn->d3dcaps.MaxTextureWidth==0)
00612 _pScrn->d3dcaps.MaxTextureWidth=256;
00613
00614 if(_pScrn->d3dcaps.MaxTextureHeight==0)
00615 _pScrn->d3dcaps.MaxTextureHeight=256;
00616
00617 if ((dx_decal_type==GDT_offset) && !(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBIAS)) {
00618 if(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) {
00619 if(dxgsg8_cat.is_debug())
00620 dxgsg8_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to mask-type decals\n";
00621 dx_decal_type = GDT_mask;
00622 } else {
00623 if(dxgsg8_cat.is_debug())
00624 dxgsg8_cat.debug() << "dx-decal-type 'offset' and color-writemasking not supported by hardware, switching to decal double-draw blend-based masking\n";
00625 dx_decal_type = GDT_blend;
00626 }
00627 }
00628
00629 #ifdef DISABLE_POLYGON_OFFSET_DECALING
00630 if(dx_decal_type==GDT_offset) {
00631 if(dxgsg8_cat.is_spam())
00632 dxgsg8_cat.spam() << "polygon-offset decaling disabled in dxgsg, switching to double-draw decaling\n";
00633
00634 if(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) {
00635 if(dxgsg8_cat.is_debug())
00636 dxgsg8_cat.debug() << "using dx-decal-type 'GDT_mask'\n";
00637 dx_decal_type = GDT_mask;
00638 } else {
00639 if(dxgsg8_cat.is_debug())
00640 dxgsg8_cat.debug() << "dx-decal-type 'mask' not supported by hardware, switching to GDT_blend\n";
00641 dx_decal_type = GDT_blend;
00642 }
00643 }
00644 #endif
00645
00646 if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ)) {
00647 dxgsg8_cat.error() << "dx-decal-types mask&blend impossible to implement, no hardware support for Z-masking, decals will not appear correctly!\n";
00648 }
00649
00650 #define REQUIRED_DESTBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_SRCALPHA)
00651 #define REQUIRED_SRCBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_INVSRCALPHA)
00652
00653 if (((_pScrn->d3dcaps.SrcBlendCaps & REQUIRED_SRCBLENDCAPS)!=REQUIRED_SRCBLENDCAPS) ||
00654 ((_pScrn->d3dcaps.DestBlendCaps & REQUIRED_DESTBLENDCAPS)!=REQUIRED_DESTBLENDCAPS)) {
00655 dxgsg8_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) _pScrn->d3dcaps.SrcBlendCaps << " DestBlendCaps: "<< (void*) _pScrn->d3dcaps.DestBlendCaps << endl;
00656 }
00657
00658
00659 #define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MINFLINEAR)
00660
00661 if ((_pScrn->d3dcaps.TextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) {
00662 dxgsg8_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureFilterCaps << endl;
00663 }
00664
00665 #define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR)
00666
00667
00668 if (!(_pScrn->d3dcaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) {
00669 if(dxgsg8_cat.is_debug())
00670 dxgsg8_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureFilterCaps << endl;
00671 dx_ignore_mipmaps = TRUE;
00672 } else if ((_pScrn->d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS)!=TRILINEAR_MIPMAP_TEXFILTERCAPS) {
00673 if(dxgsg8_cat.is_debug())
00674 dxgsg8_cat.debug() << "device is missing tri-linear mipmap filtering capability, textures may look crappy\n";
00675 } else if(_pScrn->d3dcaps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) {
00676
00677
00678 _pScrn->d3dcaps.TextureFilterCaps &= (~D3DPTFILTERCAPS_MIPFLINEAR);
00679 }
00680
00681 #define REQUIRED_TEXBLENDCAPS (D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2)
00682 if ((_pScrn->d3dcaps.TextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) {
00683 dxgsg8_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureOpCaps << endl;
00684 }
00685
00686 if(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) {
00687
00688
00689 _doFogType=PerPixelFog;
00690 } else {
00691
00692 assert((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0);
00693
00694
00695
00696
00697 if(dx_no_vertex_fog) {
00698 _doFogType = None;
00699 } else {
00700 _doFogType = PerVertexFog;
00701
00702
00703 if(dx_use_rangebased_fog && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE))
00704 _pD3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, true);
00705 }
00706 }
00707
00708 _pScrn->bCanDirectDisableColorWrites=((_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE)!=0);
00709
00710
00711 _pD3DDevice->SetRenderState(D3DRS_LIGHTING, false);
00712
00713
00714 _dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_pScrn->PresParams.BackBufferFormat)
00715 && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER));
00716 _pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, _dither_enabled);
00717
00718 _pD3DDevice->SetRenderState(D3DRS_CLIPPING,true);
00719
00720
00721 _stencil_test_enabled = false;
00722 _pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, _stencil_test_enabled);
00723
00724
00725 enable_line_smooth(false);
00726
00727
00728 _current_fill_mode = RenderModeAttrib::M_filled;
00729 _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
00730
00731 _pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 if(dx_auto_normalize_lighting)
00749 _pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
00750
00751
00752
00753
00754 _CurTexBlendMode = TextureApplyAttrib::M_modulate;
00755 SetTextureBlendMode(_CurTexBlendMode,false);
00756 _texturing_enabled = false;
00757 _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
00758
00759
00760 _CurTexMagFilter=_CurTexMinFilter=_CurTexMipFilter=D3DTEXF_NONE;
00761 _CurTexWrapModeU=_CurTexWrapModeV=Texture::WM_clamp;
00762 _CurTexAnisoDegree=1;
00763
00764
00765
00766
00767 _pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
00768 _pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
00769 _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
00770 _pD3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY,_CurTexAnisoDegree);
00771 _pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU,get_texture_wrap_mode(_CurTexWrapModeU));
00772 _pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV));
00773
00774 #ifdef _DEBUG
00775 if ((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) &&
00776 (dx_global_miplevel_bias!=0.0f)) {
00777 _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) );
00778 }
00779 #endif
00780
00781 #ifndef NDEBUG
00782 if(dx_force_backface_culling!=0) {
00783 if((dx_force_backface_culling > 0) &&
00784 (dx_force_backface_culling < D3DCULL_FORCE_DWORD)) {
00785 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling);
00786 } else {
00787 dx_force_backface_culling=0;
00788 if(dxgsg8_cat.is_debug())
00789 dxgsg8_cat.debug() << "error, invalid value for dx-force-backface-culling\n";
00790 }
00791 }
00792 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling);
00793 #else
00794 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
00795 #endif
00796
00797 _alpha_func = D3DCMP_ALWAYS;
00798 _alpha_func_refval = 1.0f;
00799 _pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, _alpha_func);
00800 _pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT)(_alpha_func_refval*255.0f));
00801 _alpha_test_enabled = false;
00802 _pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, _alpha_test_enabled);
00803
00804
00805
00806 _pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
00807
00808 PRINT_REFCNT(dxgsg8,_pD3DDevice);
00809
00810
00811 CPT(RenderAttrib) dta = DepthTestAttrib::make(DepthTestAttrib::M_less);
00812 CPT(RenderAttrib) dwa = DepthWriteAttrib::make(DepthWriteAttrib::M_on);
00813 CPT(RenderAttrib) cfa = CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise);
00814
00815 dta->issue(this);
00816 dwa->issue(this);
00817 cfa->issue(this);
00818
00819
00820 init_shader(VertexShader,_CurVertexShader,pdx_vertexshader_filename);
00821 init_shader(PixelShader,_CurPixelShader,pdx_pixelshader_filename);
00822
00823 if(pdx_globaltexture_filename!=NULL) {
00824
00825 hr = D3DXCreateTextureFromFile(_pD3DDevice,pdx_globaltexture_filename->c_str(),&_pGlobalTexture);
00826 if(FAILED(hr)) {
00827 dxgsg8_cat.fatal() << "CreateTexFromFile failed" << D3DERRORSTRING(hr);
00828 exit(1);
00829 }
00830
00831 hr=_pD3DDevice->SetTexture(dx_globaltexture_stagenum,_pGlobalTexture);
00832 if(FAILED(hr)) {
00833 dxgsg8_cat.fatal() << "SetTexture failed" << D3DERRORSTRING(hr);
00834 exit(1);
00835 }
00836 }
00837
00838 PRINT_REFCNT(dxgsg8,_pD3DDevice);
00839 }
00840
00841 void DXGraphicsStateGuardian8::
00842 init_shader(ShaderType stype,DXShaderHandle &hShader,string *pFname) {
00843
00844 if((pFname==NULL) || pFname->empty()) {
00845 hShader=NULL;
00846 return;
00847 }
00848
00849 HRESULT hr;
00850
00851 char *sh_typename;
00852 if(stype==VertexShader)
00853 sh_typename="Vertex";
00854 else sh_typename="Pixel";
00855
00856 if((stype==PixelShader) && (!_pScrn->bCanUsePixelShaders)) {
00857 dxgsg8_cat.error() << "HW doesnt support pixel shaders!\n";
00858 exit(1);
00859 }
00860
00861 if((hShader!=NULL)&&(!_pScrn->bIsDX81)) {
00862
00863 if(stype==VertexShader)
00864 hr = _pD3DDevice->DeleteVertexShader(hShader);
00865 else hr = _pD3DDevice->DeletePixelShader(hShader);
00866 if(FAILED(hr))
00867 dxgsg8_cat.error() << "Delete"<< sh_typename<<"Shader failed!" << D3DERRORSTRING(hr);
00868 hShader=NULL;
00869 }
00870
00871 if(hShader==NULL) {
00872
00873
00874
00875 if(stype==VertexShader) {
00876 hShader=read_vertex_shader(*pFname);
00877 hr = _pD3DDevice->SetVertexShader(hShader);
00878 } else {
00879 hShader=read_pixel_shader(*pFname);
00880 hr = _pD3DDevice->SetPixelShader(hShader);
00881 }
00882
00883 if(FAILED(hr))
00884 dxgsg8_cat.error() << "Set"<<sh_typename<<"Shader failed!" << D3DERRORSTRING(hr);
00885 }
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 void DXGraphicsStateGuardian8::
00904 support_overlay_window(bool flag) {
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 }
00934
00935
00936
00937
00938
00939
00940
00941 void DXGraphicsStateGuardian8::
00942 do_clear(const RenderBuffer &buffer) {
00943
00944
00945 nassertv(buffer._gsg == this);
00946 int buffer_type = buffer._buffer_type;
00947
00948 DWORD flags = 0;
00949
00950 if(buffer_type & RenderBuffer::T_depth) {
00951 flags |= D3DCLEAR_ZBUFFER;
00952 assert(_pScrn->PresParams.EnableAutoDepthStencil);
00953 }
00954
00955 if(buffer_type & RenderBuffer::T_back)
00956 flags |= D3DCLEAR_TARGET;
00957
00958 if(buffer_type & RenderBuffer::T_stencil) {
00959 flags |= D3DCLEAR_STENCIL;
00960 assert(_pScrn->PresParams.EnableAutoDepthStencil && IS_STENCIL_FORMAT(_pScrn->PresParams.AutoDepthStencilFormat));
00961 }
00962
00963 HRESULT hr = _pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value,
00964 _depth_clear_value, (DWORD)_stencil_clear_value);
00965 if(FAILED(hr))
00966 dxgsg8_cat.error() << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr);
00967
00968
00969
00970
00971
00972
00973 }
00974
00975
00976
00977
00978
00979
00980
00981 void DXGraphicsStateGuardian8::
00982 prepare_display_region() {
00983 if (_current_display_region == (DisplayRegion*)0L) {
00984 dxgsg8_cat.error()
00985 << "Invalid NULL display region in prepare_display_region()\n";
00986 } else if (_current_display_region != _actual_display_region) {
00987 _actual_display_region = _current_display_region;
00988
00989 int l, b, w, h;
00990 _actual_display_region->get_region_pixels(l, b, w, h);
00991
00992
00993 D3DVIEWPORT8 vp = {l,b,w,h,0.0f,1.0f};
00994 HRESULT hr = _pD3DDevice->SetViewport( &vp );
00995 if (FAILED(hr)) {
00996 dxgsg8_cat.error()
00997 << "SetViewport(" << l << ", " << b << ", " << w << ", " << h
00998 << ") failed" << D3DERRORSTRING(hr);
00999 }
01000
01001 }
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 bool DXGraphicsStateGuardian8::
01018 prepare_lens() {
01019 if (_current_lens == (Lens *)NULL) {
01020 return false;
01021 }
01022
01023 if (!_current_lens->is_linear()) {
01024 return false;
01025 }
01026
01027 const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
01028
01029
01030
01031 LMatrix4f new_projection_mat =
01032 LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
01033 projection_mat;
01034
01035 HRESULT hr;
01036 hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
01037 (D3DMATRIX*)new_projection_mat.get_data());
01038 return SUCCEEDED(hr);
01039 }
01040
01041 #ifndef NO_MULTIPLE_DISPLAY_REGIONS
01042
01043
01044
01045
01046
01047 void DXGraphicsStateGuardian8::set_clipper(RECT cliprect) {
01048
01049 LPDIRECTDRAWCLIPPER Clipper;
01050 HRESULT result;
01051
01052
01053
01054 if (dx_full_screen) return;
01055
01056
01057
01058
01059
01060
01061
01062 clip_rect = cliprect;
01063 cliprect.left += _view_rect.left;
01064 cliprect.right += _view_rect.left;
01065 cliprect.top += _view_rect.top;
01066 cliprect.bottom += _view_rect.top;
01067 RGNDATA *rgn_data = (RGNDATA *)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT));
01068 HRGN hrgn = CreateRectRgn(cliprect.left, cliprect.top, cliprect.right, cliprect.bottom);
01069 GetRegionData(hrgn, sizeof(RGNDATAHEADER) + sizeof(RECT), rgn_data);
01070
01071 if (_pD3DDevicesPrimary->GetClipper(&Clipper) != DD_OK) {
01072 result = _pD3DDevice->CreateClipper(0, &Clipper, NULL);
01073 result = Clipper->SetClipList(rgn_data, 0);
01074 result = _pD3DDevicesPrimary->SetClipper(Clipper);
01075 } else {
01076 result = Clipper->SetClipList(rgn_data, 0 );
01077 if (result == DDERR_CLIPPERISUSINGHWND) {
01078 result = _pD3DDevicesPrimary->SetClipper(NULL);
01079 result = _pD3DDevice->CreateClipper(0, &Clipper, NULL);
01080 result = Clipper->SetClipList(rgn_data, 0 ) ;
01081 result = _pD3DDevicesPrimary->SetClipper(Clipper);
01082 }
01083 }
01084 free(rgn_data);
01085 DeleteObject(hrgn);
01086 }
01087 #endif
01088
01089 #if defined(_DEBUG) || defined(COUNT_DRAWPRIMS)
01090 typedef enum {DrawPrim,DrawIndexedPrim} DP_Type;
01091 static const char *DP_Type_Strs[3] = {"DrawPrimitive","DrawIndexedPrimitive"};
01092
01093 void INLINE TestDrawPrimFailure(DP_Type dptype,HRESULT hr,IDirect3DDevice8 *pD3DDevice,DWORD nVerts,DWORD nTris) {
01094 if(FAILED(hr)) {
01095
01096 HRESULT testcooplvl_hr = pD3DDevice->TestCooperativeLevel();
01097 if((testcooplvl_hr != D3DERR_DEVICELOST)||(testcooplvl_hr != D3DERR_DEVICENOTRESET)) {
01098 dxgsg8_cat.fatal() << DP_Type_Strs[dptype] << "() failed: result = " << D3DERRORSTRING(hr);
01099 exit(1);
01100 }
01101 }
01102
01103 CountDPs(nVerts,nTris);
01104 }
01105 #else
01106 #define TestDrawPrimFailure(a,b,c,nVerts,nTris) CountDPs(nVerts,nTris);
01107 #endif
01108
01109
01110
01111
01112
01113
01114 void DXGraphicsStateGuardian8::
01115 report_texmgr_stats() {
01116
01117 #if defined(DO_PSTATS)||defined(PRINT_RESOURCESTATS)
01118 HRESULT hr;
01119
01120 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
01121 DWORD dwTexTotal,dwTexFree,dwVidTotal,dwVidFree;
01122
01123 #ifndef PRINT_RESOURCESTATS
01124 if (_total_texmem_pcollector.is_active())
01125 #endif
01126 {
01127 DDSCAPS2 ddsCaps;
01128
01129 ZeroMemory(&ddsCaps,sizeof(ddsCaps));
01130
01131 ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
01132 if(FAILED( hr = _pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) {
01133 dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr);
01134 exit(1);
01135 }
01136
01137 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
01138 if(FAILED( hr = _pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) {
01139 dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr);
01140 exit(1);
01141 }
01142 }
01143 #endif
01144
01145 D3DDEVINFO_RESOURCEMANAGER all_resource_stats;
01146 ZeroMemory(&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER));
01147
01148 if(!bTexStatsRetrievalImpossible) {
01149 hr = _pD3DDevice->GetInfo(D3DDEVINFOID_RESOURCEMANAGER,&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER));
01150 if (hr!=D3D_OK) {
01151 if (hr==S_FALSE) {
01152 static int PrintedMsg=2;
01153 if(PrintedMsg>0) {
01154 if(dxgsg8_cat.is_debug())
01155 dxgsg8_cat.debug() << "Error: texstats GetInfo() requires debug DX DLLs to be installed!! ***********\n";
01156 ZeroMemory(&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER));
01157 bTexStatsRetrievalImpossible=true;
01158 }
01159 } else {
01160 dxgsg8_cat.error() << "GetInfo(RESOURCEMANAGER) failed to get tex stats: result = " << D3DERRORSTRING(hr);
01161 return;
01162 }
01163 }
01164 }
01165
01166 #ifdef PRINT_RESOURCESTATS
01167 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
01168 char tmpstr1[50],tmpstr2[50],tmpstr3[50],tmpstr4[50];
01169 sprintf(tmpstr1,"%.4g",dwVidTotal/1000000.0);
01170 sprintf(tmpstr2,"%.4g",dwVidFree/1000000.0);
01171 sprintf(tmpstr3,"%.4g",dwTexTotal/1000000.0);
01172 sprintf(tmpstr4,"%.4g",dwTexFree/1000000.0);
01173 dxgsg8_cat.debug() << "\nAvailableVidMem for RenderSurfs: (megs) total: " << tmpstr1 << " free: " << tmpstr2
01174 << "\nAvailableVidMem for Textures: (megs) total: " << tmpstr3 << " free: " << tmpstr4 << endl;
01175 #endif
01176
01177 #define REAL_D3DRTYPECOUNT ((UINT) D3DRTYPE_INDEXBUFFER) // d3d boneheads defined D3DRTYPECOUNT wrong
01178 static char *ResourceNameStrs[REAL_D3DRTYPECOUNT]={"SURFACE","VOLUME","TEXTURE","VOLUME TEXTURE","CUBE TEXTURE","VERTEX BUFFER","INDEX BUFFER"};
01179 static bool bDoGetInfo[REAL_D3DRTYPECOUNT]={true,false,true,false,false,true,false};
01180
01181 if(!bTexStatsRetrievalImpossible) {
01182 for(UINT r=0; r<(UINT)REAL_D3DRTYPECOUNT;r++) {
01183 if(!bDoGetInfo[r])
01184 continue;
01185
01186 D3DRESOURCESTATS *pRStats=&all_resource_stats.stats[r];
01187 if(pRStats->NumUsed>0) {
01188 char hitrate_str[20];
01189 float fHitRate = (pRStats->NumUsedInVidMem * 100.0f) / pRStats->NumUsed;
01190 sprintf(hitrate_str,"%.1f",fHitRate);
01191
01192 dxgsg8_cat.spam()
01193 << "\n***** Stats for " << ResourceNameStrs[r] << " ********"
01194 << "\n HitRate:\t" << hitrate_str << "%"
01195 << "\n bThrashing:\t" << pRStats->bThrashing
01196 << "\n NumEvicts:\t" << pRStats->NumEvicts
01197 << "\n NumVidCreates:\t" << pRStats->NumVidCreates
01198 << "\n NumUsed:\t" << pRStats->NumUsed
01199 << "\n NumUsedInVidMem:\t" << pRStats->NumUsedInVidMem
01200 << "\n WorkingSet:\t" << pRStats->WorkingSet
01201 << "\n WorkingSetBytes:\t" << pRStats->WorkingSetBytes
01202 << "\n ApproxBytesDownloaded:\t" << pRStats->ApproxBytesDownloaded
01203 << "\n TotalManaged:\t" << pRStats->TotalManaged
01204 << "\n TotalBytes:\t" << pRStats->TotalBytes
01205 << "\n LastPri:\t" << pRStats->LastPri << endl;
01206 } else {
01207 dxgsg8_cat.spam()
01208 << "\n***** Stats for " << ResourceNameStrs[r] << " ********"
01209 << "\n NumUsed: 0\n";
01210 }
01211 }
01212
01213 D3DDEVINFO_D3DVERTEXSTATS vtxstats;
01214 ZeroMemory(&vtxstats,sizeof(D3DDEVINFO_D3DVERTEXSTATS));
01215 hr = _pD3DDevice->GetInfo(D3DDEVINFOID_VERTEXSTATS,&vtxstats,sizeof(D3DDEVINFO_D3DVERTEXSTATS));
01216 if (hr!=D3D_OK) {
01217 dxgsg8_cat.error() << "GetInfo(D3DVERTEXSTATS) failed : result = " << D3DERRORSTRING(hr);
01218 return;
01219 } else {
01220 dxgsg8_cat.spam()
01221 << "\n***** Triangle Stats ********"
01222 << "\n NumRenderedTriangles:\t" << vtxstats.NumRenderedTriangles
01223 << "\n NumExtraClippingTriangles:\t" << vtxstats.NumExtraClippingTriangles << endl;
01224 }
01225 }
01226 #endif
01227
01228 #ifdef DO_PSTATS
01229
01230
01231 if (_texmgrmem_total_pcollector.is_active()) {
01232
01233 _texmgrmem_total_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].TotalBytes);
01234 _texmgrmem_resident_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].WorkingSetBytes);
01235 }
01236 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
01237 if (_total_texmem_pcollector.is_active()) {
01238 _total_texmem_pcollector.set_level(dwTexTotal);
01239 _used_texmem_pcollector.set_level(dwTexTotal - dwTexFree);
01240 }
01241 #endif
01242 #endif
01243 #endif
01244 }
01245
01246
01247
01248
01249
01250
01251 INLINE void DXGraphicsStateGuardian8::
01252 add_to_FVFBuf(void *data, size_t bytes) {
01253 memcpy(_pCurFvfBufPtr, data, bytes);
01254 _pCurFvfBufPtr += bytes;
01255 }
01256
01257
01258 #define add_DWORD_to_FVFBuf(data) { *((DWORD *)_pCurFvfBufPtr) = (DWORD) data; _pCurFvfBufPtr += sizeof(DWORD);}
01259
01260 typedef enum {
01261 FlatVerts,IndexedVerts,MixedFmtVerts
01262 } GeomVertFormat;
01263
01264 #define COPYVERTDATA_2_VERTEXBUFFER(PrimType,NumVertices) { \
01265 DWORD numVertBytes=_pCurFvfBufPtr-_pFvfBufBasePtr; \
01266 memcpy(_pCurrentGeomContext->_pEndofVertData,_pFvfBufBasePtr,numVertBytes); \
01267 DPInfo dpInfo; \
01268 dpInfo.nVerts=NumVertices; \
01269 dpInfo.primtype=PrimType; \
01270 _pCurrentGeomContext->_PrimInfo.push_back(dpInfo); \
01271 _pCurrentGeomContext->_num_verts+=dpInfo.nVerts; \
01272 _pCurrentGeomContext->_pEndofVertData+=numVertBytes; }
01273
01274
01275 INLINE void DXGraphicsStateGuardian8::
01276 transform_color(Colorf &InColor,D3DCOLOR &OutRGBAColor) {
01277 Colorf transformed
01278 ((InColor[0] * _current_color_scale[0]) + _current_color_offset[0],
01279 (InColor[1] * _current_color_scale[1]) + _current_color_offset[1],
01280 (InColor[2] * _current_color_scale[2]) + _current_color_offset[2],
01281 (InColor[3] * _current_color_scale[3]) + _current_color_offset[3]);
01282 OutRGBAColor = Colorf_to_D3DCOLOR(transformed);
01283 }
01284
01285
01286
01287
01288
01289
01290 size_t DXGraphicsStateGuardian8::
01291 draw_prim_setup(const Geom *geom) {
01292
01293
01294
01295
01296
01297
01298 #ifdef _DEBUG
01299 assert(geom->get_binding(G_COORD) != G_OFF);
01300 #endif
01301
01302 #define GET_NEXT_VERTEX(NEXTVERT) { NEXTVERT = geom->get_next_vertex(vi); }
01303 #define GET_NEXT_NORMAL() { p_normal = geom->get_next_normal(ni); }
01304 #define GET_NEXT_TEXCOORD() { p_texcoord = geom->get_next_texcoord(ti); }
01305
01306 #define GET_NEXT_COLOR() { \
01307 Colorf tempcolor = geom->get_next_color(ci); \
01308 if(_color_transform_enabled == 0) { \
01309 _curD3Dcolor = Colorf_to_D3DCOLOR(tempcolor); \
01310 } else { \
01311 transform_color(tempcolor,_curD3Dcolor); \
01312 }}
01313
01314
01315
01316
01317 PTA_Vertexf coords;
01318 PTA_ushort vindexes;
01319
01320 geom->get_coords(coords,vindexes);
01321 if(vindexes!=NULL) {
01322 _pCurCoordIndex = _coordindex_array = &vindexes[0];
01323 } else {
01324 _pCurCoordIndex = _coordindex_array = NULL;
01325 }
01326 _pCurCoord = _coord_array = &coords[0];
01327
01328
01329
01330 vi = geom->make_vertex_iterator();
01331 DWORD newFVFflags = D3DFVF_XYZ;
01332 size_t vertex_size = sizeof(float) * 3;
01333
01334 GeomBindType ColorBinding=geom->get_binding(G_COLOR);
01335 bool bDoColor=(ColorBinding != G_OFF);
01336
01337 if (bDoColor || _has_scene_graph_color) {
01338 ci = geom->make_color_iterator();
01339 newFVFflags |= D3DFVF_DIFFUSE;
01340 vertex_size += sizeof(D3DCOLOR);
01341
01342 if (_has_scene_graph_color) {
01343 if (_scene_graph_color_stale) {
01344
01345 if(_color_transform_enabled == 0) {
01346 _scene_graph_color_D3DCOLOR = Colorf_to_D3DCOLOR(_scene_graph_color);
01347 } else {
01348 transform_color(_scene_graph_color, _scene_graph_color_D3DCOLOR);
01349 }
01350 _scene_graph_color_stale = false;
01351 }
01352 _curD3Dcolor = _scene_graph_color_D3DCOLOR;
01353
01354 _perVertex &= ~PER_COLOR;
01355 _perPrim &= ~PER_COLOR;
01356 _perComp &= ~PER_COLOR;
01357 } else if(ColorBinding == G_OVERALL){
01358 GET_NEXT_COLOR();
01359 _perVertex &= ~PER_COLOR;
01360 _perPrim &= ~PER_COLOR;
01361 _perComp &= ~PER_COLOR;
01362 }
01363 }
01364
01365 if (geom->get_binding(G_NORMAL) != G_OFF) {
01366 ni = geom->make_normal_iterator();
01367 newFVFflags |= D3DFVF_NORMAL;
01368 vertex_size += sizeof(float) * 3;
01369
01370 if (geom->get_binding(G_NORMAL) == G_OVERALL)
01371 p_normal = geom->get_next_normal(ni);
01372 }
01373
01374
01375 GeomBindType TexCoordBinding;
01376 PTA_TexCoordf texcoords;
01377 PTA_ushort tindexes;
01378 geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
01379 if (TexCoordBinding != G_OFF) {
01380 assert(TexCoordBinding == G_PER_VERTEX);
01381
01382
01383 if(tindexes!=NULL) {
01384 _pCurTexCoordIndex = _texcoordindex_array = &tindexes[0];
01385 } else {
01386 _pCurTexCoordIndex = _texcoordindex_array = NULL;
01387 }
01388 _pCurTexCoord = _texcoord_array = &texcoords[0];
01389
01390
01391 ti = geom->make_texcoord_iterator();
01392 newFVFflags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
01393 vertex_size += sizeof(float) * 2;
01394 }
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407 bool need_gouraud_shading = ((_perVertex & (PER_COLOR | (wants_normals() ? PER_NORMAL : 0))) || _fog_enabled);
01408
01409 enable_gouraud_shading(need_gouraud_shading);
01410 set_vertex_format(newFVFflags);
01411
01412 return vertex_size;
01413 }
01414
01415
01416
01417
01418
01419
01420
01421 void DXGraphicsStateGuardian8::
01422 draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags) {
01423 Vertexf NextVert;
01424
01425 for(;nVerts > 0;nVerts--) {
01426
01427 GET_NEXT_VERTEX(NextVert);
01428 add_to_FVFBuf((void *)&NextVert, 3*sizeof(float));
01429
01430 if(perFlags==(ushort)TexCoordOnly) {
01431
01432 GET_NEXT_TEXCOORD();
01433 } else {
01434 switch (DrawLoopFlags(perFlags)) {
01435 case Color_TexCoord:
01436 GET_NEXT_TEXCOORD();
01437 case ColorOnly:
01438 GET_NEXT_COLOR();
01439 break;
01440 case Normal_Color:
01441 GET_NEXT_COLOR();
01442 case NormalOnly:
01443 GET_NEXT_NORMAL();
01444 break;
01445 case Normal_Color_TexCoord:
01446 GET_NEXT_COLOR();
01447 case Normal_TexCoord:
01448 GET_NEXT_NORMAL();
01449
01450 GET_NEXT_TEXCOORD();
01451 break;
01452 }
01453 }
01454
01455 if (_CurFVFType & D3DFVF_NORMAL)
01456 add_to_FVFBuf((void *)&p_normal, 3*sizeof(float));
01457 if (_CurFVFType & D3DFVF_DIFFUSE)
01458 add_DWORD_to_FVFBuf(_curD3Dcolor);
01459 if (_CurFVFType & D3DFVF_TEXCOUNT_MASK)
01460 add_to_FVFBuf((void *)&p_texcoord, sizeof(TexCoordf));
01461 }
01462 }
01463
01464
01465
01466
01467
01468
01469
01470 void DXGraphicsStateGuardian8::
01471 draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom) {
01472
01473
01474
01475
01476
01477
01478 #ifdef _DEBUG
01479 {
01480 assert(geom->get_binding(G_NORMAL) == G_OFF);
01481 GeomBindType ColorBinding = geom->get_binding(G_COLOR);
01482 assert((ColorBinding != G_PER_VERTEX) || (ColorBinding != G_PER_COMPONENT));
01483 assert(geom->get_binding(G_TEXCOORD) == G_PER_VERTEX);
01484 }
01485 #endif
01486
01487 Vertexf *pCurCoord = _pCurCoord;
01488 ushort *pCurCoordIndex = _pCurCoordIndex;
01489 TexCoordf *pCurTexCoord = _pCurTexCoord;
01490 ushort *pCurTexCoordIndex = _pCurTexCoordIndex;
01491
01492 BYTE *pLocalFvfBufPtr = _pCurFvfBufPtr;
01493 DWORD cur_color = _curD3Dcolor;
01494 bool bDoIndexedTexCoords = (_texcoordindex_array != NULL);
01495 bool bDoIndexedCoords = (_coordindex_array != NULL);
01496
01497 for(;nVerts>0;nVerts--) {
01498 if(bDoIndexedCoords) {
01499 memcpy(pLocalFvfBufPtr,(void*)&_coord_array[*pCurCoordIndex],3*sizeof(float));
01500 pCurCoordIndex++;
01501 } else {
01502 memcpy(pLocalFvfBufPtr,(void*)pCurCoord,3*sizeof(float));
01503 pCurCoord++;
01504 }
01505
01506 pLocalFvfBufPtr+=3*sizeof(float);
01507
01508 *((DWORD *)pLocalFvfBufPtr) = cur_color;
01509 pLocalFvfBufPtr += sizeof(DWORD);
01510
01511 if(bDoIndexedTexCoords) {
01512 memcpy(pLocalFvfBufPtr,(void*)&_texcoord_array[*pCurTexCoordIndex],sizeof(TexCoordf));
01513 pCurTexCoordIndex++;
01514 } else {
01515 memcpy(pLocalFvfBufPtr,(void*)pCurTexCoord,sizeof(TexCoordf));
01516 pCurTexCoord++;
01517 }
01518 pLocalFvfBufPtr+=sizeof(TexCoordf);
01519 }
01520
01521 _pCurFvfBufPtr=pLocalFvfBufPtr;
01522 _pCurCoord = pCurCoord;
01523 _pCurCoordIndex = pCurCoordIndex;
01524 _pCurTexCoord = pCurTexCoord;
01525 _pCurTexCoordIndex = pCurTexCoordIndex;
01526 }
01527
01528
01529
01530
01531
01532
01533 void DXGraphicsStateGuardian8::
01534 draw_point(GeomPoint *geom, GeomContext *gc) {
01535
01536 #ifdef GSG_VERBOSE
01537 dxgsg8_cat.debug() << "draw_point()" << endl;
01538 #endif
01539
01540 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
01541 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
01542
01543
01544
01545 int nPrims = geom->get_num_prims();
01546
01547 if (nPrims==0) {
01548 dxgsg8_cat.warning() << "draw_point() called with ZERO vertices!!" << endl;
01549 return;
01550 }
01551
01552 #ifdef _DEBUG
01553 static bool bPrintedMsg=false;
01554
01555 if (!bPrintedMsg && (geom->get_size()!=1.0f)) {
01556 bPrintedMsg=true;
01557 dxgsg8_cat.warning() << "D3D does not support drawing points of non-unit size, setting point size to 1.0f!\n";
01558 }
01559 #endif
01560
01561 nassertv(nPrims < PANDA_MAXNUMVERTS );
01562
01563 PTA_Vertexf coords;
01564 PTA_Normalf norms;
01565 PTA_Colorf colors;
01566 PTA_TexCoordf texcoords;
01567 GeomBindType bind;
01568 PTA_ushort vindexes,nindexes,tindexes,cindexes;
01569
01570 geom->get_coords(coords,vindexes);
01571 geom->get_normals(norms,bind,nindexes);
01572 geom->get_colors(colors,bind,cindexes);
01573 geom->get_texcoords(texcoords,bind,tindexes);
01574
01575
01576
01577
01578
01579 _perVertex = 0x0;
01580 _perPrim = 0;
01581 if (geom->get_binding(G_NORMAL) == G_PER_VERTEX) _perVertex |= PER_NORMAL;
01582 if (geom->get_binding(G_COLOR) == G_PER_VERTEX) _perVertex |= PER_COLOR;
01583
01584 size_t vertex_size = draw_prim_setup(geom);
01585
01586 nassertv(_pCurFvfBufPtr == NULL);
01587 nassertv(nPrims * vertex_size < VERT_BUFFER_SIZE);
01588 _pCurFvfBufPtr = _pFvfBufBasePtr;
01589
01590
01591 draw_prim_inner_loop(nPrims, geom, _perVertex | _perPrim);
01592
01593 if(!_bDrawPrimDoSetupVertexBuffer) {
01594 HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nPrims, _pFvfBufBasePtr, vertex_size);
01595 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nPrims,0);
01596 } else {
01597 COPYVERTDATA_2_VERTEXBUFFER(D3DPT_POINTLIST,nPrims);
01598 }
01599
01600
01601 _pCurFvfBufPtr = NULL;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610 void DXGraphicsStateGuardian8::
01611 draw_line(GeomLine* geom, GeomContext *gc) {
01612
01613 #ifdef GSG_VERBOSE
01614 dxgsg8_cat.debug() << "draw_line()" << endl;
01615 #endif
01616 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
01617 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
01618
01619 #ifdef _DEBUG
01620 static bool bPrintedMsg=false;
01621
01622
01623
01624 if (!bPrintedMsg && (geom->get_width()!=1.0f)) {
01625 bPrintedMsg=true;
01626 if(dxgsg8_cat.is_debug())
01627 dxgsg8_cat.debug() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n";
01628 }
01629 #endif
01630
01631 int nPrims = geom->get_num_prims();
01632
01633 if (nPrims==0) {
01634 if(dxgsg8_cat.is_debug())
01635 dxgsg8_cat.debug() << "draw_line() called with ZERO vertices!!" << endl;
01636 return;
01637 }
01638
01639 _perVertex = 0x0;
01640 _perPrim = 0x0;
01641 _perComp = 0x0;
01642
01643 switch(geom->get_binding(G_COLOR)) {
01644 case G_PER_VERTEX:
01645 _perVertex |= PER_COLOR;
01646 break;
01647 case G_PER_COMPONENT:
01648 _perComp |= PER_COLOR;
01649 break;
01650 default:
01651 _perPrim |= PER_COLOR;
01652 }
01653
01654 switch(geom->get_binding(G_NORMAL)) {
01655 case G_PER_VERTEX:
01656 _perVertex |= PER_NORMAL;
01657 break;
01658 case G_PER_COMPONENT:
01659 _perComp |= PER_NORMAL;
01660 break;
01661 default:
01662 _perPrim |= PER_NORMAL;
01663 }
01664
01665 size_t vertex_size = draw_prim_setup(geom);
01666
01667 BYTE *_tmp_fvfOverrunBuf = NULL;
01668 nassertv(_pCurFvfBufPtr == NULL);
01669
01670
01671 if (nPrims * 2 * vertex_size > VERT_BUFFER_SIZE) {
01672
01673 _pCurFvfBufPtr = _tmp_fvfOverrunBuf = new BYTE[nPrims * 2 * vertex_size];
01674 } else _pCurFvfBufPtr = _pFvfBufBasePtr;
01675
01676 for (int i = 0; i < nPrims; i++) {
01677 if (_perPrim & PER_COLOR) {
01678 GET_NEXT_COLOR();
01679 }
01680 if (_perPrim & PER_NORMAL)
01681 p_normal = geom->get_next_normal(ni);
01682 draw_prim_inner_loop(2, geom, _perVertex);
01683 }
01684
01685 HRESULT hr;
01686
01687 DWORD nVerts = nPrims<<1;
01688
01689 if(!_bDrawPrimDoSetupVertexBuffer) {
01690 if (_tmp_fvfOverrunBuf == NULL) {
01691 nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
01692 hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _pFvfBufBasePtr, vertex_size);
01693 } else {
01694 nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_tmp_fvfOverrunBuf));
01695 hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _tmp_fvfOverrunBuf, vertex_size);
01696 delete [] _tmp_fvfOverrunBuf;
01697 }
01698 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,0);
01699 } else {
01700 COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,nVerts);
01701 }
01702
01703 _pCurFvfBufPtr = NULL;
01704 }
01705
01706 void DXGraphicsStateGuardian8::
01707 draw_linestrip(GeomLinestrip* geom, GeomContext *gc) {
01708
01709 #ifdef _DEBUG
01710 static BOOL bPrintedMsg=false;
01711
01712 if (!bPrintedMsg && (geom->get_width()!=1.0f)) {
01713 bPrintedMsg=true;
01714 dxgsg8_cat.warning() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n";
01715 }
01716 #endif
01717
01718 draw_linestrip_base(geom,gc,false);
01719 }
01720
01721
01722
01723
01724
01725
01726 void DXGraphicsStateGuardian8::
01727 draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) {
01728
01729
01730 #ifdef GSG_VERBOSE
01731 dxgsg8_cat.debug() << "draw_linestrip()" << endl;
01732 #endif
01733
01734 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
01735 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
01736
01737 int nPrims = geom->get_num_prims();
01738 const int *pLengthArr = geom->get_lengths();
01739
01740 if(nPrims==0) {
01741 if(dxgsg8_cat.is_debug())
01742 dxgsg8_cat.debug() << "draw_linestrip() called with ZERO vertices!!" << endl;
01743 return;
01744 }
01745
01746 _perVertex = 0x0;
01747 _perPrim = 0x0;
01748 _perComp = 0x0;
01749
01750 switch(geom->get_binding(G_COLOR)) {
01751 case G_PER_VERTEX:
01752 _perVertex |= PER_COLOR;
01753 break;
01754 case G_PER_COMPONENT:
01755 _perComp |= PER_COLOR;
01756 break;
01757 default:
01758 _perPrim |= PER_COLOR;
01759 }
01760
01761 switch(geom->get_binding(G_NORMAL)) {
01762 case G_PER_VERTEX:
01763 _perVertex |= PER_NORMAL;
01764 break;
01765 case G_PER_COMPONENT:
01766 _perComp |= PER_NORMAL;
01767 break;
01768 default:
01769 _perPrim |= PER_NORMAL;
01770 }
01771
01772 size_t vertex_size = draw_prim_setup(geom);
01773 ushort perFlags = _perVertex | _perComp;
01774
01775 bool bPerPrimColor = ((_perPrim & PER_COLOR)!=0);
01776 bool bPerPrimNormal = ((_perPrim & PER_NORMAL)!=0);
01777
01778 DWORD nVerts;
01779
01780 if(pLengthArr==NULL)
01781 nVerts=4;
01782
01783 for (int i = 0; i < nPrims; i++) {
01784 if (bPerPrimColor) {
01785 GET_NEXT_COLOR();
01786 }
01787
01788 if (bPerPrimNormal) {
01789 p_normal = geom->get_next_normal(ni);
01790 }
01791
01792 if(pLengthArr!=NULL) {
01793 nVerts= *(pLengthArr++);
01794 nassertv(nVerts >= 2);
01795 }
01796
01797 nassertv(_pCurFvfBufPtr == NULL);
01798 nassertv(nVerts * vertex_size < VERT_BUFFER_SIZE);
01799 _pCurFvfBufPtr = _pFvfBufBasePtr;
01800
01801 draw_prim_inner_loop(nVerts, geom, perFlags);
01802
01803 if(bConnectEnds) {
01804
01805 memcpy(_pCurFvfBufPtr,_pFvfBufBasePtr,vertex_size);
01806 _pCurFvfBufPtr+=vertex_size;
01807 nVerts++;
01808 }
01809
01810 nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
01811
01812 if(!_bDrawPrimDoSetupVertexBuffer) {
01813 HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts-1, _pFvfBufBasePtr, vertex_size);
01814 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,0);
01815 } else {
01816 COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINESTRIP,nVerts);
01817 }
01818
01819 _pCurFvfBufPtr = NULL;
01820 }
01821 }
01822
01823
01824
01825
01826
01827 typedef struct {
01828 Vertexf _v;
01829 D3DCOLOR _c;
01830 float _x_ratio;
01831 float _y_ratio;
01832 float _theta;
01833 } WrappedSprite;
01834
01835 class WrappedSpriteSortPtr {
01836 public:
01837 float z;
01838 WrappedSprite *pSpr;
01839 };
01840
01841
01842 struct draw_sprite_vertex_less {
01843 INLINE bool operator ()(const WrappedSpriteSortPtr& v0,
01844 const WrappedSpriteSortPtr& v1) const {
01845 return v0.z > v1.z;
01846 }
01847 };
01848
01849
01850
01851
01852
01853
01854 void DXGraphicsStateGuardian8::
01855 draw_sprite(GeomSprite *geom, GeomContext *gc) {
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873 #ifdef GSG_VERBOSE
01874 dxgsg8_cat.debug() << "draw_sprite()" << endl;
01875 #endif
01876
01877 int nPrims = geom->get_num_prims();
01878
01879 if (nPrims==0) {
01880 return;
01881 }
01882
01883 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
01884
01885 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(nPrims));
01886
01887 D3DMATRIX OldD3DWorldMatrix;
01888 _pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix);
01889
01890 bool bReEnableDither=false;
01891
01892 _pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix);
01893
01894 Geom::VertexIterator vi = geom->make_vertex_iterator();
01895 Geom::ColorIterator ci = geom->make_color_iterator();
01896
01897
01898
01899
01900
01901 float tex_xsize = 1.0f;
01902 float tex_ysize = 1.0f;
01903
01904 Texture *tex = geom->get_texture();
01905 if(tex !=NULL) {
01906
01907 modify_state(RenderState::make
01908 (TextureAttrib::make(tex),
01909 TextureApplyAttrib::make(TextureApplyAttrib::M_modulate)));
01910 tex_xsize = tex->_pbuffer->get_xsize();
01911 tex_ysize = tex->_pbuffer->get_ysize();
01912 }
01913
01914
01915 const LMatrix4f &modelview_mat = _transform->get_mat();
01916
01917
01918
01919
01920
01921
01922 _pD3DDevice->SetTransform(D3DTS_WORLD, &matIdentity);
01923
01924
01925
01926 float tex_left = geom->get_ll_uv()[0];
01927 float tex_right = geom->get_ur_uv()[0];
01928 float tex_bottom = geom->get_ll_uv()[1];
01929 float tex_top = geom->get_ur_uv()[1];
01930
01931 float half_width = 0.5f * tex_xsize * fabs(tex_right - tex_left);
01932 float half_height = 0.5f * tex_ysize * fabs(tex_top - tex_bottom);
01933 float scaled_width, scaled_height;
01934
01935
01936 bool alpha = false;
01937
01938 if (!geom->get_alpha_disable()) {
01939
01940 const TransparencyAttrib *trans = _state->get_transparency();
01941 if (trans != (const TransparencyAttrib *)NULL) {
01942 alpha = (trans->get_mode() != TransparencyAttrib::M_none);
01943 }
01944 }
01945
01946
01947 int i;
01948 Vertexf source_vert, cameraspace_vert;
01949 float *x_walk, *y_walk, *theta_walk;
01950 float theta;
01951
01952 nassertv(geom->get_x_bind_type() != G_PER_VERTEX);
01953 nassertv(geom->get_y_bind_type() != G_PER_VERTEX);
01954
01955
01956 bool x_overall = (geom->get_x_bind_type() == G_OVERALL);
01957 bool y_overall = (geom->get_y_bind_type() == G_OVERALL);
01958 bool theta_overall = (geom->get_theta_bind_type() == G_OVERALL);
01959 bool color_overall = (geom->get_binding(G_COLOR) == G_OVERALL);
01960 bool theta_on = !(geom->get_theta_bind_type() == G_OFF);
01961
01962
01963 if (x_overall)
01964 scaled_width = geom->_x_texel_ratio[0] * half_width;
01965 else {
01966 nassertv(((int)geom->_x_texel_ratio.size() >= geom->get_num_prims()));
01967 x_walk = &geom->_x_texel_ratio[0];
01968 }
01969
01970
01971 if (y_overall)
01972 scaled_height = geom->_y_texel_ratio[0] * half_height;
01973 else {
01974 nassertv(((int)geom->_y_texel_ratio.size() >= geom->get_num_prims()));
01975 y_walk = &geom->_y_texel_ratio[0];
01976 }
01977
01978
01979 if (theta_on) {
01980 if (theta_overall)
01981 theta = geom->_theta[0];
01982 else {
01983 nassertv(((int)geom->_theta.size() >= geom->get_num_prims()));
01984 theta_walk = &geom->_theta[0];
01985 }
01986 }
01987
01988
01989
01990
01991
01992
01993
01994 Colorf v_color;
01995
01996
01997 pvector< WrappedSpriteSortPtr > sorted_sprite_vector;
01998 pvector< WrappedSpriteSortPtr >::iterator sorted_vec_iter;
01999
02000 WrappedSprite *SpriteArray = new WrappedSprite[nPrims];
02001
02002
02003
02004
02005 if (SpriteArray==NULL) {
02006 dxgsg8_cat.fatal() << "draw_sprite() out of memory!!" << endl;
02007 return;
02008 }
02009
02010
02011
02012 WrappedSprite *pSpr;
02013
02014 for (pSpr=SpriteArray,i = 0; i < nPrims; i++,pSpr++) {
02015
02016 source_vert = geom->get_next_vertex(vi);
02017 cameraspace_vert = source_vert * modelview_mat;
02018
02019 pSpr->_v.set(cameraspace_vert[0],cameraspace_vert[1],cameraspace_vert[2]);
02020
02021 if (!color_overall) {
02022 GET_NEXT_COLOR();
02023 pSpr->_c = _curD3Dcolor;
02024 }
02025 if (!x_overall)
02026 pSpr->_x_ratio = *x_walk++;
02027 if (!y_overall)
02028 pSpr->_y_ratio = *y_walk++;
02029 if (theta_on && (!theta_overall))
02030 pSpr->_theta = *theta_walk++;
02031 }
02032
02033 if (alpha) {
02034 sorted_sprite_vector.reserve(nPrims);
02035
02036 for (pSpr=SpriteArray,i = 0; i < nPrims; i++,pSpr++) {
02037 WrappedSpriteSortPtr ws_ptr;
02038 ws_ptr.z=pSpr->_v[2];
02039 ws_ptr.pSpr=pSpr;
02040 sorted_sprite_vector.push_back(ws_ptr);
02041 }
02042
02043
02044
02045
02046
02047
02048 sort(sorted_sprite_vector.begin(), sorted_sprite_vector.end(), draw_sprite_vertex_less());
02049 sorted_vec_iter = sorted_sprite_vector.begin();
02050
02051
02052
02053
02054
02055
02056
02057
02058 if(_dither_enabled) {
02059 bReEnableDither=true;
02060 enable_dither(false);
02061 }
02062 }
02063
02064 Vertexf ul, ur, ll, lr;
02065
02066
02067
02068
02069
02070
02071
02072
02073 D3DCOLOR CurColor;
02074 DWORD FVFType = D3DFVF_XYZ | (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)) | D3DFVF_DIFFUSE;
02075 DWORD vertex_size = sizeof(float) * 2 + sizeof(float) * 3 + sizeof(D3DCOLOR);
02076
02077 if (color_overall) {
02078 GET_NEXT_COLOR();
02079 CurColor = _curD3Dcolor;
02080 }
02081
02082
02083 bool bUseGouraudShadedColor=_fog_enabled;
02084 enable_gouraud_shading(_fog_enabled);
02085 set_vertex_format(FVFType);
02086
02087 #ifdef _DEBUG
02088 nassertv(_pCurFvfBufPtr == NULL);
02089 nassertv(nPrims * 4 * vertex_size < VERT_BUFFER_SIZE);
02090 nassertv(nPrims * 6 < PANDA_MAXNUMVERTS );
02091 #endif
02092
02093 _pCurFvfBufPtr = _pFvfBufBasePtr;
02094
02095 const float TexCrdSets[4][2] = {
02096 { tex_left, tex_bottom },
02097 { tex_right, tex_bottom },
02098 { tex_left, tex_top },
02099 { tex_right, tex_top }
02100 };
02101
02102 #define QUADVERTLISTLEN 6
02103
02104 DWORD QuadVertIndexList[QUADVERTLISTLEN] = { 0, 1, 2, 3, 2, 1};
02105 DWORD CurDPIndexArrLength=0,CurVertCount=0;
02106
02107 for (pSpr=SpriteArray,i = 0; i < nPrims; i++,pSpr++) {
02108
02109 if (alpha) {
02110 pSpr = sorted_vec_iter->pSpr;
02111 sorted_vec_iter++;
02112 }
02113
02114
02115 if (!x_overall)
02116 scaled_width = pSpr->_x_ratio * half_width;
02117
02118 if (!y_overall)
02119 scaled_height = pSpr->_y_ratio * half_height;
02120
02121
02122 if (theta_on) {
02123 if (!theta_overall)
02124 theta = pSpr->_theta;
02125
02126
02127
02128
02129 LMatrix3f xform_mat = LMatrix3f::rotate_mat(theta) *
02130 LMatrix3f::scale_mat(scaled_width, scaled_height);
02131
02132 ur = (LVector3f( 1.0f, 1.0f, 0.0f) * xform_mat) + pSpr->_v;
02133 ul = (LVector3f(-1.0f, 1.0f, 0.0f) * xform_mat) + pSpr->_v;
02134 lr = (LVector3f( 1.0f, -1.0f, 0.0f) * xform_mat) + pSpr->_v;
02135 ll = (LVector3f(-1.0f, -1.0f, 0.0f) * xform_mat) + pSpr->_v;
02136 } else {
02137
02138 float x,y,negx,negy,z;
02139
02140 x = pSpr->_v[0] + scaled_width;
02141 y = pSpr->_v[1] + scaled_height;
02142 negx = pSpr->_v[0] - scaled_width;
02143 negy = pSpr->_v[1] - scaled_height;
02144 z = pSpr->_v[2];
02145
02146 ur.set(x, y, z);
02147 ul.set(negx, y, z);
02148 lr.set(x, negy, z);
02149 ll.set(negx, negy, z);
02150 }
02151
02152
02153
02154
02155
02156 add_to_FVFBuf((void *)ll.get_data(), 3*sizeof(float));
02157 if (!color_overall)
02158 CurColor = pSpr->_c;
02159 add_DWORD_to_FVFBuf(CurColor);
02160 add_to_FVFBuf((void *)TexCrdSets[0], sizeof(float)*2);
02161
02162
02163
02164 add_to_FVFBuf((void *)lr.get_data(), 3*sizeof(float));
02165
02166
02167 if(bUseGouraudShadedColor)
02168 *((DWORD *)_pCurFvfBufPtr) = (DWORD) CurColor;
02169 _pCurFvfBufPtr += sizeof(D3DCOLOR);
02170
02171 add_to_FVFBuf((void *)TexCrdSets[1], sizeof(float)*2);
02172
02173
02174
02175 add_to_FVFBuf((void *)ul.get_data(), 3*sizeof(float));
02176
02177 if(bUseGouraudShadedColor)
02178 *((DWORD *)_pCurFvfBufPtr) = (DWORD) CurColor;
02179 _pCurFvfBufPtr += sizeof(D3DCOLOR);
02180 add_to_FVFBuf((void *)TexCrdSets[2], sizeof(float)*2);
02181
02182
02183
02184 add_to_FVFBuf((void *)ur.get_data(), 3*sizeof(float));
02185 add_DWORD_to_FVFBuf(CurColor);
02186 add_to_FVFBuf((void *)TexCrdSets[3], sizeof(float)*2);
02187
02188 for (int ii=0;ii<QUADVERTLISTLEN;ii++) {
02189 _index_buf[CurDPIndexArrLength+ii]=QuadVertIndexList[ii]+CurVertCount;
02190 }
02191 CurDPIndexArrLength+=QUADVERTLISTLEN;
02192 CurVertCount+=4;
02193 }
02194
02195 DWORD nVerts= nPrims << 2;
02196 DWORD numTris = nPrims << 1;
02197
02198
02199
02200 HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0,
02201 nVerts, numTris,
02202 _index_buf, D3DFMT_INDEX16,
02203 _pFvfBufBasePtr, vertex_size);
02204 TestDrawPrimFailure(DrawIndexedPrim,hr,_pD3DDevice,QUADVERTLISTLEN*nPrims,numTris);
02205
02206 _pCurFvfBufPtr = NULL;
02207 delete [] SpriteArray;
02208
02209
02210 _pD3DDevice->SetTransform(D3DTS_WORLD,
02211 (D3DMATRIX*)modelview_mat.get_data());
02212
02213 if(bReEnableDither)
02214 enable_dither(true);
02215 }
02216
02217
02218
02219
02220
02221
02222 void DXGraphicsStateGuardian8::
02223 draw_polygon(GeomPolygon *geom, GeomContext *gc) {
02224
02225 #ifdef GSG_VERBOSE
02226 dxgsg8_cat.debug() << "draw_polygon()" << endl;
02227 #endif
02228 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02229 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
02230
02231
02232 DWORD rstate;
02233 _pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate);
02234 if(rstate==D3DFILL_WIREFRAME) {
02235 draw_linestrip_base(geom,gc,true);
02236 } else {
02237 draw_multitri(geom, D3DPT_TRIANGLEFAN);
02238 }
02239 }
02240
02241
02242
02243
02244
02245
02246 void DXGraphicsStateGuardian8::
02247 draw_quad(GeomQuad *geom, GeomContext *gc) {
02248
02249 #ifdef GSG_VERBOSE
02250 dxgsg8_cat.debug() << "draw_quad()" << endl;
02251 #endif
02252 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02253 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
02254
02255
02256 DWORD rstate;
02257 _pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate);
02258 if(rstate==D3DFILL_WIREFRAME) {
02259 draw_linestrip_base(geom,gc,true);
02260 } else {
02261 draw_multitri(geom, D3DPT_TRIANGLEFAN);
02262 }
02263 }
02264
02265
02266
02267
02268
02269
02270
02271 void DXGraphicsStateGuardian8::
02272 draw_tri(GeomTri *geom, GeomContext *gc) {
02273 #ifdef GSG_VERBOSE
02274 dxgsg8_cat.debug() << "draw_tri()" << endl;
02275 #endif
02276 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02277 DO_PSTATS_STUFF(_vertices_tri_pcollector.add_level(geom->get_num_vertices()));
02278
02279 #if 0
02280 if (_pCurTexContext!=NULL) {
02281 dxgsg8_cat.spam() << "Cur active DX texture: " << _pCurTexContext->_tex->get_name() << "\n";
02282 }
02283 #endif
02284
02285 #ifdef COUNT_DRAWPRIMS
02286 cGeomcount++;
02287 #endif
02288
02289 DWORD nPrims = geom->get_num_prims();
02290 HRESULT hr;
02291
02292 PTA_Vertexf coords;
02293 PTA_Normalf norms;
02294 PTA_Colorf colors;
02295 PTA_TexCoordf texcoords;
02296 GeomBindType TexCoordBinding,ColorBinding,NormalBinding;
02297 PTA_ushort vindexes,nindexes,tindexes,cindexes;
02298
02299 geom->get_coords(coords,vindexes);
02300 geom->get_normals(norms,NormalBinding,nindexes);
02301 geom->get_colors(colors,ColorBinding,cindexes);
02302 geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
02303
02304
02305
02306 _perVertex = 0x0;
02307 _perPrim = 0x0;
02308
02309 bool bUseTexCoordOnlyLoop = ((ColorBinding != G_PER_VERTEX) &&
02310 (NormalBinding == G_OFF) &&
02311 (TexCoordBinding != G_OFF));
02312
02313 bool bPerPrimNormal;
02314
02315 bool bPerPrimColor=(ColorBinding == G_PER_PRIM);
02316 if(bPerPrimColor)
02317 _perPrim = PER_COLOR;
02318 else if(ColorBinding == G_PER_VERTEX)
02319 _perVertex = PER_COLOR;
02320
02321 if(bUseTexCoordOnlyLoop) {
02322 _perVertex |= PER_TEXCOORD;
02323 } else {
02324 if(NormalBinding == G_PER_VERTEX)
02325 _perVertex |= PER_NORMAL;
02326 else if(NormalBinding == G_PER_PRIM)
02327 _perPrim |= PER_NORMAL;
02328
02329 bPerPrimNormal=((_perPrim & PER_NORMAL)!=0);
02330
02331 if(TexCoordBinding == G_PER_VERTEX)
02332 _perVertex |= PER_TEXCOORD;
02333 }
02334
02335 size_t vertex_size = draw_prim_setup(geom);
02336
02337
02338
02339 bPerPrimColor=(_perPrim & PER_COLOR)!=0x0;
02340
02341 #ifdef _DEBUG
02342
02343
02344 bool bNewUseTexCoordOnlyLoop = (((_perVertex & PER_COLOR)==0x0) &&
02345 ((_CurFVFType & D3DFVF_NORMAL)==0x0) &&
02346 ((_CurFVFType & D3DFVF_TEX1)!=0x0));
02347 if(bUseTexCoordOnlyLoop && (!bNewUseTexCoordOnlyLoop)) {
02348
02349
02350
02351
02352
02353
02354
02355 DebugBreak();
02356 assert(0);
02357 }
02358 #endif
02359
02360 nassertv(_pCurFvfBufPtr == NULL);
02361 nassertv(nPrims * 3 * vertex_size < VERT_BUFFER_SIZE);
02362 _pCurFvfBufPtr = _pFvfBufBasePtr;
02363
02364
02365
02366 for (uint i = 0; i < nPrims; i++) {
02367 if(bPerPrimColor) {
02368 GET_NEXT_COLOR();
02369 }
02370
02371 if(bUseTexCoordOnlyLoop) {
02372 draw_prim_inner_loop_coordtexonly(3, geom);
02373 } else {
02374 if(bPerPrimNormal)
02375 p_normal = geom->get_next_normal(ni);
02376
02377 draw_prim_inner_loop(3, geom, _perVertex);
02378 }
02379 }
02380
02381 DWORD nVerts=nPrims*3;
02382
02383 nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
02384
02385 if(!_bDrawPrimDoSetupVertexBuffer) {
02386 hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nPrims, _pFvfBufBasePtr, vertex_size);
02387 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,nPrims);
02388 } else {
02389 COPYVERTDATA_2_VERTEXBUFFER(D3DPT_TRIANGLELIST,nVerts);
02390 }
02391
02392 _pCurFvfBufPtr = NULL;
02393
02394
02395
02396 #if 0
02397
02398 float vert_buf[15] = {
02399 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
02400 33.0, 0.0f, 0.0f, 0.0f, 2.0,
02401 0.0f, 0.0f, 33.0, 2.0, 0.0f
02402 };
02403
02404 _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_BORDER);
02405 _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_BORDER);
02406 _pD3DDevice->SetTextureStageState(0,D3DTSS_BORDERCOLOR,MY_D3DRGBA(0,0,0,0));
02407
02408 DWORD FVFType = D3DFVF_XYZ | (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)) ;
02409 set_vertex_format(FVFType);
02410 HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, vert_buf, 1, 5*sizeof(float));
02411 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,3,1);
02412 #endif
02413 }
02414
02415
02416
02417
02418
02419
02420 void DXGraphicsStateGuardian8::
02421 draw_tristrip(GeomTristrip *geom, GeomContext *gc) {
02422
02423 #ifdef GSG_VERBOSE
02424 dxgsg8_cat.debug() << "draw_tristrip()" << endl;
02425 #endif
02426 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02427 DO_PSTATS_STUFF(_vertices_tristrip_pcollector.add_level(geom->get_num_vertices()));
02428
02429 draw_multitri(geom, D3DPT_TRIANGLESTRIP);
02430 }
02431
02432
02433
02434
02435
02436
02437 void DXGraphicsStateGuardian8::
02438 draw_trifan(GeomTrifan *geom, GeomContext *gc) {
02439
02440 #ifdef GSG_VERBOSE
02441 dxgsg8_cat.debug() << "draw_trifan()" << endl;
02442 #endif
02443 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02444 DO_PSTATS_STUFF(_vertices_trifan_pcollector.add_level(geom->get_num_vertices()));
02445
02446 draw_multitri(geom, D3DPT_TRIANGLEFAN);
02447 }
02448
02449
02450
02451
02452
02453
02454 void DXGraphicsStateGuardian8::
02455 draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
02456
02457 DWORD nPrims = geom->get_num_prims();
02458 const uint *pLengthArr = (const uint *) ((const int *)geom->get_lengths());
02459 HRESULT hr;
02460
02461 if(nPrims==0) {
02462 #ifdef _DEBUG
02463 dxgsg8_cat.warning() << "draw_multitri() called with ZERO vertices!!" << endl;
02464 #endif
02465 return;
02466 }
02467
02468 #ifdef COUNT_DRAWPRIMS
02469 cGeomcount++;
02470 #endif
02471
02472 PTA_Vertexf coords;
02473 PTA_Normalf norms;
02474 PTA_Colorf colors;
02475 PTA_TexCoordf texcoords;
02476 GeomBindType TexCoordBinding,ColorBinding,NormalBinding;
02477 PTA_ushort vindexes,nindexes,tindexes,cindexes;
02478
02479 geom->get_coords(coords,vindexes);
02480 geom->get_normals(norms,NormalBinding,nindexes);
02481 geom->get_colors(colors,ColorBinding,cindexes);
02482 geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
02483
02484 {
02485
02486 _perVertex = 0x0;
02487 _perPrim = 0x0;
02488 _perComp = 0x0;
02489
02490 bool bIsTriList=(trilisttype==D3DPT_TRIANGLESTRIP);
02491 bool bPerPrimColor=(ColorBinding == G_PER_PRIM);
02492 bool bPerPrimNormal;
02493 bool bUseTexCoordOnlyLoop = (((ColorBinding == G_OVERALL) || bPerPrimColor) &&
02494 (NormalBinding == G_OFF) &&
02495 (TexCoordBinding != G_OFF));
02496
02497 if(bUseTexCoordOnlyLoop) {
02498 if(bPerPrimColor) {
02499 _perPrim = PER_COLOR;
02500 }
02501 } else {
02502 switch (ColorBinding) {
02503 case G_PER_PRIM:
02504 _perPrim = PER_COLOR;
02505 break;
02506 case G_PER_COMPONENT:
02507 _perComp = PER_COLOR;
02508 break;
02509 case G_PER_VERTEX:
02510 _perVertex = PER_COLOR;
02511 break;
02512 }
02513
02514 switch (NormalBinding) {
02515 case G_PER_VERTEX:
02516 _perVertex |= PER_NORMAL;
02517 break;
02518 case G_PER_PRIM:
02519 _perPrim |= PER_NORMAL;
02520 break;
02521 case G_PER_COMPONENT:
02522 _perComp |= PER_NORMAL;
02523 break;
02524 }
02525
02526 bPerPrimNormal=((_perPrim & PER_NORMAL)!=0);
02527
02528 if (TexCoordBinding == G_PER_VERTEX)
02529 _perVertex |= PER_TEXCOORD;
02530 }
02531
02532 size_t vertex_size = draw_prim_setup(geom);
02533
02534
02535
02536 bPerPrimColor=(_perPrim & PER_COLOR)!=0;
02537
02538 #ifdef _DEBUG
02539
02540
02541 bool bNewUseTexCoordOnlyLoop = ((((_perComp|_perVertex) & PER_COLOR)==0x0) &&
02542 ((_CurFVFType & D3DFVF_NORMAL)==0x0) &&
02543 ((_CurFVFType & D3DFVF_TEX1)!=0x0));
02544
02545 if(bUseTexCoordOnlyLoop && (!bNewUseTexCoordOnlyLoop)) {
02546
02547
02548
02549
02550
02551
02552
02553 DebugBreak();
02554 assert(0);
02555 }
02556
02557 #endif
02558
02559
02560
02561 int nVerts;
02562 if(pLengthArr==NULL) {
02563
02564 nVerts=4;
02565 }
02566
02567 for (uint i = 0; i < nPrims; i++) {
02568
02569 if(pLengthArr!=NULL) {
02570 nVerts = *(pLengthArr++);
02571 }
02572
02573 if(bPerPrimColor) {
02574 GET_NEXT_COLOR();
02575 }
02576
02577 #ifdef _DEBUG
02578 nassertv(nVerts >= 3);
02579 nassertv(_pCurFvfBufPtr == NULL);
02580 nassertv(nVerts * vertex_size < VERT_BUFFER_SIZE);
02581 #endif
02582 _pCurFvfBufPtr = _pFvfBufBasePtr;
02583
02584 if(_perComp==0x0) {
02585 if(bUseTexCoordOnlyLoop) {
02586 draw_prim_inner_loop_coordtexonly(nVerts, geom);
02587 } else {
02588 if (bPerPrimNormal)
02589 p_normal = geom->get_next_normal(ni);
02590
02591 draw_prim_inner_loop(nVerts, geom, _perVertex);
02592 }
02593 } else {
02594 if(bPerPrimNormal)
02595 p_normal = geom->get_next_normal(ni);
02596
02597 if(bIsTriList) {
02598
02599
02600
02601
02602 draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp);
02603
02604
02605 draw_prim_inner_loop(2, geom, _perVertex);
02606 } else {
02607
02608
02609
02610
02611
02612 draw_prim_inner_loop(1, geom, _perVertex);
02613 draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp);
02614 draw_prim_inner_loop(1, geom, _perVertex);
02615 }
02616 }
02617
02618 assert((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
02619 DWORD numTris=nVerts-2;
02620
02621 if(!_bDrawPrimDoSetupVertexBuffer) {
02622 hr = _pD3DDevice->DrawPrimitiveUP(trilisttype, numTris, _pFvfBufBasePtr, vertex_size);
02623 TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,numTris);
02624 } else {
02625 COPYVERTDATA_2_VERTEXBUFFER(trilisttype,nVerts);
02626 }
02627
02628 _pCurFvfBufPtr = NULL;
02629 }
02630 }
02631
02632 }
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642 void DXGraphicsStateGuardian8::
02643 GenerateSphere(void *pVertexSpace,DWORD dwVertSpaceByteSize,
02644 void *pIndexSpace,DWORD dwIndexSpaceByteSize,
02645 D3DXVECTOR3 *pCenter, float fRadius,
02646 DWORD wNumRings, DWORD wNumSections, float sx, float sy, float sz,
02647 DWORD *pNumVertices,DWORD *pNumTris,DWORD fvfFlags,DWORD dwVertSize) {
02648 float x, y, z, rsintheta;
02649 D3DXVECTOR3 vPoint;
02650
02651
02652 #define M_PI 3.1415926f // probably should get this from mathNumbers.h instead
02653
02654 nassertv(wNumRings>=2 && wNumSections>=2);
02655 wNumRings--;
02656
02657 wNumSections++;
02658
02659
02660 DWORD dwNumVertices,dwNumIndices,dwNumTriangles;
02661
02662 #define DO_SPHERE_TEXTURING (fvfFlags & D3DFVF_TEXCOUNT_MASK)
02663 #define DO_SPHERE_NORMAL (fvfFlags & D3DFVF_NORMAL)
02664 #define DO_SPHERE_COLOR (fvfFlags & D3DFVF_DIFFUSE)
02665
02666 if (DO_SPHERE_TEXTURING) {
02667
02668 wNumRings+=2;
02669 dwNumVertices = *pNumVertices = wNumRings * wNumSections;
02670 dwNumTriangles = (wNumRings-1) * wNumSections * 2;
02671 } else {
02672 dwNumVertices = *pNumVertices = wNumRings * wNumSections + 2;
02673 dwNumTriangles = wNumRings*wNumSections*2;
02674 }
02675
02676 dwNumIndices = dwNumTriangles*3;
02677 *pNumTris = dwNumTriangles;
02678
02679
02680 WORD *pwIndices = (WORD *) pIndexSpace;
02681
02682 nassertv(dwNumVertices*dwVertSize < VERT_BUFFER_SIZE);
02683 nassertv(dwNumIndices < PANDA_MAXNUMVERTS );
02684
02685
02686 D3DXVECTOR3 vTopPoint = *pCenter;
02687 D3DXVECTOR3 vBotPoint = *pCenter;
02688 float yRadius=sy*fRadius;
02689 vTopPoint.y+=yRadius;
02690 vBotPoint.y-=yRadius;
02691 D3DXVECTOR3 vNormal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
02692 float texCoords[2];
02693
02694 nassertv(pVertexSpace==_pCurFvfBufPtr);
02695
02696 #define ADD_GENSPHERE_VERTEX_TO_BUFFER(VERT) \
02697 add_to_FVFBuf((void *)&(VERT), 3*sizeof(float)); \
02698 if(fvfFlags & D3DFVF_NORMAL) \
02699 add_to_FVFBuf((void *)&vNormal, 3*sizeof(float)); \
02700 if(fvfFlags & D3DFVF_DIFFUSE) \
02701 add_DWORD_to_FVFBuf(_curD3Dcolor); \
02702 if(fvfFlags & D3DFVF_TEXCOUNT_MASK) \
02703 add_to_FVFBuf((void *)texCoords, sizeof(TexCoordf));
02704
02705 #ifdef DBG_GENSPHERE
02706 int nvs_written=0;
02707 memset(pVertexSpace,0xFF,dwNumVertices*dwVertSize);
02708 #endif
02709
02710 if (! DO_SPHERE_TEXTURING) {
02711 ADD_GENSPHERE_VERTEX_TO_BUFFER(vTopPoint);
02712 #ifdef DBG_GENSPHERE
02713 nvs_written++;
02714 #endif
02715 }
02716
02717
02718 float inv_radius = 1.0f/fRadius;
02719 const float reciprocal_PI=1.0f/M_PI;
02720 const float reciprocal_2PI=1.0f/(2.0*M_PI);
02721 DWORD i;
02722 float theta,dtheta;
02723
02724 if (DO_SPHERE_TEXTURING) {
02725
02726 dtheta = (float)(M_PI / (wNumRings-1));
02727 theta = 0.0f;
02728 } else {
02729 dtheta = (float)(M_PI / (wNumRings + 1));
02730 theta = dtheta;
02731 }
02732 float phi,dphi = (float)(2*M_PI / (wNumSections-1));
02733
02734 for (i = 0; i < wNumRings; i++) {
02735 float costheta,sintheta,cosphi,sinphi;
02736 phi = 0.0f;
02737
02738 if (DO_SPHERE_TEXTURING) {
02739 texCoords[1] = theta * reciprocal_PI;
02740 }
02741
02742
02743 csincos(theta,&sintheta,&costheta);
02744 y = fRadius * costheta;
02745
02746 rsintheta = fRadius * sintheta;
02747
02748 for (DWORD j = 0; j < wNumSections; j++) {
02749 csincos(phi,&sinphi,&cosphi);
02750 x = rsintheta * sinphi;
02751 z = rsintheta * cosphi;
02752
02753 #ifdef DBG_GENSPHERE
02754 nvs_written++;
02755 #endif
02756 vPoint.x = pCenter->x + sx*x;
02757 vPoint.y = pCenter->y + sy*y;
02758 vPoint.z = pCenter->z + sz*z;
02759
02760 add_to_FVFBuf((void *)&vPoint, 3*sizeof(float));
02761
02762 if (DO_SPHERE_NORMAL) {
02763
02764 D3DXVECTOR3 vVec = D3DXVECTOR3( x*inv_radius, y*inv_radius, z*inv_radius );
02765 D3DXVec3Normalize(&vNormal,&vVec);
02766 add_to_FVFBuf((float *)&vNormal, 3*sizeof(float));
02767 }
02768
02769 if (DO_SPHERE_COLOR)
02770 add_DWORD_to_FVFBuf(_curD3Dcolor);
02771
02772 if (DO_SPHERE_TEXTURING) {
02773 texCoords[0] = 1.0f - phi*reciprocal_2PI;
02774 add_to_FVFBuf((void *)texCoords, sizeof(TexCoordf));
02775 }
02776
02777 phi += dphi;
02778 }
02779 theta += dtheta;
02780 }
02781
02782 if (! DO_SPHERE_TEXTURING) {
02783
02784 vNormal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f );
02785 ADD_GENSPHERE_VERTEX_TO_BUFFER(vBotPoint);
02786 #ifdef DBG_GENSPHERE
02787 nvs_written++;
02788 #endif
02789 }
02790
02791 #ifdef DBG_GENSPHERE
02792 assert(nvs_written == dwNumVertices);
02793 #endif
02794
02795
02796 #ifdef DBG_GENSPHERE
02797 memset(pwIndices,0xFF,dwNumIndices*sizeof(WORD));
02798 #endif
02799
02800
02801 DWORD cur_vertring_startidx=0;
02802 DWORD CurFinalTriIndex = 0;
02803
02804 if (! DO_SPHERE_TEXTURING) {
02805
02806
02807
02808
02809
02810 for (i = 0; i < wNumSections; i++) {
02811 DWORD TopCapTriIndex=3*i;
02812 DWORD BotCapTriIndex=3*(dwNumTriangles - wNumSections + i);
02813 DWORD i_incd = ((i + 1) % wNumSections);
02814
02815 pwIndices[TopCapTriIndex++] = 0;
02816 pwIndices[TopCapTriIndex++] = i + 1;
02817 pwIndices[TopCapTriIndex] = i_incd + 1;
02818
02819 pwIndices[BotCapTriIndex++] = (WORD)( dwNumVertices - 1 );
02820 pwIndices[BotCapTriIndex++] = (WORD)( dwNumVertices - 2 - i );
02821 pwIndices[BotCapTriIndex] = (WORD)( dwNumVertices - 2 - i_incd);
02822 }
02823
02824 cur_vertring_startidx = 1;
02825 CurFinalTriIndex = wNumSections;
02826 }
02827
02828 DWORD j_incd,base_index;
02829
02830
02831
02832
02833
02834 for (i = 0; i < wNumRings-1; i++) {
02835 for (DWORD j = 0; j < wNumSections; j++) {
02836
02837 base_index=3*CurFinalTriIndex;
02838 j_incd=(j+1) % wNumSections;
02839
02840 DWORD v1_row1_idx,v2_row1_idx,v1_row2_idx,v2_row2_idx;
02841
02842 v1_row1_idx = cur_vertring_startidx + j;
02843 v2_row1_idx = cur_vertring_startidx + j_incd;
02844 v1_row2_idx = v1_row1_idx + wNumSections;
02845 v2_row2_idx = v2_row1_idx + wNumSections;
02846
02847 #ifdef DBG_GENSPHERE
02848 assert(v2_row2_idx<dwNumVertices);
02849 assert(v1_row2_idx<dwNumVertices);
02850 assert(v2_row1_idx<dwNumVertices);
02851 assert(v1_row1_idx<dwNumVertices);
02852 #endif
02853
02854 pwIndices[base_index++] = v1_row1_idx;
02855 pwIndices[base_index++] = v1_row2_idx;
02856 pwIndices[base_index++] = v2_row2_idx;
02857
02858 pwIndices[base_index++] = v1_row1_idx;
02859 pwIndices[base_index++] = v2_row2_idx;
02860 pwIndices[base_index++] = v2_row1_idx;
02861
02862 CurFinalTriIndex += 2;
02863 }
02864 cur_vertring_startidx += wNumSections;
02865 }
02866
02867 #ifdef DBG_GENSPHERE
02868 if (DO_SPHERE_TEXTURING) {
02869 assert(CurFinalTriIndex == dwNumTriangles);
02870 assert(base_index == dwNumIndices);
02871 } else {
02872 assert(CurFinalTriIndex == dwNumTriangles-wNumSections);
02873 assert(base_index == dwNumIndices-wNumSections*3);
02874 }
02875
02876 for (i = 0; i < dwNumIndices; i++)
02877 assert(pwIndices[i] <dwNumVertices);
02878 #endif
02879 }
02880
02881
02882
02883
02884
02885
02886
02887 void DXGraphicsStateGuardian8::
02888 draw_sphere(GeomSphere *geom, GeomContext *gc) {
02889
02890 #define SPHERE_NUMSLICES 16
02891 #define SPHERE_NUMSTACKS 10
02892
02893 #ifdef GSG_VERBOSE
02894 dxgsg8_cat.debug() << "draw_sphere()" << endl;
02895 #endif
02896 DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
02897 DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
02898
02899 int nprims = geom->get_num_prims();
02900
02901 if (nprims==0) {
02902 dxgsg8_cat.warning() << "draw_sphere() called with ZERO vertices!!" << endl;
02903 return;
02904 }
02905
02906 Geom::VertexIterator vi = geom->make_vertex_iterator();
02907 Geom::ColorIterator ci;
02908 bool bPerPrimColor = (geom->get_binding(G_COLOR) == G_PER_PRIM);
02909 if (bPerPrimColor)
02910 ci = geom->make_color_iterator();
02911
02912 for (int i = 0; i < nprims; i++) {
02913
02914 DWORD nVerts,nTris;
02915 Vertexf center = geom->get_next_vertex(vi);
02916 Vertexf edge = geom->get_next_vertex(vi);
02917 LVector3f v = edge - center;
02918 float fRadius = sqrt(dot(v, v));
02919
02920 size_t vertex_size = draw_prim_setup(geom);
02921
02922 _pCurFvfBufPtr = _pFvfBufBasePtr;
02923
02924 if (bPerPrimColor) {
02925 GET_NEXT_COLOR();
02926 }
02927
02928 GenerateSphere(_pCurFvfBufPtr, VERT_BUFFER_SIZE,
02929 _index_buf, PANDA_MAXNUMVERTS*2,
02930 (D3DXVECTOR3 *)¢er, fRadius,
02931 SPHERE_NUMSTACKS, SPHERE_NUMSLICES,
02932 1.0f, 1.0f, 1.0f,
02933 &nVerts,&nTris,_CurFVFType,vertex_size);
02934
02935
02936
02937 HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0,
02938 nVerts, nTris, _index_buf, D3DFMT_INDEX16,
02939 _pFvfBufBasePtr, vertex_size);
02940 TestDrawPrimFailure(DrawIndexedPrim,hr,_pD3DDevice,nVerts,nTris);
02941 }
02942
02943 _pCurFvfBufPtr = NULL;
02944 }
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956 TextureContext *DXGraphicsStateGuardian8::
02957 prepare_texture(Texture *tex) {
02958
02959 DXTextureContext8 *dtc = new DXTextureContext8(tex);
02960 #ifdef WBD_GL_MODE
02961 glGenTextures(1, >c->_index);
02962
02963 bind_texture(gtc);
02964 glPrioritizeTextures(1, >c->_index, >c->_priority);
02965 specify_texture(tex);
02966 apply_texture_immediate(tex);
02967 #else
02968
02969 if (dtc->CreateTexture(*_pScrn) == NULL) {
02970 delete dtc;
02971 return NULL;
02972 }
02973 #endif // WBD_GL_MODE
02974
02975 bool inserted = mark_prepared_texture(dtc);
02976
02977
02978
02979
02980 nassertr(inserted, NULL);
02981
02982 return dtc;
02983 }
02984
02985
02986
02987
02988
02989
02990
02991 void DXGraphicsStateGuardian8::
02992 apply_texture(TextureContext *tc) {
02993 if (tc==NULL) {
02994 return;
02995 }
02996 #ifdef DO_PSTATS
02997 add_to_texture_record(tc);
02998 #endif
02999
03000
03001
03002
03003
03004
03005
03006 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
03007
03008 int dirty = dtc->get_dirty_flags();
03009
03010 if (dirty) {
03011
03012
03013
03014
03015 if((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
03016
03017
03018
03019 if ((dirty & Texture::DF_image) == 0) {
03020 dxgsg8_cat.warning()
03021 << "Texture " << *dtc->_texture << " has changed mipmap state.\n";
03022 }
03023
03024 dtc->DeleteTexture();
03025 if (dtc->CreateTexture(*_pScrn) == NULL) {
03026
03027
03028 dxgsg8_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl;
03029
03030 release_texture(dtc);
03031 enable_texturing(false);
03032 return;
03033 }
03034 }
03035 dtc->clear_dirty_flags();
03036 } else {
03037 if(_pCurTexContext == dtc) {
03038 return;
03039 }
03040 }
03041
03042 Texture *tex = tc->_texture;
03043 Texture::WrapMode wrapU,wrapV;
03044 wrapU=tex->get_wrapu();
03045 wrapV=tex->get_wrapv();
03046
03047 if (wrapU!=_CurTexWrapModeU) {
03048 _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU));
03049 _CurTexWrapModeU = wrapU;
03050 }
03051 if (wrapV!=_CurTexWrapModeV) {
03052 _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,get_texture_wrap_mode(wrapV));
03053 _CurTexWrapModeV = wrapV;
03054 }
03055
03056 uint aniso_degree=tex->get_anisotropic_degree();
03057 Texture::FilterType ft=tex->get_magfilter();
03058
03059 if(_CurTexAnisoDegree != aniso_degree) {
03060 _pD3DDevice->SetTextureStageState(0,D3DTSS_MAXANISOTROPY,aniso_degree);
03061 _CurTexAnisoDegree = aniso_degree;
03062 }
03063
03064 D3DTEXTUREFILTERTYPE newMagFilter;
03065 if (aniso_degree<=1) {
03066 newMagFilter=((ft!=Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT);
03067
03068 #ifdef _DEBUG
03069 if((ft!=Texture::FT_linear)&&(ft!=Texture::FT_nearest)) {
03070 dxgsg8_cat.error() << "MipMap filter type setting for texture magfilter makes no sense, texture: " << tex->get_name() << "\n";
03071 }
03072 #endif
03073 } else {
03074 newMagFilter=D3DTEXF_ANISOTROPIC;
03075 }
03076
03077 if(_CurTexMagFilter!=newMagFilter) {
03078 _CurTexMagFilter=newMagFilter;
03079 _pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, newMagFilter);
03080 }
03081
03082 #ifdef _DEBUG
03083 assert(Texture::FT_linear_mipmap_linear < 8);
03084 #endif
03085
03086
03087
03088
03089
03090
03091 static D3DTEXTUREFILTERTYPE PandaToD3DMinType[8] =
03092 {D3DTEXF_POINT,D3DTEXF_LINEAR,D3DTEXF_POINT,D3DTEXF_LINEAR,D3DTEXF_POINT,D3DTEXF_LINEAR};
03093 static D3DTEXTUREFILTERTYPE PandaToD3DMipType[8] =
03094 {D3DTEXF_NONE,D3DTEXF_NONE,D3DTEXF_POINT,D3DTEXF_POINT,D3DTEXF_LINEAR,D3DTEXF_LINEAR};
03095
03096 ft=tex->get_minfilter();
03097
03098 #ifdef _DEBUG
03099 if(ft > Texture::FT_linear_mipmap_linear) {
03100 dxgsg8_cat.error() << "Unknown tex filter type for tex: " << tex->get_name() << " filter: "<<(DWORD)ft<<"\n";
03101 return;
03102 }
03103 #endif
03104
03105 D3DTEXTUREFILTERTYPE newMipFilter = PandaToD3DMipType[(DWORD)ft];
03106
03107 #ifndef NDEBUG
03108
03109 extern char *PandaFilterNameStrs[];
03110 if((!(dtc->_bHasMipMaps))&&(newMipFilter!=D3DTEXF_NONE)) {
03111 dxgsg8_cat.error() << "Trying to set mipmap filtering for texture with no generated mipmaps!! texname[" << tex->get_name() << "], filter("<<PandaFilterNameStrs[ft]<<")\n";
03112 newMipFilter=D3DTEXF_NONE;
03113 }
03114 #endif
03115
03116
03117 D3DTEXTUREFILTERTYPE newMinFilter = PandaToD3DMinType[(DWORD)ft];
03118
03119 if(aniso_degree>=2) {
03120 newMinFilter=D3DTEXF_ANISOTROPIC;
03121 }
03122
03123 if(newMinFilter!=_CurTexMinFilter) {
03124 _CurTexMinFilter = newMinFilter;
03125 _pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, newMinFilter);
03126 }
03127
03128 if(newMipFilter!=_CurTexMipFilter) {
03129 _CurTexMipFilter = newMipFilter;
03130 _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, newMipFilter);
03131 }
03132
03133
03134
03135 _pD3DDevice->SetTexture(0,dtc->_pD3DTexture8);
03136
03137 #if 0
03138 if (dtc!=NULL) {
03139 dxgsg8_cat.spam() << "Setting active DX texture: " << dtc->_tex->get_name() << "\n";
03140 }
03141 #endif
03142
03143 _pCurTexContext = dtc;
03144 }
03145
03146
03147
03148
03149
03150
03151
03152 void DXGraphicsStateGuardian8::
03153 release_texture(TextureContext *tc) {
03154 DXTextureContext8 *gtc = DCAST(DXTextureContext8, tc);
03155 Texture *tex = tc->_texture;
03156
03157 gtc->DeleteTexture();
03158 bool erased = unmark_prepared_texture(gtc);
03159
03160
03161
03162 nassertv(erased);
03163
03164 tex->clear_gsg(this);
03165
03166 delete gtc;
03167 }
03168
03169
03170
03171 void DXGraphicsStateGuardian8::
03172 copy_texture(TextureContext *tc, const DisplayRegion *dr) {
03173
03174 HRESULT hr;
03175 int xo, yo, w, h;
03176 dr->get_region_pixels(xo, yo, w, h);
03177
03178 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
03179 PixelBuffer *pb = dtc->_tex->_pbuffer;
03180 pb->set_size(0,0,w-xo,h-yo);
03181
03182 IDirect3DSurface8 *pTexSurfaceLev0,*pCurRenderTarget;
03183 hr = dtc->_pD3DTexture8->GetSurfaceLevel(0,&pTexSurfaceLev0);
03184 if(FAILED(hr)) {
03185 dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
03186 exit(1);
03187 }
03188
03189 hr = _pD3DDevice->GetRenderTarget(&pCurRenderTarget);
03190 if(FAILED(hr)) {
03191 dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr);
03192 exit(1);
03193 }
03194
03195
03196 RECT SrcRect;
03197
03198 SrcRect.left = xo;
03199 SrcRect.right = xo+w;
03200 SrcRect.top = yo;
03201 SrcRect.bottom = yo+h;
03202
03203
03204 hr = _pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL);
03205 if(FAILED(hr)) {
03206 dxgsg8_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr);
03207 exit(1);
03208 }
03209
03210 SAFE_RELEASE(pCurRenderTarget);
03211 SAFE_RELEASE(pTexSurfaceLev0);
03212 }
03213
03214
03215
03216
03217
03218
03219
03220 void DXGraphicsStateGuardian8::
03221 copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
03222 set_read_buffer(rb);
03223 copy_texture(tc, dr);
03224 }
03225
03226
03227
03228
03229
03230
03231 void DXGraphicsStateGuardian8::
03232 texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
03233
03234
03235 #if 0
03236
03237 nassertv(tc != NULL && pb != NULL);
03238
03239 Texture *tex = tc->_texture;
03240
03241 int w = tex->_pbuffer->get_xsize();
03242 int h = tex->_pbuffer->get_ysize();
03243
03244 PT(DisplayRegion) dr = _win->make_scratch_display_region(w, h);
03245
03246 FrameBufferStack old_fb = push_frame_buffer
03247 (get_render_buffer(RenderBuffer::T_back | RenderBuffer::T_depth),
03248 dr);
03249
03250 texture_to_pixel_buffer(tc, pb, dr);
03251
03252 pop_frame_buffer(old_fb);
03253 #else
03254 dxgsg8_cat.error() << "texture_to_pixel_buffer unimplemented for DX!\n";
03255 #endif
03256 }
03257
03258
03259
03260
03261
03262
03263 void DXGraphicsStateGuardian8::
03264 texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb,
03265 const DisplayRegion *dr) {
03266 dxgsg8_cat.error()
03267 << "texture_to_pixel_buffer unimplemented!\n";
03268 }
03269
03270
03271
03272
03273
03274
03275 void DXGraphicsStateGuardian8::
03276 copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
03277
03278 RECT SrcCopyRect;
03279 nassertv(pb != NULL && dr != NULL);
03280
03281 int xo, yo, w, h;
03282 dr->get_region_pixels(xo, yo, w, h);
03283
03284
03285 nassertv(xo==0);
03286 nassertv(yo==0);
03287 nassertv(w==pb->get_xsize());
03288 nassertv(h==pb->get_ysize());
03289
03290 IDirect3DSurface8 *pD3DSurf;
03291 HRESULT hr;
03292
03293 RECT WindRect;
03294 GetWindowRect(_pScrn->hWnd,&WindRect);
03295
03296
03297 if(_cur_read_pixel_buffer & RenderBuffer::T_back) {
03298 hr=_pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf);
03299
03300 if(FAILED(hr)) {
03301 dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr);
03302 exit(1);
03303 }
03304
03305 D3DSURFACE_DESC SurfDesc;
03306 hr = pD3DSurf->GetDesc(&SurfDesc);
03307
03308 SrcCopyRect.top=SrcCopyRect.left=0;
03309 SrcCopyRect.right=SurfDesc.Width;
03310 SrcCopyRect.bottom=SurfDesc.Height;
03311
03312
03313
03314
03315 } else if(_cur_read_pixel_buffer & RenderBuffer::T_front) {
03316
03317
03318 DWORD TmpSurfXsize,TmpSurfYsize;
03319
03320 if(_pScrn->PresParams.Windowed) {
03321
03322
03323 MONITORINFO minfo;
03324 minfo.cbSize = sizeof(MONITORINFO);
03325 GetMonitorInfo(_pScrn->hMon, &minfo);
03326
03327 TmpSurfXsize=RECT_XSIZE(minfo.rcMonitor);
03328 TmpSurfYsize=RECT_YSIZE(minfo.rcMonitor);
03329
03330
03331 GetClientRect( _pScrn->hWnd, &SrcCopyRect);
03332 ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left );
03333 ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right );
03334 } else {
03335 TmpSurfXsize=RECT_XSIZE(WindRect);
03336 TmpSurfYsize=RECT_YSIZE(WindRect);
03337
03338 SrcCopyRect.top=SrcCopyRect.left=0;
03339 SrcCopyRect.right=TmpSurfXsize;
03340 SrcCopyRect.bottom=TmpSurfYsize;
03341 }
03342
03343 hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf);
03344 if(FAILED(hr)) {
03345 dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr);
03346 exit(1);
03347 }
03348
03349 hr=_pD3DDevice->GetFrontBuffer(pD3DSurf);
03350
03351 if(hr==D3DERR_DEVICELOST) {
03352
03353 pD3DSurf->Release();
03354 dxgsg8_cat.error() << "copy_pixel_buffer failed: device lost\n";
03355 return;
03356 }
03357 } else {
03358 dxgsg8_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
03359 }
03360
03361 if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) {
03362 dxgsg8_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n";
03363 exit(1);
03364 }
03365
03366 (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb);
03367
03368 RELEASE(pD3DSurf,dxgsg8,"pD3DSurf",RELEASE_ONCE);
03369
03370 nassertv(!pb->_image.empty());
03371 }
03372
03373
03374
03375
03376
03377
03378 void DXGraphicsStateGuardian8::
03379 copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
03380 const RenderBuffer &rb) {
03381 set_read_buffer(rb);
03382 copy_pixel_buffer(pb, dr);
03383 }
03384
03385
03386
03387
03388
03389
03390 void DXGraphicsStateGuardian8::apply_material( const Material* material ) {
03391 D3DMATERIAL8 cur_material;
03392 cur_material.Diffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
03393 cur_material.Ambient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
03394 cur_material.Specular = *(D3DCOLORVALUE *)(material->get_specular().get_data());
03395 cur_material.Emissive = *(D3DCOLORVALUE *)(material->get_emission().get_data());
03396 cur_material.Power = material->get_shininess();
03397 _pD3DDevice->SetMaterial(&cur_material);
03398 }
03399
03400
03401
03402
03403
03404
03405 void DXGraphicsStateGuardian8::
03406 apply_fog(Fog *fog) {
03407
03408 if(_doFogType==None)
03409 return;
03410
03411 Fog::Mode panda_fogmode = fog->get_mode();
03412 D3DFOGMODE d3dfogmode = get_fog_mode_type(panda_fogmode);
03413
03414
03415
03416 _pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode);
03417
03418 const Colorf &fog_colr = fog->get_color();
03419 _pD3DDevice->SetRenderState(D3DRS_FOGCOLOR,
03420 MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f));
03421
03422
03423
03424
03425 switch (panda_fogmode) {
03426 case Fog::M_linear:
03427 {
03428 float onset, opaque;
03429 fog->get_linear_range(onset, opaque);
03430
03431 _pD3DDevice->SetRenderState( D3DRS_FOGSTART,
03432 *((LPDWORD) (&onset)) );
03433 _pD3DDevice->SetRenderState( D3DRS_FOGEND,
03434 *((LPDWORD) (&opaque)) );
03435 }
03436 break;
03437 case Fog::M_exponential:
03438 case Fog::M_exponential_squared:
03439 {
03440
03441 float fog_density = fog->get_exp_density();
03442 _pD3DDevice->SetRenderState( D3DRS_FOGDENSITY,
03443 *((LPDWORD) (&fog_density)) );
03444 }
03445 break;
03446 }
03447 }
03448
03449 void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bCanJustEnable) {
03450
03451
03452
03453
03454
03455 static D3DTEXTUREOP TexBlendColorOp1[ 10] =
03456 {D3DTOP_MODULATE,D3DTOP_BLENDTEXTUREALPHA,D3DTOP_MODULATE,D3DTOP_SELECTARG1,D3DTOP_ADD};
03457
03458
03459 if (bCanJustEnable && (TexBlendMode==_CurTexBlendMode)) {
03460
03461 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] );
03462 return;
03463 }
03464
03465 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] );
03466
03467 switch (TexBlendMode) {
03468
03469 case TextureApplyAttrib::M_modulate:
03470
03471
03472 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
03473 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
03474 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
03475 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
03476 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
03477
03478 break;
03479 case TextureApplyAttrib::M_decal:
03480
03481 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
03482 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
03483
03484 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
03485 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
03486
03487 break;
03488 case TextureApplyAttrib::M_replace:
03489 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
03490
03491 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
03492 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
03493 break;
03494 case TextureApplyAttrib::M_add:
03495 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
03496 _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
03497
03498
03499 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
03500 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
03501 _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
03502
03503 break;
03504 case TextureApplyAttrib::M_blend:
03505 dxgsg8_cat.error()
03506 << "Impossible to emulate GL_BLEND in DX exactly " << (int) TexBlendMode << endl;
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531 break;
03532 default:
03533 dxgsg8_cat.error() << "Unknown texture blend mode " << (int) TexBlendMode << endl;
03534 break;
03535 }
03536 }
03537
03538
03539
03540
03541
03542
03543
03544 INLINE void DXGraphicsStateGuardian8::
03545 enable_texturing(bool val) {
03546
03547
03548
03549
03550 _texturing_enabled = val;
03551
03552
03553
03554
03555 if (val == false) {
03556 _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
03557 } else {
03558 SetTextureBlendMode(_CurTexBlendMode,true);
03559 }
03560 }
03561
03562
03563
03564
03565
03566
03567
03568 void DXGraphicsStateGuardian8::
03569 issue_transform(const TransformState *transform) {
03570
03571 D3DMATRIX *pMat = (D3DMATRIX*)transform->get_mat().get_data();
03572 _pD3DDevice->SetTransform(D3DTS_WORLD,pMat);
03573
03574 #ifdef USE_VERTEX_SHADERS
03575 if(_CurVertexShader!=NULL) {
03576
03577
03578 HRESULT hr = _pD3DDevice->SetVertexShaderConstant(VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART, pMat, 4);
03579 #ifdef _DEBUG
03580 if(FAILED(hr)) {
03581 dxgsg8_cat.error() << "SetVertexShader failed" << D3DERRORSTRING(hr);
03582 exit(1);
03583 }
03584 #endif
03585 }
03586 #endif
03587 }
03588
03589
03590
03591
03592
03593
03594 void DXGraphicsStateGuardian8::
03595 issue_tex_matrix(const TexMatrixAttrib *attrib) {
03596
03597 }
03598
03599
03600
03601
03602
03603
03604 void DXGraphicsStateGuardian8::
03605 issue_texture(const TextureAttrib *attrib) {
03606 if (attrib->is_off()) {
03607 enable_texturing(false);
03608 } else {
03609 enable_texturing(true);
03610 Texture *tex = attrib->get_texture();
03611 nassertv(tex != (Texture *)NULL);
03612 tex->apply(this);
03613 }
03614 }
03615
03616
03617
03618
03619
03620
03621 void DXGraphicsStateGuardian8::
03622 issue_material(const MaterialAttrib *attrib) {
03623 const Material *material = attrib->get_material();
03624 if (material != (const Material *)NULL) {
03625 apply_material(material);
03626 } else {
03627
03628 Material empty;
03629 apply_material(&empty);
03630 }
03631 }
03632
03633
03634
03635
03636
03637
03638 void DXGraphicsStateGuardian8::
03639 issue_render_mode(const RenderModeAttrib *attrib) {
03640 RenderModeAttrib::Mode mode = attrib->get_mode();
03641
03642 switch (mode) {
03643 case RenderModeAttrib::M_filled:
03644 _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
03645 break;
03646
03647 case RenderModeAttrib::M_wireframe:
03648 _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
03649 break;
03650
03651 default:
03652 dxgsg8_cat.error()
03653 << "Unknown render mode " << (int)mode << endl;
03654 }
03655
03656 _current_fill_mode = mode;
03657 }
03658
03659
03660
03661
03662
03663
03664 void DXGraphicsStateGuardian8::
03665 issue_texture_apply(const TextureApplyAttrib *attrib) {
03666 }
03667
03668
03669
03670
03671
03672
03673 void DXGraphicsStateGuardian8::
03674 issue_depth_test(const DepthTestAttrib *attrib) {
03675 DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode();
03676 if (mode == DepthTestAttrib::M_none) {
03677 _depth_test_enabled = false;
03678 _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
03679 } else {
03680 _depth_test_enabled = true;
03681 _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
03682 _pD3DDevice->SetRenderState(D3DRS_ZFUNC, (D3DCMPFUNC) mode);
03683 }
03684 }
03685
03686
03687
03688
03689
03690
03691 void DXGraphicsStateGuardian8::
03692 issue_alpha_test(const AlphaTestAttrib *attrib) {
03693 AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
03694 if (mode == AlphaTestAttrib::M_none) {
03695 enable_alpha_test(false);
03696 } else {
03697
03698 call_dxAlphaFunc((D3DCMPFUNC)mode, attrib->get_reference_alpha());
03699 enable_alpha_test(true);
03700 }
03701 }
03702
03703
03704
03705
03706
03707
03708 void DXGraphicsStateGuardian8::
03709 issue_depth_write(const DepthWriteAttrib *attrib) {
03710 enable_zwritemask(attrib->get_mode() == DepthWriteAttrib::M_on);
03711 }
03712
03713
03714
03715
03716
03717
03718 void DXGraphicsStateGuardian8::
03719 issue_cull_face(const CullFaceAttrib *attrib) {
03720 CullFaceAttrib::Mode mode = attrib->get_effective_mode();
03721
03722 switch (mode) {
03723 case CullFaceAttrib::M_cull_none:
03724 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
03725 break;
03726 case CullFaceAttrib::M_cull_clockwise:
03727 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
03728 break;
03729 case CullFaceAttrib::M_cull_counter_clockwise:
03730 _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
03731 break;
03732 default:
03733 dxgsg8_cat.error()
03734 << "invalid cull face mode " << (int)mode << endl;
03735 break;
03736 }
03737 }
03738
03739
03740
03741
03742
03743
03744 void DXGraphicsStateGuardian8::
03745 issue_fog(const FogAttrib *attrib) {
03746 if (!attrib->is_off()) {
03747 enable_fog(true);
03748 Fog *fog = attrib->get_fog();
03749 nassertv(fog != (Fog *)NULL);
03750 apply_fog(fog);
03751 } else {
03752 enable_fog(false);
03753 }
03754 }
03755
03756
03757
03758
03759
03760
03761 void DXGraphicsStateGuardian8::
03762 issue_depth_offset(const DepthOffsetAttrib *attrib) {
03763 int offset = attrib->get_offset();
03764 _pD3DDevice->SetRenderState(D3DRS_ZBIAS, offset);
03765 }
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775 void DXGraphicsStateGuardian8::
03776 bind_light(PointLight *light, int light_id) {
03777
03778
03779
03780 NodePath light_np(light);
03781 const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_camera_path());
03782 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
03783 LPoint3f pos = light->get_point() * rel_mat;
03784
03785 D3DCOLORVALUE black;
03786 black.r = black.g = black.b = black.a = 0.0f;
03787 D3DLIGHT8 alight;
03788 alight.Type = D3DLIGHT_POINT;
03789 alight.Diffuse = *(D3DCOLORVALUE *)(light->get_color().get_data());
03790 alight.Ambient = black ;
03791 alight.Specular = *(D3DCOLORVALUE *)(light->get_specular_color().get_data());
03792
03793
03794
03795 alight.Position = *(D3DVECTOR *)pos.get_data();
03796
03797 alight.Range = __D3DLIGHT_RANGE_MAX;
03798 alight.Falloff = 1.0f;
03799
03800 const LVecBase3f &att = light->get_attenuation();
03801 alight.Attenuation0 = att[0];
03802 alight.Attenuation1 = att[1];
03803 alight.Attenuation2 = att[2];
03804
03805 HRESULT res = _pD3DDevice->SetLight(light_id, &alight);
03806 }
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816 void DXGraphicsStateGuardian8::
03817 bind_light(DirectionalLight *light, int light_id) {
03818
03819
03820
03821 NodePath light_np(light);
03822 const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_camera_path());
03823 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
03824 LVector3f dir = light->get_direction() * rel_mat;
03825
03826 D3DCOLORVALUE black;
03827 black.r = black.g = black.b = black.a = 0.0f;
03828
03829 D3DLIGHT8 alight;
03830 ZeroMemory(&alight, sizeof(D3DLIGHT8));
03831
03832 alight.Type = D3DLIGHT_DIRECTIONAL;
03833 alight.Diffuse = *(D3DCOLORVALUE *)(light->get_color().get_data());
03834 alight.Ambient = black ;
03835 alight.Specular = *(D3DCOLORVALUE *)(light->get_specular_color().get_data());
03836
03837 alight.Direction = *(D3DVECTOR *)dir.get_data();
03838
03839 alight.Range = __D3DLIGHT_RANGE_MAX;
03840 alight.Falloff = 1.0f;
03841
03842 alight.Attenuation0 = 1.0f;
03843 alight.Attenuation1 = 0.0f;
03844 alight.Attenuation2 = 0.0f;
03845
03846 HRESULT res = _pD3DDevice->SetLight(light_id, &alight);
03847 }
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857 void DXGraphicsStateGuardian8::
03858 bind_light(Spotlight *light, int light_id) {
03859 Lens *lens = light->get_lens();
03860 nassertv(lens != (Lens *)NULL);
03861
03862
03863
03864
03865 NodePath light_np(light);
03866 const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_camera_path());
03867 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
03868 LPoint3f pos = lens->get_nodal_point() * rel_mat;
03869 LVector3f dir = lens->get_view_vector() * rel_mat;
03870
03871 D3DCOLORVALUE black;
03872 black.r = black.g = black.b = black.a = 0.0f;
03873
03874 D3DLIGHT8 alight;
03875 ZeroMemory(&alight, sizeof(D3DLIGHT8));
03876
03877 alight.Type = D3DLIGHT_SPOT;
03878 alight.Ambient = black ;
03879 alight.Diffuse = *(D3DCOLORVALUE *)(light->get_color().get_data());
03880 alight.Specular = *(D3DCOLORVALUE *)(light->get_specular_color().get_data());
03881
03882 alight.Position = *(D3DVECTOR *)pos.get_data();
03883
03884 alight.Direction = *(D3DVECTOR *)dir.get_data();
03885
03886 alight.Range = __D3DLIGHT_RANGE_MAX;
03887 alight.Falloff = 1.0f;
03888 alight.Theta = 0.0f;
03889 alight.Phi = lens->get_hfov();
03890
03891 const LVecBase3f &att = light->get_attenuation();
03892 alight.Attenuation0 = att[0];
03893 alight.Attenuation1 = att[1];
03894 alight.Attenuation2 = att[2];
03895
03896 HRESULT res = _pD3DDevice->SetLight(light_id, &alight);
03897 }
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912 bool DXGraphicsStateGuardian8::
03913 begin_frame() {
03914 return GraphicsStateGuardian::begin_frame();
03915 }
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932 bool DXGraphicsStateGuardian8::
03933 begin_scene() {
03934 if (!GraphicsStateGuardian::begin_scene()) {
03935 return false;
03936 }
03937
03938 HRESULT hr = _pD3DDevice->BeginScene();
03939
03940 if (FAILED(hr)) {
03941 if (hr == D3DERR_DEVICELOST) {
03942 if (dxgsg8_cat.is_debug()) {
03943 dxgsg8_cat.debug()
03944 << "BeginScene returns D3DERR_DEVICELOST" << endl;
03945 }
03946
03947 CheckCooperativeLevel();
03948
03949 } else {
03950 dxgsg8_cat.error()
03951 << "BeginScene failed, unhandled error hr == "
03952 << D3DERRORSTRING(hr) << endl;
03953 exit(1);
03954 }
03955 return false;
03956 }
03957
03958 return true;
03959 }
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970 void DXGraphicsStateGuardian8::
03971 end_scene() {
03972 HRESULT hr = _pD3DDevice->EndScene();
03973
03974 if (FAILED(hr)) {
03975
03976 if (hr == D3DERR_DEVICELOST) {
03977 if(dxgsg8_cat.is_debug()) {
03978 dxgsg8_cat.debug()
03979 << "EndScene returns DeviceLost\n";
03980 }
03981 CheckCooperativeLevel();
03982
03983 } else {
03984 dxgsg8_cat.error()
03985 << "EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr);
03986 exit(1);
03987 }
03988 return;
03989 }
03990 }
03991
03992
03993
03994
03995
03996
03997
03998
03999 void DXGraphicsStateGuardian8::
04000 end_frame() {
04001 #ifdef COUNT_DRAWPRIMS
04002 {
04003 #define FRAMES_PER_DPINFO 90
04004 static DWORD LastDPInfoFrame=0;
04005 static DWORD LastTickCount=0;
04006 const float one_thousandth = 1.0f/1000.0f;
04007
04008 if (_cur_frame_count-LastDPInfoFrame > FRAMES_PER_DPINFO) {
04009 DWORD CurTickCount=GetTickCount();
04010 float delta_secs=(CurTickCount-LastTickCount)*one_thousandth;
04011
04012 float numframes=_cur_frame_count-LastDPInfoFrame;
04013 float verts_per_frame = cVertcount/numframes;
04014 float tris_per_frame = cTricount/numframes;
04015 float DPs_per_frame = cDPcount/numframes;
04016 float DPs_notexchange_per_frame = cDP_noTexChangeCount/numframes;
04017 float verts_per_DP = cVertcount/(float)cDPcount;
04018 float verts_per_sec = cVertcount/delta_secs;
04019 float tris_per_sec = cTricount/delta_secs;
04020 float Geoms_per_frame = cGeomcount/numframes;
04021 float DrawPrims_per_Geom = cDPcount/(float)cGeomcount;
04022 float verts_per_Geom = cVertcount/(float)cGeomcount;
04023
04024 dxgsg8_cat.debug() << "==================================="
04025 << "\n Avg Verts/sec:\t\t" << verts_per_sec
04026 << "\n Avg Tris/sec:\t\t" << tris_per_sec
04027 << "\n Avg Verts/frame:\t" << verts_per_frame
04028 << "\n Avg Tris/frame:\t" << tris_per_frame
04029 << "\n Avg DrawPrims/frm:\t" << DPs_per_frame
04030 << "\n Avg Verts/DrawPrim:\t" << verts_per_DP
04031 << "\n Avg DrawPrims w/no Texture Change from prev DrawPrim/frm:\t" << DPs_notexchange_per_frame
04032 << "\n Avg Geoms/frm:\t" << Geoms_per_frame
04033 << "\n Avg DrawPrims/Geom:\t" << DrawPrims_per_Geom
04034 << "\n Avg Verts/Geom:\t" << verts_per_Geom
04035 << endl;
04036
04037 LastDPInfoFrame=_cur_frame_count;
04038 cDPcount = cVertcount=cTricount=cDP_noTexChangeCount=cGeomcount=0;
04039 LastTickCount=CurTickCount;
04040 }
04041 }
04042 #endif
04043
04044 #if defined(DO_PSTATS)||defined(PRINT_RESOURCESTATS)
04045 #ifndef PRINT_RESOURCESTATS
04046 if (_texmgrmem_total_pcollector.is_active())
04047 #endif
04048 {
04049 #define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
04050 static DWORD LastTickCount=0;
04051 DWORD CurTickCount=GetTickCount();
04052
04053 if (CurTickCount-LastTickCount > TICKS_PER_GETTEXINFO) {
04054 LastTickCount=CurTickCount;
04055 report_texmgr_stats();
04056 }
04057 }
04058 #endif
04059
04060
04061
04062
04063 GraphicsStateGuardian::end_frame();
04064 }
04065
04066
04067
04068
04069
04070
04071 INLINE bool DXGraphicsStateGuardian8::
04072 wants_normals() const {
04073 return (_lighting_enabled || _normals_enabled);
04074 }
04075
04076
04077
04078
04079
04080
04081 INLINE bool DXGraphicsStateGuardian8::
04082 wants_texcoords() const {
04083 return _texturing_enabled;
04084 }
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095 bool DXGraphicsStateGuardian8::
04096 depth_offset_decals() {
04097
04098 return false;
04099 }
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114 CoordinateSystem DXGraphicsStateGuardian8::
04115 get_internal_coordinate_system() const {
04116 return CS_yup_left;
04117 }
04118
04119
04120
04121
04122
04123
04124
04125
04126
04127 INLINE float DXGraphicsStateGuardian8::
04128 compute_distance_to(const LPoint3f &point) const {
04129
04130
04131
04132
04133
04134
04135 return point[2];
04136 }
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146 void DXGraphicsStateGuardian8::
04147 set_draw_buffer(const RenderBuffer &rb) {
04148 dxgsg8_cat.fatal() << "DX set_draw_buffer unimplemented!!!";
04149 return;
04150
04151 #ifdef WBD_GL_MODE
04152 switch (rb._buffer_type & RenderBuffer::T_color) {
04153 case RenderBuffer::T_front:
04154 call_glDrawBuffer(GL_FRONT);
04155 break;
04156
04157 case RenderBuffer::T_back:
04158 call_glDrawBuffer(GL_BACK);
04159 break;
04160
04161 case RenderBuffer::T_right:
04162 call_glDrawBuffer(GL_RIGHT);
04163 break;
04164
04165 case RenderBuffer::T_left:
04166 call_glDrawBuffer(GL_LEFT);
04167 break;
04168
04169 case RenderBuffer::T_front_right:
04170 call_glDrawBuffer(GL_FRONT_RIGHT);
04171 break;
04172
04173 case RenderBuffer::T_front_left:
04174 call_glDrawBuffer(GL_FRONT_LEFT);
04175 break;
04176
04177 case RenderBuffer::T_back_right:
04178 call_glDrawBuffer(GL_BACK_RIGHT);
04179 break;
04180
04181 case RenderBuffer::T_back_left:
04182 call_glDrawBuffer(GL_BACK_LEFT);
04183 break;
04184
04185 default:
04186 call_glDrawBuffer(GL_FRONT_AND_BACK);
04187 }
04188 #endif // WBD_GL_MODE
04189 }
04190
04191
04192
04193
04194
04195
04196 void DXGraphicsStateGuardian8::
04197 set_read_buffer(const RenderBuffer &rb) {
04198
04199 if(rb._buffer_type & RenderBuffer::T_front) {
04200 _cur_read_pixel_buffer=RenderBuffer::T_front;
04201 } else if(rb._buffer_type & RenderBuffer::T_back) {
04202 _cur_read_pixel_buffer=RenderBuffer::T_back;
04203 } else {
04204 dxgsg8_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n";
04205 }
04206 return;
04207 }
04208
04209
04210
04211
04212
04213
04214
04215 INLINE D3DTEXTUREADDRESS DXGraphicsStateGuardian8::
04216 get_texture_wrap_mode(Texture::WrapMode wm) const {
04217 static D3DTEXTUREADDRESS PandaTexWrapMode_to_D3DTexWrapMode[Texture::WM_invalid] = {
04218 D3DTADDRESS_CLAMP,D3DTADDRESS_WRAP,D3DTADDRESS_MIRROR,D3DTADDRESS_MIRRORONCE,D3DTADDRESS_BORDER};
04219
04220 return PandaTexWrapMode_to_D3DTexWrapMode[wm];
04221 }
04222
04223
04224
04225
04226
04227
04228 INLINE D3DFOGMODE DXGraphicsStateGuardian8::
04229 get_fog_mode_type(Fog::Mode m) const {
04230 switch (m) {
04231 case Fog::M_linear:
04232 return D3DFOG_LINEAR;
04233 case Fog::M_exponential:
04234 return D3DFOG_EXP;
04235 case Fog::M_exponential_squared:
04236 return D3DFOG_EXP2;
04237 }
04238 dxgsg8_cat.error() << "Invalid Fog::Mode value" << endl;
04239 return D3DFOG_EXP;
04240 }
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250 void DXGraphicsStateGuardian8::
04251 enable_lighting(bool enable) {
04252 _pD3DDevice->SetRenderState(D3DRS_LIGHTING, (DWORD)enable);
04253 }
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263 void DXGraphicsStateGuardian8::
04264 set_ambient_light(const Colorf &color) {
04265 _pD3DDevice->SetRenderState(D3DRS_AMBIENT,
04266 Colorf_to_D3DCOLOR(color));
04267 }
04268
04269
04270
04271
04272
04273
04274
04275
04276 void DXGraphicsStateGuardian8::
04277 enable_light(int light_id, bool enable) {
04278 HRESULT res = _pD3DDevice->LightEnable(light_id, enable);
04279
04280 #ifdef GSG_VERBOSE
04281 dxgsg8_cat.debug()
04282 << "LightEnable(" << light_id << "=" << enable << ")" << endl;
04283 #endif
04284 }
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300 bool DXGraphicsStateGuardian8::
04301 slot_new_clip_plane(int plane_id) {
04302 return (plane_id < D3DMAXUSERCLIPPLANES);
04303 }
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313 INLINE void DXGraphicsStateGuardian8::
04314 enable_clip_plane(int plane_id, bool enable) {
04315 assert(plane_id < D3DMAXUSERCLIPPLANES);
04316
04317 DWORD bitflag = ((DWORD)1 << plane_id);
04318 if (enable) {
04319 _clip_plane_bits |= bitflag;
04320 } else {
04321 _clip_plane_bits &= ~bitflag;
04322 }
04323
04324 _pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, _clip_plane_bits);
04325 }
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335 void DXGraphicsStateGuardian8::
04336 bind_clip_plane(PlaneNode *plane, int plane_id) {
04337
04338
04339
04340 NodePath plane_np(plane);
04341 const LMatrix4f &plane_mat = plane_np.get_mat(_scene_setup->get_camera_path());
04342 LMatrix4f rel_mat = plane_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
04343 Planef world_plane = plane->get_plane() * rel_mat;
04344
04345 _pD3DDevice->SetClipPlane(plane_id, world_plane.get_data());
04346 }
04347
04348 void DXGraphicsStateGuardian8::
04349 issue_color_write(const ColorWriteAttrib *attrib) {
04350 _color_write_mode = attrib->get_mode();
04351 set_color_writemask((_color_write_mode ==ColorWriteAttrib::M_on) ? 0xFFFFFFFF : 0x0);
04352 }
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362 void DXGraphicsStateGuardian8::
04363 set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
04364 ColorBlendAttrib::Mode color_blend_mode,
04365 TransparencyAttrib::Mode transparency_mode) {
04366
04367 if((color_write_mode == ColorWriteAttrib::M_off) && !_pScrn->bCanDirectDisableColorWrites) {
04368
04369
04370
04371 enable_blend(true);
04372 call_dxBlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE);
04373 return;
04374 }
04375
04376
04377 switch (color_blend_mode) {
04378 case ColorBlendAttrib::M_none:
04379 break;
04380
04381 case ColorBlendAttrib::M_multiply:
04382 enable_blend(true);
04383 call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ZERO);
04384 return;
04385
04386 case ColorBlendAttrib::M_add:
04387 enable_blend(true);
04388 call_dxBlendFunc(D3DBLEND_ONE, D3DBLEND_ONE);
04389 return;
04390
04391 case ColorBlendAttrib::M_multiply_add:
04392 enable_blend(true);
04393 call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ONE);
04394 return;
04395
04396 default:
04397 dxgsg8_cat.error()
04398 << "Unknown color blend mode " << (int)color_blend_mode << endl;
04399 break;
04400 }
04401
04402
04403 switch (transparency_mode) {
04404 case TransparencyAttrib::M_none:
04405 case TransparencyAttrib::M_binary:
04406 break;
04407
04408 case TransparencyAttrib::M_alpha:
04409 case TransparencyAttrib::M_alpha_sorted:
04410 case TransparencyAttrib::M_multisample:
04411 case TransparencyAttrib::M_multisample_mask:
04412 case TransparencyAttrib::M_dual:
04413 enable_blend(true);
04414 call_dxBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
04415 return;
04416
04417 default:
04418 dxgsg8_cat.error()
04419 << "invalid transparency mode " << (int)transparency_mode << endl;
04420 break;
04421 }
04422
04423
04424 enable_blend(false);
04425 }
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437 PT(SavedFrameBuffer) DXGraphicsStateGuardian8::
04438 save_frame_buffer(const RenderBuffer &buffer,
04439 CPT(DisplayRegion) dr) {
04440
04441 dxgsg8_cat.error() << "save_frame_buffer unimplemented!!\n";
04442 return NULL;
04443
04444 #if 0
04445 DXSavedFrameBuffer *sfb = new DXSavedFrameBuffer(buffer, dr);
04446
04447 if (buffer._buffer_type & RenderBuffer::T_depth) {
04448
04449 sfb->_depth =
04450 new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(),
04451 dr->get_pixel_height()));
04452 copy_pixel_buffer(sfb->_depth, dr, buffer);
04453 }
04454
04455 if (buffer._buffer_type & RenderBuffer::T_back) {
04456
04457 sfb->_back_rgba = new Texture;
04458 copy_texture(sfb->_back_rgba->prepare(this), dr, buffer);
04459 }
04460
04461 return sfb;
04462 #endif
04463 }
04464
04465
04466
04467
04468
04469
04470 void DXGraphicsStateGuardian8::
04471 restore_frame_buffer(SavedFrameBuffer *frame_buffer) {
04472 dxgsg8_cat.error() << "restore_frame_buffer unimplemented!!\n";
04473 return;
04474 }
04475
04476 TypeHandle DXGraphicsStateGuardian8::get_type(void) const {
04477 return get_class_type();
04478 }
04479
04480 TypeHandle DXGraphicsStateGuardian8::get_class_type(void) {
04481 return _type_handle;
04482 }
04483
04484 void DXGraphicsStateGuardian8::init_type(void) {
04485 GraphicsStateGuardian::init_type();
04486 register_type(_type_handle, "DXGraphicsStateGuardian8",
04487 GraphicsStateGuardian::get_class_type());
04488 }
04489
04490
04491
04492
04493
04494 void DXGraphicsStateGuardian8::
04495 dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) {
04496 static bool bAtExitFnEverCalled=false;
04497
04498 if(dxgsg8_cat.is_spam()) {
04499 dxgsg8_cat.spam() << "dx_cleanup called, bAtExitFnCalled=" << bAtExitFnCalled << ", bAtExitFnEverCalled=" << bAtExitFnEverCalled << endl;
04500 }
04501
04502 bAtExitFnEverCalled = (bAtExitFnEverCalled || bAtExitFnCalled);
04503
04504
04505
04506
04507 if(bAtExitFnEverCalled)
04508 return;
04509
04510
04511
04512
04513 free_nondx_resources();
04514
04515 PRINT_REFCNT(dxgsg8,_pD3DDevice);
04516
04517
04518 release_all_textures();
04519 release_all_geoms();
04520
04521 PRINT_REFCNT(dxgsg8,_pD3DDevice);
04522
04523
04524 SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice);
04525 SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice);
04526 SAFE_RELEASE(_pGlobalTexture);
04527
04528 PRINT_REFCNT(dxgsg8,_pD3DDevice);
04529
04530
04531
04532 if (_pD3DDevice!=NULL) {
04533 for(int i=0;i<D3D_MAXTEXTURESTAGES;i++)
04534 _pD3DDevice->SetTexture(i,NULL);
04535 RELEASE(_pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO);
04536 _pScrn->pD3DDevice = NULL;
04537 }
04538
04539
04540 }
04541
04542 void DXGraphicsStateGuardian8::
04543 set_context(DXScreenData *pNewContextData) {
04544
04545
04546
04547 assert(pNewContextData!=NULL);
04548 _pScrn = pNewContextData;
04549 _pD3DDevice = _pScrn->pD3DDevice;
04550 }
04551
04552 bool refill_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) {
04553 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
04554
04555
04556
04557
04558 HRESULT hr=dtc->FillDDSurfTexturePixels();
04559 return hr==S_OK;
04560 }
04561
04562 bool delete_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) {
04563 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
04564
04565
04566 dtc->DeleteTexture();
04567 return true;
04568 }
04569
04570 bool recreate_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) {
04571 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
04572 DXGraphicsStateGuardian8 *dxgsg = (DXGraphicsStateGuardian8 *)void_dxgsg_ptr;
04573
04574
04575
04576
04577 IDirect3DTexture8 *ddtex = dtc->CreateTexture(*dxgsg->_pScrn);
04578 return ddtex!=NULL;
04579 }
04580
04581
04582 HRESULT DXGraphicsStateGuardian8::DeleteAllDeviceObjects(void) {
04583
04584
04585
04586
04587
04588
04589
04590 traverse_prepared_textures(delete_tex_callback,this);
04591
04592 if(dxgsg8_cat.is_debug())
04593 dxgsg8_cat.debug() << "release of all textures complete\n";
04594
04595
04596 SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice);
04597 SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice);
04598 SAFE_RELEASE(_pGlobalTexture);
04599
04600 assert(_pD3DDevice);
04601
04602 SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice);
04603 SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice);
04604 SAFE_RELEASE(_pGlobalTexture);
04605
04606 return S_OK;
04607 }
04608
04609
04610 HRESULT DXGraphicsStateGuardian8::RecreateAllDeviceObjects(void) {
04611
04612
04613
04614 traverse_prepared_textures(recreate_tex_callback,this);
04615
04616 if(dxgsg8_cat.is_debug())
04617 dxgsg8_cat.debug() << "recreation of all textures complete\n";
04618 return S_OK;
04619 }
04620
04621 HRESULT DXGraphicsStateGuardian8::ReleaseAllDeviceObjects(void) {
04622
04623 return S_OK;
04624 }
04625
04626
04627
04628
04629
04630
04631 void DXGraphicsStateGuardian8::show_frame(bool bNoNewFrameDrawn) {
04632 if(_pD3DDevice==NULL)
04633 return;
04634
04635
04636 HRESULT hr;
04637
04638 if(bNoNewFrameDrawn) {
04639
04640
04641 if(_pScrn->PresParams.SwapEffect==D3DSWAPEFFECT_DISCARD) {
04642
04643
04644 return;
04645 } else if(_pScrn->PresParams.SwapEffect==D3DSWAPEFFECT_FLIP) {
04646
04647
04648
04649
04650
04651
04652 return;
04653 }
04654
04655
04656
04657 }
04658
04659 hr = _pD3DDevice->Present((CONST RECT*)NULL,(CONST RECT*)NULL,(HWND)NULL,NULL);
04660 if(FAILED(hr)) {
04661 if(hr == D3DERR_DEVICELOST) {
04662 CheckCooperativeLevel();
04663 } else {
04664 dxgsg8_cat.error() << "show_frame() - Present() failed" << D3DERRORSTRING(hr);
04665 exit(1);
04666 }
04667 }
04668 }
04669
04670 HRESULT DXGraphicsStateGuardian8::reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams) {
04671 HRESULT hr;
04672
04673 assert(IS_VALID_PTR(pPresParams));
04674 assert(IS_VALID_PTR(_pScrn->pD3D8));
04675 assert(IS_VALID_PTR(_pD3DDevice));
04676
04677 ReleaseAllDeviceObjects();
04678
04679 if(!dx_full_screen) {
04680
04681
04682
04683 _pScrn->pD3D8->GetAdapterDisplayMode(_pScrn->CardIDNum, &_pScrn->DisplayMode);
04684 pPresParams->BackBufferFormat = _pScrn->DisplayMode.Format;
04685 }
04686
04687 hr=_pD3DDevice->Reset(pPresParams);
04688 if(SUCCEEDED(hr)) {
04689 if(pPresParams!=&_pScrn->PresParams)
04690 memcpy(&_pScrn->PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS));
04691 }
04692 return hr;
04693 }
04694
04695 bool DXGraphicsStateGuardian8::
04696 CheckCooperativeLevel(bool bDoReactivateWindow) {
04697 HRESULT hr = _pD3DDevice->TestCooperativeLevel();
04698
04699 if(SUCCEEDED(hr)) {
04700 assert(SUCCEEDED(_last_testcooplevel_result));
04701 return true;
04702 }
04703
04704 switch(hr) {
04705 case D3DERR_DEVICENOTRESET:
04706 _bDXisReady = false;
04707 hr=reset_d3d_device(&_pScrn->PresParams);
04708 if (FAILED(hr)) {
04709
04710 dxgsg8_cat.error()
04711 << "CheckCooperativeLevel Reset() failed, hr = " << D3DERRORSTRING(hr);
04712 exit(1);
04713 }
04714
04715
04716
04717
04718
04719
04720
04721
04722 hr = _pD3DDevice->TestCooperativeLevel();
04723 if(FAILED(hr)) {
04724
04725 dxgsg8_cat.error()
04726 << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr);
04727 exit(1);
04728 }
04729
04730 _bDXisReady = TRUE;
04731 break;
04732
04733 case D3DERR_DEVICELOST:
04734 if(SUCCEEDED(_last_testcooplevel_result)) {
04735 if(_bDXisReady) {
04736
04737 _bDXisReady = false;
04738 if(dxgsg8_cat.is_debug())
04739 dxgsg8_cat.debug() << "D3D Device was Lost, waiting...\n";
04740 }
04741 }
04742 }
04743
04744 _last_testcooplevel_result = hr;
04745 return SUCCEEDED(hr);
04746 }
04747
04748
04749
04750 // Function: adjust_view_rect
04751 // Access:
04752 // Description: we receive the new x and y position of the client
04753
04754 void DXGraphicsStateGuardian8::adjust_view_rect(int x, int y) {
04755 if (_pScrn->view_rect.left != x || _pScrn->view_rect.top != y) {
04756
04757 _pScrn->view_rect.right = x + RECT_XSIZE(_pScrn->view_rect);
04758 _pScrn->view_rect.left = x;
04759 _pScrn->view_rect.bottom = y + RECT_YSIZE(_pScrn->view_rect);
04760 _pScrn->view_rect.top = y;
04761
04762 // set_clipper(clip_rect);
04763 }
04764 }
04765 */
04766
04767 #if 0
04768
04769
04770
04771
04772
04773
04774
04775
04776 void DXGraphicsStateGuardian8::read_mipmap_images(Texture *tex) {
04777 Filename filename = tex->get_name();
04778 string name;
04779 if (filename.empty()) {
04780 static index = 0;
04781 name = "texture" + format_string(index);
04782 index++;
04783 } else {
04784 name = filename.get_basename_wo_extension();
04785 }
04786
04787 PixelBuffer *pb = tex->get_ram_image();
04788 nassertv(pb != (PixelBuffer *)NULL);
04789
04790 GLenum external_format = get_external_image_format(pb->get_format());
04791 GLenum type = get_image_type(pb->get_image_type());
04792
04793 int xsize = pb->get_xsize();
04794 int ysize = pb->get_ysize();
04795
04796
04797 glPixelStorei(GL_PACK_ALIGNMENT, 1);
04798
04799 int mipmap_level = 0;
04800 do {
04801 xsize = max(xsize, 1);
04802 ysize = max(ysize, 1);
04803
04804 PT(PixelBuffer) mpb =
04805 new PixelBuffer(xsize, ysize, pb->get_num_components(),
04806 pb->get_component_width(), pb->get_image_type(),
04807 pb->get_format());
04808 glGetTexImage(GL_TEXTURE_2D, mipmap_level, external_format,
04809 type, mpb->_image);
04810 Filename mipmap_filename = name + "_" + format_string(mipmap_level) + ".pnm";
04811 nout << "Writing mipmap level " << mipmap_level
04812 << " (" << xsize << " by " << ysize << ") "
04813 << mipmap_filename << "\n";
04814 mpb->write(mipmap_filename);
04815
04816 xsize >>= 1;
04817 ysize >>= 1;
04818 mipmap_level++;
04819 } while (xsize > 0 && ysize > 0);
04820 }
04821 #endif
04822
04823
04824 #if 0
04825
04826
04827
04828
04829
04830 HRESULT SetViewMatrix( D3DMATRIX& mat, D3DXVECTOR3& vFrom, D3DXVECTOR3& vAt,
04831 D3DXVECTOR3& vWorldUp ) {
04832
04833
04834 D3DXVECTOR3 vView = vAt - vFrom;
04835
04836 float fLength = Magnitude( vView );
04837 if (fLength < 1e-6f)
04838 return E_INVALIDARG;
04839
04840
04841 vView /= fLength;
04842
04843
04844
04845 float fDotProduct = DotProduct( vWorldUp, vView );
04846
04847 D3DXVECTOR3 vUp = vWorldUp - fDotProduct * vView;
04848
04849
04850
04851 if (1e-6f > ( fLength = Magnitude( vUp ) )) {
04852 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
04853
04854
04855 if (1e-6f > ( fLength = Magnitude( vUp ) )) {
04856 vUp = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
04857
04858 if (1e-6f > ( fLength = Magnitude( vUp ) ))
04859 return E_INVALIDARG;
04860 }
04861 }
04862
04863
04864 vUp /= fLength;
04865
04866
04867
04868 D3DXVECTOR3 vRight = CrossProduct( vUp, vView );
04869
04870
04871
04872 mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x; mat._14 = 0.0f;
04873 mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y; mat._24 = 0.0f;
04874 mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z; mat._34 = 0.0f;
04875
04876
04877 mat._41 = - DotProduct( vFrom, vRight );
04878 mat._42 = - DotProduct( vFrom, vUp );
04879 mat._43 = - DotProduct( vFrom, vView );
04880 mat._44 = 1.0f;
04881
04882 return S_OK;
04883 }
04884
04885 #endif
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896
04897 GeomNodeContext *DXGraphicsStateGuardian8::
04898 prepare_geom_node(GeomNode *node) {
04899 dxgsg8_cat.error() << "prepare_geom_node unimplemented for DX8!\n";
04900 return NULL;
04901 }
04902
04903
04904
04905
04906
04907
04908
04909 void DXGraphicsStateGuardian8::
04910 draw_geom_node(GeomNode *node, const RenderState *state,
04911 GeomNodeContext *gnc) {
04912 return;
04913 }
04914
04915
04916
04917
04918
04919
04920
04921
04922 void DXGraphicsStateGuardian8::
04923 release_geom_node(GeomNodeContext *gnc) {
04924 }
04925
04926 HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark) {
04927
04928 HRESULT hr = E_FAIL;
04929 ICONINFO iconinfo;
04930 LPDIRECT3DSURFACE8 pCursorBitmap = NULL;
04931 HDC hdcColor = NULL;
04932 HDC hdcMask = NULL;
04933 HDC hdcScreen = NULL;
04934 BITMAP bm;
04935 DWORD dwWidth,dwHeightSrc,dwHeightDest;
04936 COLORREF crColor,crMask;
04937 UINT x,y;
04938 BITMAPINFO bmi;
04939 COLORREF* pcrArrayColor = NULL;
04940 COLORREF* pcrArrayMask = NULL;
04941 DWORD* pBitmap;
04942 HGDIOBJ hgdiobjOld;
04943 bool bBWCursor;
04944
04945 ZeroMemory( &iconinfo, sizeof(iconinfo) );
04946 if( !GetIconInfo( hCursor, &iconinfo ) )
04947 goto End;
04948
04949 if (0 == GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm))
04950 goto End;
04951 dwWidth = bm.bmWidth;
04952 dwHeightSrc = bm.bmHeight;
04953
04954 if( iconinfo.hbmColor == NULL ) {
04955 bBWCursor = true;
04956 dwHeightDest = dwHeightSrc / 2;
04957 } else {
04958 bBWCursor = false;
04959 dwHeightDest = dwHeightSrc;
04960 }
04961
04962
04963 if( FAILED( hr = pd3dDevice->CreateImageSurface( dwWidth, dwHeightDest,
04964 D3DFMT_A8R8G8B8, &pCursorBitmap ) ) ) {
04965 goto End;
04966 }
04967
04968 pcrArrayMask = new DWORD[dwWidth * dwHeightSrc];
04969
04970 ZeroMemory(&bmi, sizeof(bmi));
04971 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
04972 bmi.bmiHeader.biWidth = dwWidth;
04973 bmi.bmiHeader.biHeight = dwHeightSrc;
04974 bmi.bmiHeader.biPlanes = 1;
04975 bmi.bmiHeader.biBitCount = 32;
04976 bmi.bmiHeader.biCompression = BI_RGB;
04977
04978 hdcScreen = GetDC( NULL );
04979 hdcMask = CreateCompatibleDC( hdcScreen );
04980 if( hdcMask == NULL )
04981 {
04982 hr = E_FAIL;
04983 goto End;
04984 }
04985 hgdiobjOld = SelectObject(hdcMask, iconinfo.hbmMask);
04986 GetDIBits(hdcMask, iconinfo.hbmMask, 0, dwHeightSrc,
04987 pcrArrayMask, &bmi, DIB_RGB_COLORS);
04988 SelectObject(hdcMask, hgdiobjOld);
04989
04990 if (!bBWCursor)
04991 {
04992 pcrArrayColor = new DWORD[dwWidth * dwHeightDest];
04993 hdcColor = CreateCompatibleDC( GetDC( NULL ) );
04994 if( hdcColor == NULL )
04995 {
04996 hr = E_FAIL;
04997 goto End;
04998 }
04999 SelectObject(hdcColor, iconinfo.hbmColor);
05000 GetDIBits(hdcColor, iconinfo.hbmColor, 0, dwHeightDest,
05001 pcrArrayColor, &bmi, DIB_RGB_COLORS);
05002 }
05003
05004
05005 D3DLOCKED_RECT lr;
05006 pCursorBitmap->LockRect( &lr, NULL, 0 );
05007 pBitmap = (DWORD*)lr.pBits;
05008 for( y = 0; y < dwHeightDest; y++ )
05009 {
05010 for( x = 0; x < dwWidth; x++ )
05011 {
05012 if (bBWCursor)
05013 {
05014 crColor = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
05015 crMask = pcrArrayMask[dwWidth*(dwHeightSrc-1-y) + x];
05016 }
05017 else
05018 {
05019 crColor = pcrArrayColor[dwWidth*(dwHeightDest-1-y) + x];
05020 crMask = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
05021 }
05022 if (crMask == 0)
05023 pBitmap[dwWidth*y + x] = 0xff000000 | crColor;
05024 else
05025 pBitmap[dwWidth*y + x] = 0x00000000;
05026
05027
05028
05029
05030
05031
05032
05033 if( bAddWatermark && x < 12 && y < 5 )
05034 {
05035
05036
05037
05038
05039
05040
05041 const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 };
05042 if( wMask[y] & (1 << (15 - x)) )
05043 {
05044 pBitmap[dwWidth*y + x] |= 0xff808080;
05045 }
05046 }
05047 }
05048 }
05049 pCursorBitmap->UnlockRect();
05050
05051
05052 if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot,
05053 iconinfo.yHotspot, pCursorBitmap ) ) )
05054 {
05055 goto End;
05056 }
05057
05058 hr = S_OK;
05059
05060 End:
05061 if( iconinfo.hbmMask != NULL )
05062 DeleteObject( iconinfo.hbmMask );
05063 if( iconinfo.hbmColor != NULL )
05064 DeleteObject( iconinfo.hbmColor );
05065 if( hdcScreen != NULL )
05066 ReleaseDC( NULL, hdcScreen );
05067 if( hdcColor != NULL )
05068 DeleteDC( hdcColor );
05069 if( hdcMask != NULL )
05070 DeleteDC( hdcMask );
05071
05072 SAFE_DELETE_ARRAY( pcrArrayColor );
05073 SAFE_DELETE_ARRAY( pcrArrayMask );
05074 RELEASE(pCursorBitmap,dxgsg8,"pCursorBitmap",RELEASE_ONCE);
05075 return hr;
05076 }
05077
05078 #ifdef _DEBUG
05079
05080 typedef struct {
05081 float x,y,z;
05082 float nx,ny,nz;
05083 D3DCOLOR diffuse;
05084 float u,v;
05085 } POS_NORM_COLOR_TEX_VERTEX;
05086
05087 typedef struct {
05088 float x,y,z;
05089 D3DCOLOR diffuse;
05090 float u,v;
05091 } POS_COLOR_TEX_VERTEX;
05092
05093 typedef struct {
05094 float x,y,z;
05095 float u,v;
05096 } POS_TEX_VERTEX;
05097
05098
05099 POS_TEX_VERTEX junk11;
05100 POS_COLOR_TEX_VERTEX junk22;
05101 POS_NORM_COLOR_TEX_VERTEX junk33;
05102 #endif
05103