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 <Stdio.h>
00024 
00025 #include "BaseType.h"
00026 #include "TPage.h"
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 // These must be a power of 2!!!
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 // NOTE - Blocks Width/Height that go into TPages MUST be <= AlignX/AlignY!!!
00042 
00043 typedef struct TPage_Block
00044 {
00045         int32                                   RefCount;                       // Number of references to this object
00046 
00047         LPDIRECTDRAWSURFACE4    Surface;                        // The DD surface for this Block
00048         LPDIRECT3DTEXTURE2              Texture;                        // The Texture interface to the surface
00049 
00050         RECT                                    Rect;                           // The Rect into the surface that this block can use
00051 
00052         uint32                                  LRU;                            // Set to the TPage->TPageMgr->LRU when accesed...
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;            // Surface description of this page (note all blocks must use this format!!!)
00066         LPDIRECTDRAWSURFACE4    Surface;                        // The DD surface for this TPage
00067         LPDIRECT3DTEXTURE2              Texture;                        // The texture interface to the surface
00068 
00069         TPage_Block                             *Blocks;                        //      Linked list of 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;                        // Linked list of TPages
00082 
00083         LPDIRECTDRAW4                   lpDD;                           // DD object used to create surfaces
00084 } TPage_Mgr;
00085 
00086 //============================================================================
00087 //       *** TPage_Mgr ***
00088 //============================================================================
00089 
00090 //============================================================================
00091 //      TPage_MgrCreate
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         // Remeber the DD object
00106         TPageMgr->lpDD = lpDD;
00107         // Ref the dd object
00108         lpDD->AddRef();                 
00109 
00110         TPageMgr->NumPages = NumPages;
00111 
00112         // Create the pages
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 //      TPage_MgrDestroy
00138 //============================================================================
00139 void TPage_MgrDestroy(TPage_Mgr **TPageMgr)
00140 {
00141         TPage_Mgr       *Mgr;
00142         TPage           *Page, *Next;
00143 
00144         Mgr = *TPageMgr;
00145 
00146         // Free the pages
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         // Release our ref on the DD object
00156         Mgr->lpDD->Release();                   
00157 
00158         free(*TPageMgr);
00159 
00160         *TPageMgr = NULL;
00161 }
00162 
00163 //============================================================================
00164 //      TPage_MgrHasTPage
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 //      TPage_MgrAttachTPage
00183 //      NOTE - A TPage can only attach to one TPage_Mgr, and only ONCE!!
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 //      TPage_MgrDetachTPage
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                 // If we get here, this better be the first TPage in the list!
00210                 Mgr->TPages = TPage->Next;
00211         }
00212 
00213         TPage->Next = NULL;
00214         TPage->Prev = NULL;
00215 }
00216 
00217 //============================================================================
00218 //      TPage_MgrFindOptimalBlock
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         // We really should make a TPage_GetOptimalBlock...
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 //         *** TPage ***
00249 //============================================================================
00250 
00251 //============================================================================
00252 //      TPage_Create
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);          // Create the very first ref
00269 
00270         if (!TPage_CreateSurfaces(Page, lpDD, SurfDesc))
00271         {
00272                 free(Page);
00273                 return NULL;
00274         }
00275 
00276         // Create the blocks
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 //      TPage_CreateRef
00312 //============================================================================
00313 void TPage_CreateRef(TPage *Page)
00314 {
00315         Page->RefCount++;
00316 }
00317 
00318 //============================================================================
00319 //      TPage_Destroy
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         // Destroy any dd surfaces for this page
00334         TPage_DestroySurfaces(Page);
00335 
00336         // Destroy all the blocks this page has
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 //      TPage_HasBlock
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 //      TPage_AttachBlock
00370 //      NOTE - A Block can only attach to one TPage, and only ONCE!!
00371 //============================================================================
00372 geBoolean TPage_AttachBlock(TPage *Page, TPage_Block *Block)
00373 {
00374         // Insert the block into the list of blocks for this Page
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 //      TPage_DetachBlock
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                 // If we get here, this better be the first Block in the list!
00399                 TPage->Blocks = Block->Next;
00400         }
00401 
00402         // Reset the Block link
00403         Block->Next = NULL;
00404         Block->Prev = NULL;
00405 }
00406 
00407 //=====================================================================================
00408 //      TPage_CreateSurfaces
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;         // All good dude
00442 }
00443 
00444 
00445 //=====================================================================================
00446 //      TPage_DestroySurfaces
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 //      *** TPage_Block ***
00465 //============================================================================
00466 
00467 //============================================================================
00468 //      TPage_BlockCreate
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();              // Ref the surface
00482         Texture->AddRef();              // Ditto...
00483 
00484         // Save off the surface, texture, and rect into the surface
00485         Block->Surface = Surface;
00486         Block->Texture = Texture;
00487         Block->Rect = *Rect;
00488 
00489         TPage_BlockCreateRef(Block);            // Create very first ref
00490 
00491         return Block;
00492 }
00493 
00494 //============================================================================
00495 //      TPage_BlockCreateRef
00496 //============================================================================
00497 geBoolean TPage_BlockCreateRef(TPage_Block *Block)
00498 {
00499         Block->RefCount++;
00500 
00501         return GE_TRUE;
00502 }
00503 
00504 //============================================================================
00505 //      TPage_BlockDestroy
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         // Destroy references to the surface and texture
00519         if (Block2->Surface)
00520                 Block2->Surface->Release();
00521 
00522         if (Block2->Texture)
00523                 Block2->Texture->Release();
00524         
00525         // Free the block
00526         free(Block2);
00527 
00528         *Block = NULL;
00529 }
00530 
00531 //============================================================================
00532 //      TPage_BlockGetTexture
00533 //============================================================================
00534 LPDIRECT3DTEXTURE2 TPage_BlockGetTexture(TPage_Block *Block)
00535 {
00536         return Block->Texture;
00537 }
00538 
00539 //============================================================================
00540 //      TPage_BlockGetSurface
00541 //============================================================================
00542 LPDIRECTDRAWSURFACE4 TPage_BlockGetSurface(TPage_Block *Block)
00543 {
00544         return Block->Surface;
00545 }
00546 
00547 //============================================================================
00548 //      TPage_BlockGetRect
00549 //============================================================================
00550 const RECT *TPage_BlockGetRect(TPage_Block *Block)
00551 {
00552         return &Block->Rect;
00553 }
00554 
00555 //============================================================================
00556 //      TPage_BlockSetLRU
00557 //============================================================================
00558 void TPage_BlockSetLRU(TPage_Block *Block, uint32 LRU)
00559 {
00560         Block->LRU = LRU;
00561 }
00562 
00563 //============================================================================
00564 //      TPage_BlockSetUserData
00565 //============================================================================
00566 void TPage_BlockSetUserData(TPage_Block *Block, void *UserData)
00567 {
00568         Block->UserData = UserData;
00569 }
00570 
00571 //============================================================================
00572 //      TPage_BlockGetUserData
00573 //============================================================================
00574 void *TPage_BlockGetUserData(TPage_Block *Block)
00575 {
00576         return Block->UserData;
00577 }

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