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