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 <Stdio.h>
00024
00025 #include "BaseType.h"
00026 #include "TPage.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035 #define TPAGE_WIDTH 16 // Width of TPAges
00036 #define TPAGE_HEIGHT 16 // Height of TPages
00037
00038 #define TPAGE_GRID_X 16 // Must be <= TPAGE_WIDTH, and power of 2
00039 #define TPAGE_GRID_Y 16 // Must be <= TPAGE_HEIGHT, and power of 2
00040
00041
00042
00043 typedef struct TPage_Block
00044 {
00045 int32 RefCount;
00046
00047 LPDIRECTDRAWSURFACE4 Surface;
00048 LPDIRECT3DTEXTURE2 Texture;
00049
00050 RECT Rect;
00051
00052 uint32 LRU;
00053
00054 void *UserData;
00055
00056 struct TPage_Block *Prev;
00057 struct TPage_Block *Next;
00058
00059 } TPage_Block;
00060
00061 typedef struct TPage
00062 {
00063 int32 RefCount;
00064
00065 DDSURFACEDESC2 SurfaceDesc;
00066 LPDIRECTDRAWSURFACE4 Surface;
00067 LPDIRECT3DTEXTURE2 Texture;
00068
00069 TPage_Block *Blocks;
00070
00071 uint32 LRU;
00072
00073 struct TPage *Prev;
00074 struct TPage *Next;
00075 } TPage;
00076
00077 typedef struct TPage_Mgr
00078 {
00079 int32 NumPages;
00080
00081 TPage *TPages;
00082
00083 LPDIRECTDRAW4 lpDD;
00084 } TPage_Mgr;
00085
00086
00087
00088
00089
00090
00091
00092
00093 TPage_Mgr *TPage_MgrCreate(LPDIRECTDRAW4 lpDD, const DDSURFACEDESC2 *SurfaceDesc, int32 NumPages)
00094 {
00095 TPage_Mgr *TPageMgr;
00096 int32 i;
00097
00098 TPageMgr = (TPage_Mgr*)malloc(sizeof(TPage_Mgr));
00099
00100 if (!TPageMgr)
00101 return NULL;
00102
00103 memset(TPageMgr, 0, sizeof(TPage_Mgr));
00104
00105
00106 TPageMgr->lpDD = lpDD;
00107
00108 lpDD->AddRef();
00109
00110 TPageMgr->NumPages = NumPages;
00111
00112
00113 for (i=0; i<NumPages; i++)
00114 {
00115 TPage *Page;
00116
00117 Page = TPage_Create(lpDD, SurfaceDesc);
00118
00119 if (!Page)
00120 goto ExitWithError;
00121
00122 if (!TPage_MgrAttachTPage(TPageMgr, Page))
00123 goto ExitWithError;
00124 }
00125
00126 return TPageMgr;
00127
00128 ExitWithError:
00129 {
00130 if (TPageMgr)
00131 TPage_MgrDestroy(&TPageMgr);
00132 return NULL;
00133 }
00134 }
00135
00136
00137
00138
00139 void TPage_MgrDestroy(TPage_Mgr **TPageMgr)
00140 {
00141 TPage_Mgr *Mgr;
00142 TPage *Page, *Next;
00143
00144 Mgr = *TPageMgr;
00145
00146
00147 for (Page = Mgr->TPages; Page; Page = Next)
00148 {
00149 Next = Page->Next;
00150
00151 TPage_MgrDetachTPage(Mgr, Page);
00152 TPage_Destroy(&Page);
00153 }
00154
00155
00156 Mgr->lpDD->Release();
00157
00158 free(*TPageMgr);
00159
00160 *TPageMgr = NULL;
00161 }
00162
00163
00164
00165
00166 geBoolean TPage_MgrHasTPage(TPage_Mgr *Mgr, TPage *Page)
00167 {
00168 TPage *Page2;
00169
00170 for (Page2 = Mgr->TPages; Page2; Page2 = Page2->Next)
00171 {
00172 if (Page2 == Page)
00173 {
00174 return GE_TRUE;
00175 }
00176 }
00177
00178 return GE_FALSE;
00179 }
00180
00181
00182
00183
00184
00185 geBoolean TPage_MgrAttachTPage(TPage_Mgr *Mgr, TPage *TPage)
00186 {
00187 if (Mgr->TPages)
00188 Mgr->TPages->Prev = TPage;
00189
00190 TPage->Prev = NULL;
00191 TPage->Next = Mgr->TPages;
00192 Mgr->TPages = TPage;
00193
00194 return GE_TRUE;
00195 }
00196
00197
00198
00199
00200 void TPage_MgrDetachTPage(TPage_Mgr *Mgr, TPage *TPage)
00201 {
00202 if (TPage->Next)
00203 TPage->Next->Prev = TPage->Prev;
00204
00205 if (TPage->Prev)
00206 TPage->Prev->Next = TPage->Prev;
00207 else
00208 {
00209
00210 Mgr->TPages = TPage->Next;
00211 }
00212
00213 TPage->Next = NULL;
00214 TPage->Prev = NULL;
00215 }
00216
00217
00218
00219
00220 TPage_Block *TPage_MgrFindOptimalBlock(TPage_Mgr *Mgr, uint32 LRU)
00221 {
00222 TPage *Page;
00223 TPage_Block *Block, *BestBlock;
00224 uint32 BestLRU;
00225
00226
00227 BestBlock = NULL;
00228 BestLRU = 0xffffffff;
00229
00230 for (Page = Mgr->TPages; Page; Page = Page->Next)
00231 {
00232 for (Block = Page->Blocks; Block; Block = Block->Next)
00233 {
00234 if (Block->LRU < BestLRU)
00235 {
00236 BestBlock = Block;
00237 BestLRU = Block->LRU;
00238 }
00239 }
00240 }
00241
00242 BestBlock->LRU = LRU;
00243
00244 return BestBlock;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254 TPage *TPage_Create(LPDIRECTDRAW4 lpDD, const DDSURFACEDESC2 *SurfDesc)
00255 {
00256 TPage *Page;
00257 int32 w, h;
00258
00259 Page = (TPage*)malloc(sizeof(TPage));
00260
00261 if (!Page)
00262 return NULL;
00263
00264 memset(Page, 0, sizeof(TPage));
00265
00266 Page->SurfaceDesc = *SurfDesc;
00267
00268 TPage_CreateRef(Page);
00269
00270 if (!TPage_CreateSurfaces(Page, lpDD, SurfDesc))
00271 {
00272 free(Page);
00273 return NULL;
00274 }
00275
00276
00277 for (h=0; h<TPAGE_HEIGHT/16; h++)
00278 {
00279 for (w=0; w<TPAGE_WIDTH/16; w++)
00280 {
00281 TPage_Block *Block;
00282 RECT Rect;
00283
00284 Rect.left = w*TPAGE_GRID_X;
00285 Rect.right = Rect.left+(TPAGE_GRID_X-1);
00286 Rect.top = h*TPAGE_GRID_Y;
00287 Rect.bottom = Rect.top+(TPAGE_GRID_Y-1);
00288
00289 Block = TPage_BlockCreate(Page->Surface, Page->Texture, &Rect);
00290
00291 if (!Block)
00292 goto ExitWithError;
00293
00294 if (!TPage_AttachBlock(Page, Block))
00295 goto ExitWithError;
00296 }
00297 }
00298
00299 return Page;
00300
00301 ExitWithError:
00302 {
00303 if (Page)
00304 TPage_Destroy(&Page);
00305
00306 return NULL;
00307 }
00308 }
00309
00310
00311
00312
00313 void TPage_CreateRef(TPage *Page)
00314 {
00315 Page->RefCount++;
00316 }
00317
00318
00319
00320
00321 void TPage_Destroy(TPage **Page1)
00322 {
00323 TPage *Page;
00324 TPage_Block *Block, *Next;
00325
00326 Page = *Page1;
00327
00328 Page->RefCount--;
00329
00330 if (Page->RefCount > 0)
00331 return;
00332
00333
00334 TPage_DestroySurfaces(Page);
00335
00336
00337 for (Block = Page->Blocks; Block; Block = Next)
00338 {
00339 Next = Block->Next;
00340
00341 TPage_DetachBlock(Page, Block);
00342 TPage_BlockDestroy(&Block);
00343 }
00344
00345 free(*Page1);
00346
00347 *Page1 = NULL;
00348 }
00349
00350
00351
00352
00353 geBoolean TPage_HasBlock(TPage *TPage, TPage_Block *Block)
00354 {
00355 TPage_Block *Block2;
00356
00357 for (Block2 = TPage->Blocks; Block2; Block2 = Block2->Next)
00358 {
00359 if (Block2 == Block)
00360 {
00361 return GE_TRUE;
00362 }
00363 }
00364
00365 return GE_FALSE;
00366 }
00367
00368
00369
00370
00371
00372 geBoolean TPage_AttachBlock(TPage *Page, TPage_Block *Block)
00373 {
00374
00375 if (Page->Blocks)
00376 Page->Blocks->Prev = Block;
00377
00378 Block->Prev = NULL;
00379 Block->Next = Page->Blocks;
00380
00381 Page->Blocks = Block;
00382
00383 return GE_TRUE;
00384 }
00385
00386
00387
00388
00389 void TPage_DetachBlock(TPage *TPage, TPage_Block *Block)
00390 {
00391 if (Block->Next)
00392 Block->Next->Prev = Block->Prev;
00393
00394 if (Block->Prev)
00395 Block->Prev->Next = Block->Prev;
00396 else
00397 {
00398
00399 TPage->Blocks = Block->Next;
00400 }
00401
00402
00403 Block->Next = NULL;
00404 Block->Prev = NULL;
00405 }
00406
00407
00408
00409
00410 geBoolean TPage_CreateSurfaces(TPage *Page, LPDIRECTDRAW4 lpDD, const DDSURFACEDESC2 *SurfDesc)
00411 {
00412 HRESULT Hr;
00413 DDSURFACEDESC2 ddsd;
00414
00415 memcpy(&ddsd, SurfDesc, sizeof(DDSURFACEDESC2));
00416
00417 ddsd.dwSize = sizeof(DDSURFACEDESC2);
00418 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
00419 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
00420 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC;
00421 ddsd.ddsCaps.dwCaps3 = 0;
00422 ddsd.ddsCaps.dwCaps4 = 0;
00423 ddsd.dwWidth = TPAGE_WIDTH;
00424 ddsd.dwHeight = TPAGE_HEIGHT;
00425
00426 Hr = lpDD->CreateSurface(&ddsd, &Page->Surface, NULL);
00427
00428 if (Hr != DD_OK)
00429 return GE_FALSE;
00430
00431 Hr = Page->Surface->QueryInterface(IID_IDirect3DTexture2, (void**)&Page->Texture);
00432
00433 if(Hr != DD_OK)
00434 {
00435 Page->Surface->Release();
00436 Page->Surface = NULL;
00437 Page->Texture = NULL;
00438 return GE_FALSE;
00439 }
00440
00441 return GE_TRUE;
00442 }
00443
00444
00445
00446
00447
00448 void TPage_DestroySurfaces(TPage *Page)
00449 {
00450 if (Page->Texture)
00451 {
00452 Page->Texture->Release();
00453 Page->Texture = NULL;
00454 }
00455
00456 if (Page->Surface)
00457 {
00458 Page->Surface->Release();
00459 Page->Surface = NULL;
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470 TPage_Block *TPage_BlockCreate(LPDIRECTDRAWSURFACE4 Surface, LPDIRECT3DTEXTURE2 Texture, const RECT *Rect)
00471 {
00472 TPage_Block *Block;
00473
00474 Block = (TPage_Block*)malloc(sizeof(TPage_Block));
00475
00476 if (!Block)
00477 return NULL;
00478
00479 memset(Block, 0, sizeof(TPage_Block));
00480
00481 Surface->AddRef();
00482 Texture->AddRef();
00483
00484
00485 Block->Surface = Surface;
00486 Block->Texture = Texture;
00487 Block->Rect = *Rect;
00488
00489 TPage_BlockCreateRef(Block);
00490
00491 return Block;
00492 }
00493
00494
00495
00496
00497 geBoolean TPage_BlockCreateRef(TPage_Block *Block)
00498 {
00499 Block->RefCount++;
00500
00501 return GE_TRUE;
00502 }
00503
00504
00505
00506
00507 void TPage_BlockDestroy(TPage_Block **Block)
00508 {
00509 TPage_Block *Block2;
00510
00511 Block2 = *Block;
00512
00513 Block2->RefCount--;
00514
00515 if (Block2->RefCount > 0)
00516 return;
00517
00518
00519 if (Block2->Surface)
00520 Block2->Surface->Release();
00521
00522 if (Block2->Texture)
00523 Block2->Texture->Release();
00524
00525
00526 free(Block2);
00527
00528 *Block = NULL;
00529 }
00530
00531
00532
00533
00534 LPDIRECT3DTEXTURE2 TPage_BlockGetTexture(TPage_Block *Block)
00535 {
00536 return Block->Texture;
00537 }
00538
00539
00540
00541
00542 LPDIRECTDRAWSURFACE4 TPage_BlockGetSurface(TPage_Block *Block)
00543 {
00544 return Block->Surface;
00545 }
00546
00547
00548
00549
00550 const RECT *TPage_BlockGetRect(TPage_Block *Block)
00551 {
00552 return &Block->Rect;
00553 }
00554
00555
00556
00557
00558 void TPage_BlockSetLRU(TPage_Block *Block, uint32 LRU)
00559 {
00560 Block->LRU = LRU;
00561 }
00562
00563
00564
00565
00566 void TPage_BlockSetUserData(TPage_Block *Block, void *UserData)
00567 {
00568 Block->UserData = UserData;
00569 }
00570
00571
00572
00573
00574 void *TPage_BlockGetUserData(TPage_Block *Block)
00575 {
00576 return Block->UserData;
00577 }