Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

tpage.cpp

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  TPage.cpp                                                                           */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description: D3D cache manager using pages                                          */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
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 // These must be a power of 2!!!
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 // NOTE - Blocks Width/Height that go into TPages MUST be <= AlignX/AlignY!!!
00037 
00038 typedef struct TPage_Block
00039 {
00040         int32                                   RefCount;                       // Number of references to this object
00041 
00042         LPDIRECTDRAWSURFACE4    Surface;                        // The DD surface for this Block
00043         LPDIRECT3DTEXTURE2              Texture;                        // The Texture interface to the surface
00044 
00045         RECT                                    Rect;                           // The Rect into the surface that this block can use
00046 
00047         uint32                                  LRU;                            // Set to the TPage->TPageMgr->LRU when accesed...
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;            // Surface description of this page (note all blocks must use this format!!!)
00061         LPDIRECTDRAWSURFACE4    Surface;                        // The DD surface for this TPage
00062         LPDIRECT3DTEXTURE2              Texture;                        // The texture interface to the surface
00063 
00064         TPage_Block                             *Blocks;                        //      Linked list of 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;                        // Linked list of TPages
00077 
00078         LPDIRECTDRAW4                   lpDD;                           // DD object used to create surfaces
00079 } TPage_Mgr;
00080 
00081 //============================================================================
00082 //       *** TPage_Mgr ***
00083 //============================================================================
00084 
00085 //============================================================================
00086 //      TPage_MgrCreate
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         // Remeber the DD object
00101         TPageMgr->lpDD = lpDD;
00102         // Ref the dd object
00103         lpDD->AddRef();                 
00104 
00105         TPageMgr->NumPages = NumPages;
00106 
00107         // Create the pages
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 //      TPage_MgrDestroy
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         // Free the pages
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         // Release our ref on the DD object
00157         Mgr->lpDD->Release();                   
00158 
00159         free(*TPageMgr);
00160 
00161         *TPageMgr = NULL;
00162 }
00163 
00164 //============================================================================
00165 //      TPage_MgrHasTPage
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 //      TPage_MgrAttachTPage
00187 //      NOTE - A TPage can only attach to one TPage_Mgr, and only ONCE!!
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 //      TPage_MgrDetachTPage
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                 // If we get here, this better be the first TPage in the list!
00222                 assert(Mgr->TPages == TPage);
00223                 Mgr->TPages = TPage->Next;
00224         }
00225 
00226         TPage->Next = NULL;
00227         TPage->Prev = NULL;
00228 }
00229 
00230 //============================================================================
00231 //      TPage_MgrFindOptimalBlock
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         // We really should make a TPage_GetOptimalBlock...
00241 
00242         // First, find the page that has the highest LRU
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         // Now, find the block with the lowest LRU in this page
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         if (BestBlock->LRU == LRU)
00269                 BestPage->NumFull++;
00270         else
00271         */
00272                 BestBlock->LRU = LRU;
00273         BestPage->LRU = LRU;
00274 #else
00275         TPage           *Page;
00276         TPage_Block     *Block, *BestBlock;
00277         uint32          BestLRU;
00278 
00279         // We really should make a TPage_GetOptimalBlock...
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 //         *** TPage ***
00303 //============================================================================
00304 
00305 //============================================================================
00306 //      TPage_Create
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);          // Create the very first ref
00323 
00324         if (!TPage_CreateSurfaces(Page, lpDD, SurfDesc))
00325         {
00326                 free(Page);
00327                 return NULL;
00328         }
00329 
00330         // Create the blocks
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 //      TPage_CreateRef
00366 //============================================================================
00367 void TPage_CreateRef(TPage *Page)
00368 {
00369         assert(Page->RefCount >= 0);            // Refs can == 0, because thats what they are when TPages are first created
00370 
00371         Page->RefCount++;
00372 }
00373 
00374 //============================================================================
00375 //      TPage_Destroy
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         // Destroy any dd surfaces for this page
00394         TPage_DestroySurfaces(Page);
00395 
00396         // Destroy all the blocks this page has
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 //      TPage_HasBlock
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 //      TPage_AttachBlock
00435 //      NOTE - A Block can only attach to one TPage, and only ONCE!!
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         // Insert the block into the list of blocks for this Page
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 //      TPage_DetachBlock
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                 // If we get here, this better be the first Block in the list!
00472                 assert(TPage->Blocks == Block);
00473                 TPage->Blocks = Block->Next;
00474         }
00475 
00476         // Reset the Block link
00477         Block->Next = NULL;
00478         Block->Prev = NULL;
00479 }
00480 
00481 //=====================================================================================
00482 //      TPage_CreateSurfaces
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;         // All good dude
00521 }
00522 
00523 
00524 //=====================================================================================
00525 //      TPage_DestroySurfaces
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 //      *** TPage_Block ***
00546 //============================================================================
00547 
00548 //============================================================================
00549 //      TPage_BlockCreate
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();              // Ref the surface
00563         Texture->AddRef();              // Ditto...
00564 
00565         // Save off the surface, texture, and rect into the surface
00566         Block->Surface = Surface;
00567         Block->Texture = Texture;
00568         Block->Rect = *Rect;
00569 
00570         TPage_BlockCreateRef(Block);            // Create very first ref
00571 
00572         return Block;
00573 }
00574 
00575 //============================================================================
00576 //      TPage_BlockCreateRef
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 //      TPage_BlockDestroy
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         // Destroy references to the surface and texture
00607         if (Block2->Surface)
00608                 Block2->Surface->Release();
00609 
00610         if (Block2->Texture)
00611                 Block2->Texture->Release();
00612         
00613         // Free the block
00614         free(Block2);
00615 
00616         *Block = NULL;
00617 }
00618 
00619 //============================================================================
00620 //      TPage_BlockGetTexture
00621 //============================================================================
00622 LPDIRECT3DTEXTURE2 TPage_BlockGetTexture(TPage_Block *Block)
00623 {
00624         assert(Block);
00625 
00626         return Block->Texture;
00627 }
00628 
00629 //============================================================================
00630 //      TPage_BlockGetSurface
00631 //============================================================================
00632 LPDIRECTDRAWSURFACE4 TPage_BlockGetSurface(TPage_Block *Block)
00633 {
00634         assert(Block);
00635 
00636         return Block->Surface;
00637 }
00638 
00639 //============================================================================
00640 //      TPage_BlockGetRect
00641 //============================================================================
00642 const RECT *TPage_BlockGetRect(TPage_Block *Block)
00643 {
00644         assert(Block);
00645 
00646         return &Block->Rect;
00647 }
00648 
00649 //============================================================================
00650 //      TPage_BlockSetLRU
00651 //============================================================================
00652 void TPage_BlockSetLRU(TPage_Block *Block, uint32 LRU)
00653 {
00654         assert(Block);
00655 
00656         Block->LRU = LRU;
00657 }
00658 
00659 //============================================================================
00660 //      TPage_BlockSetUserData
00661 //============================================================================
00662 void TPage_BlockSetUserData(TPage_Block *Block, void *UserData)
00663 {
00664         assert(Block);
00665 
00666         Block->UserData = UserData;
00667 }
00668 
00669 //============================================================================
00670 //      TPage_BlockGetUserData
00671 //============================================================================
00672 void *TPage_BlockGetUserData(TPage_Block *Block)
00673 {
00674         assert(Block);
00675 
00676         return Block->UserData;
00677 }

Generated on Tue Sep 30 12:36:32 2003 for GTestAndEngine by doxygen 1.3.2