00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Windows.h>
00023 #include <DDraw.h>
00024 #include <D3D.h>
00025
00026 #include "THandle.h"
00027 #include "BaseType.h"
00028 #include "D3DDrv.h"
00029 #include "DCommon.h"
00030 #include "D3DCache.h"
00031 #include "D3D_Main.h"
00032 #include "PCache.h"
00033 #include "D3d_FX.h"
00034
00035 #include "TPage.h"
00036
00037
00038
00039
00040
00041
00042 #define MAX_TEXTURE_HANDLES 15000
00043 #define TEXTURE_CACHE_PERCENT 0.75f
00044 #define LMAP_CACHE_PERCENT 0.25f
00045 #define TSTAGE_0 0
00046 #define TSTAGE_1 1
00047
00048
00049
00050 geRDriver_THandle TextureHandles[MAX_TEXTURE_HANDLES];
00051 DDMemMgr *MemMgr;
00052 DDMemMgr_Partition *Partition[2];
00053 D3DCache *TextureCache;
00054 D3DCache *LMapCache;
00055 TPage_Mgr *TPageMgr;
00056 DDSURFACEDESC2 CurrentSurfDesc;
00057 THandle_MipData SystemToVideo[MAX_LMAP_LOG_SIZE];
00058 geBoolean CacheNeedsUpdate;
00059
00060
00061
00062
00063
00064
00065 void FreeAllCaches(void)
00066 {
00067 if (LMapCache)
00068 D3DCache_Destroy(LMapCache);
00069
00070 if (TextureCache)
00071 D3DCache_Destroy(TextureCache);
00072
00073 LMapCache = NULL;
00074 TextureCache = NULL;
00075
00076 if (Partition[1])
00077 DDMemMgr_PartitionDestroy(Partition[1]);
00078 if (Partition[0])
00079 DDMemMgr_PartitionDestroy(Partition[0]);
00080 if (MemMgr)
00081 DDMemMgr_Destroy(MemMgr);
00082
00083 Partition[1] = NULL;
00084 Partition[0] = NULL;
00085 MemMgr = NULL;
00086 }
00087
00088
00089
00090
00091 geRDriver_THandle *FindTextureHandle(void)
00092 {
00093 int32 i;
00094 geRDriver_THandle *pHandle;
00095
00096 pHandle = TextureHandles;
00097
00098 for (i=0; i< MAX_TEXTURE_HANDLES; i++, pHandle++)
00099 {
00100 if (!pHandle->Active)
00101 {
00102 memset(pHandle, 0, sizeof(geRDriver_THandle));
00103 pHandle->Active = 1;
00104 return pHandle;
00105 }
00106 }
00107
00108 SetLastDrvError(DRV_ERROR_GENERIC, "D3D_FindTextureHandle: No more handles left.\n");
00109
00110 return NULL;
00111 }
00112
00113
00114
00115
00116 geBoolean FreeAllTextureHandles(void)
00117 {
00118 int32 i;
00119 geRDriver_THandle *pHandle;
00120
00121 pHandle = TextureHandles;
00122
00123 for (i=0; i< MAX_TEXTURE_HANDLES; i++, pHandle++)
00124 {
00125 if (!pHandle->Active)
00126 continue;
00127
00128 if (!THandle_Destroy(pHandle))
00129 return GE_FALSE;
00130 }
00131
00132 return GE_TRUE;
00133 }
00134
00135
00136
00137 geBoolean THandle_Startup(void)
00138 {
00139
00140 MemMgr = DDMemMgr_Create(AppInfo.VidMemFree);
00141
00142 if (!MemMgr)
00143 goto ExitWithError;
00144
00145
00146 Partition[0] = DDMemMgr_PartitionCreate(MemMgr, (uint32)((float)DDMemMgr_GetFreeMem(MemMgr)*TEXTURE_CACHE_PERCENT));
00147
00148 if (!Partition[0])
00149 goto ExitWithError;
00150
00151
00152 Partition[1] = DDMemMgr_PartitionCreate(MemMgr, DDMemMgr_GetFreeMem(MemMgr));
00153
00154 if (!Partition[1])
00155 goto ExitWithError;
00156
00157
00158 TextureCache = D3DCache_Create("Main Texture Cache", AppInfo.lpDD, Partition[0], AppInfo.CanDoMultiTexture);
00159
00160 if (!TextureCache)
00161 goto ExitWithError;
00162
00163
00164 LMapCache = D3DCache_Create("Lightmap Cache", AppInfo.lpDD, Partition[1], AppInfo.CanDoMultiTexture);
00165
00166 if (!LMapCache)
00167 goto ExitWithError;
00168
00169
00170 if (!CreateSystemToVideoSurfaces())
00171 goto ExitWithError;
00172
00173 #ifdef USE_TPAGES
00174 TPageMgr = TPage_MgrCreate(AppInfo.lpDD, &AppInfo.ddTexFormat, 512);
00175 if (!TPageMgr)
00176 goto ExitWithError;
00177 #endif
00178
00179 return GE_TRUE;
00180
00181 ExitWithError:
00182 {
00183 THandle_Shutdown();
00184 return GE_FALSE;
00185 }
00186 }
00187
00188
00189
00190 void THandle_Shutdown(void)
00191 {
00192 FreeAllTextureHandles();
00193 FreeAllCaches();
00194 DestroySystemToVideoSurfaces();
00195
00196 CacheNeedsUpdate = GE_FALSE;
00197 }
00198
00199
00200
00201
00202 geRDriver_THandle *Create3DTHandle(geRDriver_THandle *THandle, int32 Width, int32 Height, int32 NumMipLevels, const geRDriver_PixelFormat *PixelFormat)
00203 {
00204 int32 Size, i;
00205
00206
00207 THandle->Width = Width;
00208 THandle->Height = Height;
00209 THandle->NumMipLevels = (uint8)NumMipLevels;
00210 THandle->Log = (uint8)GetLog(Width, Height);
00211 THandle->Stride = (1<<THandle->Log);
00212
00213
00214 THandle->MipData = (THandle_MipData*)malloc(sizeof(THandle_MipData)*NumMipLevels);
00215 memset(THandle->MipData, 0, sizeof(THandle_MipData)*NumMipLevels);
00216
00217 if (!THandle->MipData)
00218 {
00219 THandle_Destroy(THandle);
00220 return NULL;
00221 }
00222
00223 Size = 1<<THandle->Log;
00224
00225
00226 for (i=0; i< NumMipLevels; i++)
00227 {
00228 int32 Stage;
00229
00230 if (!THandle_CreateSurfaces(&THandle->MipData[i], Size, Size, &CurrentSurfDesc, GE_FALSE, 0))
00231 {
00232 THandle_Destroy(THandle);
00233 return NULL;
00234 }
00235
00236
00237
00238
00239 if (AppInfo.CanDoMultiTexture)
00240 Stage = TSTAGE_0;
00241 else
00242 Stage = 0;
00243
00244 THandle->MipData[i].CacheType = D3DCache_TypeCreate(TextureCache, Size, Size, 1, Stage, &CurrentSurfDesc);
00245
00246 if (!THandle->MipData[i].CacheType)
00247 {
00248 THandle_Destroy(THandle);
00249 return NULL;
00250 }
00251
00252 Size>>=1;
00253 }
00254
00255 return THandle;
00256 }
00257
00258
00259
00260
00261 geRDriver_THandle *CreateLightmapTHandle(geRDriver_THandle *THandle, int32 Width, int32 Height, int32 NumMipLevels, const geRDriver_PixelFormat *PixelFormat)
00262 {
00263 int32 Size, Stage;
00264
00265
00266
00267 THandle->Width = Width;
00268 THandle->Height = Height;
00269 THandle->NumMipLevels = (uint8)NumMipLevels;
00270 THandle->Log = (uint8)GetLog(Width, Height);
00271 THandle->Stride = 1<<THandle->Log;
00272
00273
00274 Size = 1<<THandle->Log;
00275
00276 THandle->MipData = (THandle_MipData*)malloc(sizeof(THandle_MipData)*NumMipLevels);
00277 memset(THandle->MipData, 0, sizeof(THandle_MipData)*NumMipLevels);
00278
00279 THandle->MipData[0].Flags = THANDLE_UPDATE;
00280
00281 if (AppInfo.CanDoMultiTexture)
00282 Stage = TSTAGE_1;
00283 else
00284 Stage = 0;
00285
00286 THandle->MipData[0].CacheType = D3DCache_TypeCreate(LMapCache, Size, Size, NumMipLevels, Stage, &CurrentSurfDesc);
00287
00288 if (!THandle->MipData[0].CacheType)
00289 {
00290 THandle_Destroy(THandle);
00291 return NULL;
00292 }
00293
00294 return THandle;
00295 }
00296
00297
00298
00299
00300 geRDriver_THandle *Create2DTHandle(geRDriver_THandle *THandle, int32 Width, int32 Height, int32 NumMipLevels, const geRDriver_PixelFormat *PixelFormat)
00301 {
00302
00303
00304 THandle->Width = Width;
00305 THandle->Height = Height;
00306 THandle->NumMipLevels = (uint8)NumMipLevels;
00307 THandle->Log = (uint8)GetLog(Width, Height);
00308 THandle->Stride = Width;
00309
00310
00311 THandle->MipData = (THandle_MipData*)malloc(sizeof(THandle_MipData)*NumMipLevels);
00312 memset(THandle->MipData, 0, sizeof(THandle_MipData)*NumMipLevels);
00313
00314 if (!THandle->MipData)
00315 {
00316 THandle_Destroy(THandle);
00317 return NULL;
00318 }
00319
00320 if (!THandle_CreateSurfaces(&THandle->MipData[0], Width, Height, &CurrentSurfDesc, GE_TRUE, 0))
00321 {
00322 THandle_Destroy(THandle);
00323 return NULL;
00324 }
00325
00326 return THandle;
00327 }
00328
00329
00330
00331
00332 geBoolean SetupCurrent3dDesc(gePixelFormat PixelFormat)
00333 {
00334 switch (PixelFormat)
00335 {
00336 case GE_PIXELFORMAT_16BIT_555_RGB:
00337 case GE_PIXELFORMAT_16BIT_565_RGB:
00338 {
00339 memcpy(&CurrentSurfDesc, &AppInfo.ddTexFormat, sizeof(DDSURFACEDESC2));
00340 break;
00341 }
00342 case GE_PIXELFORMAT_16BIT_4444_ARGB:
00343 {
00344 memcpy(&CurrentSurfDesc, &AppInfo.ddFourBitAlphaSurfFormat, sizeof(DDSURFACEDESC2));
00345 break;
00346 }
00347 case GE_PIXELFORMAT_16BIT_1555_ARGB:
00348 {
00349 memcpy(&CurrentSurfDesc, &AppInfo.ddOneBitAlphaSurfFormat, sizeof(DDSURFACEDESC2));
00350 break;
00351 }
00352
00353 default:
00354 {
00355 SetLastDrvError(DRV_ERROR_GENERIC, "SetupCurrent3dDesc: Invalid pixel format.\n");
00356 return GE_FALSE;
00357 }
00358 }
00359
00360 return GE_TRUE;
00361 }
00362
00363
00364
00365 geRDriver_THandle *DRIVERCC THandle_Create(int32 Width, int32 Height, int32 NumMipLevels, const geRDriver_PixelFormat *PixelFormat)
00366 {
00367 geRDriver_THandle *THandle;
00368
00369 THandle = FindTextureHandle();
00370
00371 if (!THandle)
00372 {
00373 SetLastDrvError(DRV_ERROR_GENERIC, "D3DDRV:THandle_Create: Out of texture handles.\n");
00374 return NULL;
00375 }
00376
00377 THandle->PixelFormat = *PixelFormat;
00378
00379 if (PixelFormat->Flags & RDRIVER_PF_3D)
00380 {
00381
00382 if (!SetupCurrent3dDesc(PixelFormat->PixelFormat))
00383 return NULL;
00384
00385 if (!Create3DTHandle(THandle, Width, Height, NumMipLevels, PixelFormat))
00386 return NULL;
00387
00388 CacheNeedsUpdate = GE_TRUE;
00389 }
00390 else if (PixelFormat->Flags & RDRIVER_PF_LIGHTMAP)
00391 {
00392
00393 if (!SetupCurrent3dDesc(PixelFormat->PixelFormat))
00394 return NULL;
00395
00396 if (!CreateLightmapTHandle(THandle, Width, Height, NumMipLevels, PixelFormat))
00397 return NULL;
00398
00399 CacheNeedsUpdate = GE_TRUE;
00400 }
00401 else if (PixelFormat->Flags & RDRIVER_PF_2D)
00402 {
00403
00404 memcpy(&CurrentSurfDesc, &AppInfo.ddSurfFormat, sizeof(DDSURFACEDESC2));
00405
00406 if (!Create2DTHandle(THandle, Width, Height, NumMipLevels, PixelFormat))
00407 return NULL;
00408 }
00409
00410 return THandle;
00411 }
00412
00413
00414
00415
00416 geBoolean DRIVERCC THandle_Destroy(geRDriver_THandle *THandle)
00417 {
00418 int32 i;
00419
00420
00421 for (i=0; i< THandle->NumMipLevels; i++)
00422 {
00423
00424 if (THandle->MipData[i].CacheType)
00425 {
00426 D3DCache_TypeDestroy(THandle->MipData[i].CacheType);
00427 CacheNeedsUpdate = GE_TRUE;
00428 THandle->MipData[i].CacheType = NULL;
00429 }
00430
00431 if (THandle->MipData[i].Surface)
00432 {
00433
00434 THandle_DestroySurfaces(&THandle->MipData[i]);
00435 THandle->MipData[i].Surface = NULL;
00436 THandle->MipData[i].Texture = NULL;
00437 }
00438 }
00439
00440 if (THandle->MipData)
00441 free(THandle->MipData);
00442
00443 memset(THandle, 0, sizeof(geRDriver_THandle));
00444
00445 return GE_TRUE;
00446 }
00447
00448
00449
00450 geBoolean DRIVERCC THandle_Lock(geRDriver_THandle *THandle, int32 MipLevel, void **Bits)
00451 {
00452 DDSURFACEDESC2 SurfDesc;
00453 HRESULT Result;
00454
00455
00456
00457 memset(&SurfDesc, 0, sizeof(DDSURFACEDESC2));
00458 SurfDesc.dwSize = sizeof(DDSURFACEDESC2);
00459
00460 Result = THandle->MipData[MipLevel].Surface->Lock(NULL, &SurfDesc, DDLOCK_WAIT, NULL);
00461
00462 if (Result != DD_OK)
00463 {
00464 return GE_FALSE;
00465 }
00466
00467 THandle->MipData[MipLevel].Flags |= THANDLE_LOCKED;
00468
00469 *Bits = (void*)SurfDesc.lpSurface;
00470
00471 return GE_TRUE;
00472 }
00473
00474
00475
00476
00477 geBoolean DRIVERCC THandle_UnLock(geRDriver_THandle *THandle, int32 MipLevel)
00478 {
00479 HRESULT Result;
00480
00481
00482 Result = THandle->MipData[MipLevel].Surface->Unlock(NULL);
00483
00484 if (Result != DD_OK)
00485 {
00486 return GE_FALSE;
00487 }
00488
00489 THandle->MipData[MipLevel].Flags |= THANDLE_UPDATE;
00490 THandle->MipData[MipLevel].Flags &= ~THANDLE_LOCKED;
00491
00492 return GE_TRUE;
00493 }
00494
00495
00496
00497
00498
00499 geBoolean DRIVERCC THandle_GetInfo(geRDriver_THandle *THandle, int32 MipLevel, geRDriver_THandleInfo *Info)
00500 {
00501 Info->Width = THandle->Width>>MipLevel;
00502 Info->Height = THandle->Height>>MipLevel;
00503 Info->Stride = THandle->Stride>>MipLevel;
00504
00505 if (THandle->PixelFormat.Flags & RDRIVER_PF_CAN_DO_COLORKEY)
00506 {
00507 Info->Flags = RDRIVER_THANDLE_HAS_COLORKEY;
00508 Info->ColorKey = 1;
00509 }
00510 else
00511 {
00512 Info->Flags = 0;
00513 Info->ColorKey = 0;
00514 }
00515
00516 Info->PixelFormat = THandle->PixelFormat;
00517
00518 return GE_TRUE;
00519 }
00520
00521
00522
00523
00524
00525 geBoolean CreateSystemToVideoSurfaces(void)
00526 {
00527 int32 i;
00528 DDSURFACEDESC2 SurfDesc;
00529
00530 memcpy(&SurfDesc, &AppInfo.ddTexFormat, sizeof(DDSURFACEDESC2));
00531
00532 for (i=0; i<MAX_LMAP_LOG_SIZE; i++)
00533 {
00534 int32 Size;
00535
00536 Size = 1<<i;
00537
00538 if (!THandle_CreateSurfaces(&SystemToVideo[i], Size, Size, &SurfDesc, GE_FALSE, 1))
00539 {
00540 DestroySystemToVideoSurfaces();
00541 return GE_FALSE;
00542 }
00543 }
00544
00545 return GE_TRUE;
00546 }
00547
00548
00549
00550
00551 void DestroySystemToVideoSurfaces(void)
00552 {
00553 int32 i;
00554
00555 for (i=0; i<MAX_LMAP_LOG_SIZE; i++)
00556 THandle_DestroySurfaces(&SystemToVideo[i]);
00557 }
00558
00559
00560
00561
00562 geBoolean THandle_CreateSurfaces(THandle_MipData *Surf, int32 Width, int32 Height, DDSURFACEDESC2 *SurfDesc, geBoolean ColorKey, int32 Stage)
00563 {
00564 LPDIRECTDRAWSURFACE4 Surface;
00565 DDSURFACEDESC2 ddsd;
00566 HRESULT Hr;
00567
00568 memcpy(&ddsd, SurfDesc, sizeof(DDSURFACEDESC2));
00569
00570 ddsd.dwSize = sizeof(DDSURFACEDESC2);
00571 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_TEXTURESTAGE;
00572 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
00573 ddsd.ddsCaps.dwCaps2 = 0;
00574 ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
00575 ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
00576 ddsd.ddsCaps.dwCaps3 = 0;
00577 ddsd.ddsCaps.dwCaps4 = 0;
00578 ddsd.dwWidth = Width;
00579 ddsd.dwHeight = Height;
00580
00581 ddsd.dwTextureStage = Stage;
00582
00583 Hr = AppInfo.lpDD->CreateSurface(&ddsd, &Surface, NULL);
00584
00585 if(Hr != DD_OK)
00586 {
00587 return FALSE;
00588 }
00589
00590 Surf->Surface = Surface;
00591
00592 Surf->Texture = NULL;
00593
00594 Hr = Surface->QueryInterface(IID_IDirect3DTexture2, (void**)&Surf->Texture);
00595
00596 if(Hr != DD_OK)
00597 {
00598 Surface->Release();
00599 return GE_FALSE;
00600 }
00601
00602 if (ColorKey)
00603 {
00604 DDCOLORKEY CKey;
00605
00606
00607 CKey.dwColorSpaceLowValue = 1;
00608 CKey.dwColorSpaceHighValue = 1;
00609
00610 if (Surf->Surface->SetColorKey(DDCKEY_SRCBLT , &CKey) != DD_OK)
00611 {
00612 SetLastDrvError(DRV_ERROR_GENERIC, "THandle_CreateSurfaces: SetColorKey failed for texture.");
00613 Surf->Surface->Release();
00614 Surf->Surface = NULL;
00615 Surf->Texture->Release();
00616 Surf->Texture = NULL;
00617 return FALSE;
00618 }
00619 }
00620 return GE_TRUE;
00621 }
00622
00623
00624
00625
00626 void THandle_DestroySurfaces(THandle_MipData *Surf)
00627 {
00628 if (Surf->Texture)
00629 Surf->Texture->Release();
00630 if (Surf->Surface)
00631 Surf->Surface->Release();
00632
00633 memset(Surf, 0, sizeof (THandle_MipData));
00634 }
00635
00636
00637
00638
00639 geBoolean THandle_CheckCache(void)
00640 {
00641 geRDriver_THandle *pTHandle;
00642 int32 i, Stage0, Stage1;
00643 int32 MaxTable1[9], MaxTable2[9];
00644
00645 if (!CacheNeedsUpdate)
00646 return GE_TRUE;
00647
00648 D3DMain_Log("THandle_CheckCache: Resetting texture cache...\n");
00649
00650 if (AppInfo.DeviceIdentifier.dwVendorId == 4634)
00651 {
00652 D3DMain_Log(" 3dfx card detected, using smaller number of handles...\n");
00653
00654
00655 MaxTable1[0] = 24;
00656 MaxTable1[1] = 24;
00657 MaxTable1[2] = 24;
00658 MaxTable1[3] = 24;
00659 MaxTable1[4] = 24;
00660 MaxTable1[5] = 128;
00661 MaxTable1[6] = 128;
00662 MaxTable1[7] = 128;
00663 MaxTable1[8] = 128;
00664
00665
00666 MaxTable2[0] = 128;
00667 MaxTable2[1] = 128;
00668 MaxTable2[2] = 256;
00669 MaxTable2[3] = 256;
00670 MaxTable2[4] = 256;
00671 MaxTable2[5] = 128;
00672 MaxTable2[6] = 128;
00673 MaxTable2[7] = 128;
00674 MaxTable2[8] = 128;
00675 }
00676 else
00677 {
00678 D3DMain_Log(" NO 3dfx card detected, using larger number of handles...\n");
00679
00680
00681 MaxTable1[0] = 32;
00682 MaxTable1[1] = 32;
00683 MaxTable1[2] = 32;
00684 MaxTable1[3] = 32;
00685 MaxTable1[4] = 32;
00686 MaxTable1[5] = 32;
00687 MaxTable1[6] = 128;
00688 MaxTable1[7] = 128;
00689 MaxTable1[8] = 128;
00690
00691 MaxTable2[0] = 128;
00692 MaxTable2[1] = 128;
00693 MaxTable2[2] = 256;
00694 MaxTable2[3] = 1024;
00695 MaxTable2[4] = 1024;
00696 MaxTable2[5] = 512;
00697 MaxTable2[6] = 256;
00698 MaxTable2[7] = 256;
00699 MaxTable2[8] = 256;
00700 }
00701
00702 if (AppInfo.CanDoMultiTexture)
00703 {
00704 Stage0 = TSTAGE_0;
00705 Stage1 = TSTAGE_1;
00706 }
00707 else
00708 {
00709 Stage0 = 0;
00710 Stage1 = 0;
00711 }
00712
00713 if (!D3DCache_AdjustSlots(LMapCache, MaxTable2, GE_TRUE))
00714 {
00715 D3DMain_Log("THandle_CheckCache: D3DCache_AdjustSlots failed for LMapCache.\n");
00716 return GE_FALSE;
00717 }
00718
00719 if (!D3DCache_AdjustSlots(TextureCache, MaxTable1, GE_FALSE))
00720 {
00721 D3DMain_Log("THandle_CheckCache: D3DCache_AdjustSlots failed for TextureCache.\n");
00722 return GE_FALSE;
00723 }
00724
00725
00726
00727
00728 pTHandle = TextureHandles;
00729
00730 for (i=0; i< MAX_TEXTURE_HANDLES; i++, pTHandle++)
00731 {
00732 int32 m;
00733
00734 for (m=0; m< pTHandle->NumMipLevels; m++)
00735 {
00736 pTHandle->MipData[m].Slot = NULL;
00737 }
00738 }
00739
00740 CacheNeedsUpdate = GE_FALSE;
00741
00742 return GE_TRUE;
00743 }