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