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

THandle.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  THandle.c                                                                           */
00003 /*                                                                                      */
00004 /*  Author: George McBay (gfm@my-deja.com)                                              */
00005 /*  Description: Texture handle manager for OpenGL driver                               */
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 /*                                                                                      */
00018 /****************************************************************************************/
00019 
00020 #include <math.h>
00021 #include <stdio.h>
00022 
00023 #include "THandle.h"
00024 #include "OglDrv.h"
00025 #include "Render.h"
00026 
00027 
00028 geRDriver_THandle       TextureHandles[MAX_TEXTURE_HANDLES];
00029 
00030 
00031 // Init THandle system (do nothing, for now)
00032 geBoolean THandle_Startup(void)
00033 {
00034 
00035         return GE_TRUE;
00036 }
00037 
00038 
00039 // Find an empty texture handle
00040 geRDriver_THandle *FindTextureHandle()
00041 {
00042         int32                           i;
00043         geRDriver_THandle       *THandle;
00044 
00045         THandle = TextureHandles;
00046 
00047         for(i = 0; i < MAX_TEXTURE_HANDLES; i++, THandle++)
00048         {
00049                 if(!THandle->Active)
00050                 {
00051                         memset(THandle, 0, sizeof(geRDriver_THandle));
00052 
00053                         THandle->Active = GE_TRUE;
00054 
00055                         return THandle;
00056                 }
00057         }
00058 
00059         return NULL;
00060 }
00061 
00062 
00063 // Cleanup a texture handle.  Remove texture from texture memory and free up related
00064 // system memory.
00065 geBoolean DRIVERCC THandle_Destroy(geRDriver_THandle *THandle)
00066 {
00067         GLint i;
00068 
00069 
00070         if(!THandle->Active)
00071         {
00072                 return  GE_FALSE;
00073         }
00074 
00075         glDeleteTextures(1, &THandle->TextureID);
00076 
00077         for(i = 0; i < THANDLE_MAX_MIP_LEVELS; i++)
00078         {
00079                 if(THandle->Data[i] != NULL)
00080                 {
00081                         free(THandle->Data[i]);
00082                         THandle->Data[i] = NULL;
00083                 }
00084         }
00085 
00086         memset(THandle, 0, sizeof(geRDriver_THandle));  
00087 
00088         return  GE_TRUE;
00089 }
00090 
00091 
00092 // Cleanup all currently in-use texture handles
00093 geBoolean FreeAllTextureHandles(void)
00094 {
00095         int32                           i;
00096         geRDriver_THandle       *pTHandle;
00097 
00098         pTHandle = TextureHandles;
00099 
00100 
00101         for(i = 0; i < MAX_TEXTURE_HANDLES; i++, pTHandle++)
00102         {
00103                 if(!pTHandle->Active)
00104                 {
00105                         continue;
00106                 }
00107                 
00108                 THandle_Destroy(pTHandle);
00109         }
00110 
00111         glDeleteTextures(1, &decalTexObj);
00112         decalTexObj = -1;
00113 
00114         return GE_TRUE;
00115 }
00116 
00117 
00118 // Create a new texture handle...
00119 geRDriver_THandle *DRIVERCC THandle_Create(int32 Width, int32 Height, int32 NumMipLevels, 
00120                                                                                    const geRDriver_PixelFormat *PixelFormat)
00121 {
00122         int32                           SWidth, SHeight;                
00123         geRDriver_THandle       *THandle;       
00124         GLubyte                         Log;
00125 
00126         
00127         THandle = FindTextureHandle();
00128 
00129         if (!THandle)
00130         {
00131                 SetLastDrvError(DRV_ERROR_GENERIC, "OGL_THandleCreate: No more handles left.");
00132                 goto ExitWithError;
00133         }
00134 
00135         if(PixelFormat->Flags & RDRIVER_PF_3D)
00136         {
00137                 char errMsg[64];
00138 
00139                 if(Width > maxTextureSize)
00140                 {
00141                         sprintf(errMsg, "OGL_THandleCreate: Width > GL_MAX_TEXTURE_SIZE (%d)", maxTextureSize);
00142                         SetLastDrvError(DRV_ERROR_GENERIC, errMsg);
00143                         goto ExitWithError;
00144                 }
00145 
00146                 if (Height > maxTextureSize)
00147                 {
00148                         sprintf(errMsg, "OGL_THandleCreate: Height > GL_MAX_TEXTURE_SIZE (%d)", maxTextureSize);
00149                         SetLastDrvError(DRV_ERROR_GENERIC, errMsg);
00150                         goto ExitWithError;
00151                 }
00152         
00153                 SWidth = SnapToPower2(Width);
00154                 SHeight = SnapToPower2(Height);
00155 
00156                 if (Width != SWidth)
00157                 {
00158                         SetLastDrvError(DRV_ERROR_GENERIC, "OGL_THandleCreate: Not a power of 2.");
00159                         goto ExitWithError;
00160                 }
00161 
00162                 if (Height != SHeight)
00163                 {
00164                         SetLastDrvError(DRV_ERROR_GENERIC, "OGL_THandleCreate: Not a power of 2.");
00165                         goto ExitWithError;
00166                 }
00167         }
00168 
00169         THandle->MipLevels                      = NumMipLevels;
00170         THandle->Width                          = Width;
00171         THandle->Height                         = Height;
00172         THandle->PixelFormat            = *PixelFormat;
00173         THandle->Flags                          = 0;
00174         
00175         Log                                                     = (uint8)GetLog(Width, Height);
00176         
00177         if(THandle->PixelFormat.Flags & RDRIVER_PF_2D)
00178         {
00179                 THandle->PaddedWidth = SnapToPower2(THandle->Width);
00180                 THandle->PaddedHeight = SnapToPower2(THandle->Height);
00181         }
00182         else if(THandle->PixelFormat.Flags & RDRIVER_PF_3D)
00183         {
00184                 THandle->InvScale = 1.0f / (GLfloat)((1<<Log));
00185         }
00186         else
00187         {
00188                 // Must be a lightmap
00189                 THandle->Flags |= THANDLE_UPDATE_LM;
00190                 THandle->InvScale = 1.0f / (GLfloat)((1<<Log)<<4);      
00191         }
00192 
00193         // Init an OpenGL texture object to hold this texture
00194         glGenTextures(1, &THandle->TextureID);
00195 
00196         return THandle;
00197                 
00198         ExitWithError:
00199         {
00200                 return NULL;
00201         }
00202 }
00203 
00204 
00205 geBoolean DRIVERCC THandle_GetInfo(geRDriver_THandle *THandle, int32 MipLevel, geRDriver_THandleInfo *Info)
00206 {
00207 
00208         if(!THandle->Active)
00209         {
00210                 return GE_FALSE;
00211         }
00212 
00213         Info->Width                     = THandle->Width >> MipLevel;
00214         Info->Height            = THandle->Height >> MipLevel;
00215         Info->Stride            = Info->Width;
00216         Info->Flags             = 0;
00217         Info->PixelFormat       = THandle->PixelFormat;
00218 
00219         if(THandle->PixelFormat.Flags & RDRIVER_PF_CAN_DO_COLORKEY)
00220         {
00221                 Info->Flags = RDRIVER_THANDLE_HAS_COLORKEY;
00222                 Info->ColorKey = 1;
00223         }
00224         else
00225         {
00226                 Info->Flags = 0;
00227                 Info->ColorKey = 0;
00228         }
00229 
00230         return  GE_TRUE;
00231 }
00232 
00233 
00234 // Lock a texture for editing by the engine
00235 geBoolean DRIVERCC THandle_Lock(geRDriver_THandle *THandle, int32 MipLevel, void **Data)
00236 {
00237 
00238         // If we've already got data in system mem, return it to the engine as-is
00239         if(THandle->Data[MipLevel] != NULL)
00240         {
00241                 THandle->Flags |= (THANDLE_LOCKED << MipLevel);
00242                 *Data = THandle->Data[MipLevel] ;
00243                 return GE_TRUE;
00244         }
00245 
00246         // Otherwise, grab a new block of memory for the engine to draw on...
00247         if(THandle->PixelFormat.PixelFormat == GE_PIXELFORMAT_32BIT_ABGR)
00248         {
00249                 GLint mipWidth, mipHeight;
00250 
00251                 if(MipLevel == 0)
00252                 {
00253                         mipWidth = THandle->Width;
00254                         mipHeight = THandle->Height;
00255                 }
00256                 else
00257                 {
00258                         mipWidth =  (THandle->Width / (int)pow(2.0, (double)MipLevel));
00259                         mipHeight = (THandle->Height / (int)pow(2.0, (double)MipLevel));
00260                 }
00261 
00262                 THandle->Data[MipLevel] = (GLubyte *)malloc(mipWidth * mipHeight * 4);
00263         }
00264         else if(THandle->PixelFormat.PixelFormat == GE_PIXELFORMAT_24BIT_RGB)
00265         {
00266                 THandle->Data[MipLevel] = (GLubyte *)malloc(THandle->Width * THandle->Height * 3);
00267         }
00268         else
00269         {
00270                 *Data = NULL;
00271                 return GE_FALSE;
00272         }
00273 
00274 
00275         THandle->Flags |= (THANDLE_LOCKED << MipLevel);
00276         *Data = THandle->Data[MipLevel];
00277 
00278         return GE_TRUE;
00279 }
00280 
00281 
00282 // Unlocks a texture locked for editing, and sets the texture to be uploaded next time
00283 // it needs to be visible.
00284 geBoolean DRIVERCC THandle_UnLock(geRDriver_THandle *THandle, int32 MipLevel)
00285 {
00286 
00287         if(!(THandle->Flags & (THANDLE_LOCKED << MipLevel)))
00288         {
00289                 return GE_FALSE;
00290         }
00291 
00292         if(THandle->Data == NULL)
00293         {
00294                 return GE_FALSE;
00295         }
00296 
00297         THandle->Flags  &=~(THANDLE_LOCKED << MipLevel);        
00298 
00299         // Don't update on mips other than level 0.  We ignore the engine-created mips.
00300         // Somewhat inefficient (since mips will be generated twice), but good visual results.
00301         // Would be nice if you could tell the engine not to bother with mipping
00302         if(MipLevel == 0)
00303         {       
00304                 THandle->Flags  |= THANDLE_UPDATE;                                      
00305         }
00306         
00307         return GE_TRUE;
00308 }
00309 
00310 
00311 // Do an actual card upload (well, at least tell the OpenGL driver you'd like one when it 
00312 // gets a chance) of a texture.  Called from the Render_* functions when they require
00313 // use of a texture that is marked for updating (THANDLE_UPDATE)
00314 void THandle_Update(geRDriver_THandle *THandle)
00315 {               
00316 
00317         if(THandle->PixelFormat.Flags & RDRIVER_PF_2D)
00318         {
00319                 if(THandle->PixelFormat.PixelFormat == GE_PIXELFORMAT_24BIT_RGB)
00320                 {
00321                         if(THandle->Width <= maxTextureSize && THandle->Height <= maxTextureSize)
00322                         {
00323                                 GLubyte *dest;
00324 
00325                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00326                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00327                                 
00328                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00329                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00330                         
00331                                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5f);
00332 
00333                                 dest = malloc(THandle->PaddedWidth * THandle->PaddedHeight * 4);
00334 
00335                                 CkBlit24_32(dest, THandle->PaddedWidth, THandle->PaddedHeight, THandle->Data[0], 
00336                                         THandle->Width, THandle->Height);
00337 
00338                                 glTexImage2D(GL_TEXTURE_2D, 0, 4, THandle->PaddedWidth, THandle->PaddedHeight, 
00339                                         0, GL_RGBA, GL_UNSIGNED_BYTE, dest); 
00340 
00341                                 free(dest);
00342                         }
00343                         else
00344                         {
00345                                 if(THandle->Data[1] != NULL)
00346                                 {
00347                                         free(THandle->Data[1]);
00348                                 }
00349 
00350                                 THandle->Data[1] = malloc(THandle->Width * THandle->Height * 4);
00351 
00352                                 CkBlit24_32(THandle->Data[1], THandle->Width, THandle->Height, THandle->Data[0],
00353                                         THandle->Width, THandle->Height);
00354                         }
00355                 }
00356         }
00357         else
00358         {
00359 #ifdef USE_LINEAR_INTERPOLATION 
00360  #ifdef TRILINEAR_INTERPOLATION
00361                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00362                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00363  #else 
00364                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
00365                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00366  #endif
00367 #else
00368  #ifdef TRILINEAR_INTERPOLATION
00369                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
00370                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00371  #else
00372                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
00373                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00374  #endif
00375 #endif 
00376 
00377                 if(THandle->PixelFormat.PixelFormat == GE_PIXELFORMAT_32BIT_ABGR)
00378                 {
00379                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00380                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00381                         
00382                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0f);
00383                         
00384                         gluBuild2DMipmaps(GL_TEXTURE_2D, 4, THandle->Width, THandle->Height, GL_RGBA,
00385                                 GL_UNSIGNED_BYTE, THandle->Data[0]);
00386                 }
00387                 else
00388                 {
00389                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00390                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00391                         
00392                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.0f);
00393                         
00394                         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, THandle->Width, THandle->Height, 
00395                                 GL_RGB, GL_UNSIGNED_BYTE, THandle->Data[0]);
00396                 }
00397         }
00398 
00399         THandle->Flags &= ~THANDLE_UPDATE;
00400 }
00401 
00402 
00403 // Take engine supplied lightmap raw-RGB data and put it into a texture handle.
00404 void THandle_DownloadLightmap(DRV_LInfo *LInfo)
00405 {
00406         GLubyte *tempBits;
00407 
00408         THandle_Lock(LInfo->THandle, 0, (void**)&tempBits);
00409 
00410         memcpy(tempBits, LInfo->RGBLight[0], LInfo->THandle->Width * LInfo->THandle->Height * 3);
00411 
00412         THandle_UnLock(LInfo->THandle, 0);
00413 }
00414 
00415 
00416 // Reset the THandle system
00417 geBoolean DRIVERCC DrvResetAll(void)
00418 {
00419 
00420         return  FreeAllTextureHandles();
00421 }
00422 
00423 
00424 S32 SnapToPower2(S32 Width)
00425 {
00426         if(Width > 1 && Width <= 2) 
00427         {
00428                 Width = 2;
00429         }
00430         else if(Width > 2 && Width <= 4)
00431         {
00432                 Width = 4;
00433         }
00434         else if(Width > 4 && Width <= 8) 
00435         {
00436                 Width = 8;
00437         }
00438         else if(Width > 8 && Width <= 16)
00439         {
00440                 Width =16;
00441         }
00442         else if(Width > 16 && Width <= 32)
00443         {
00444                 Width = 32;
00445         }
00446         else if(Width > 32 && Width <= 64) 
00447         {
00448                 Width = 64;
00449         }
00450         else if(Width > 64 && Width <= 128) 
00451         {
00452                 Width = 128;
00453         }
00454         else if(Width > 128 && Width <= 256) 
00455         {
00456                 Width = 256;
00457         }
00458         else if(Width > 256 && Width <= 512) 
00459         {
00460                 Width = 512;
00461         }
00462         else if(Width > 512 && Width <= 1024) 
00463         {
00464                 Width = 1024;
00465         }
00466         else if(Width > 1024 && Width <= 2048) 
00467         {
00468                 Width = 2048;
00469         }
00470 
00471         return Width;
00472 }
00473 
00474 
00475 uint32 Log2(uint32 P2)
00476 {
00477         uint32          p = 0;
00478         int32           i = 0;
00479         
00480         for (i = P2; i > 0; i>>=1)
00481                 p++;
00482 
00483         return (p-1);
00484 }
00485 
00486 
00487 int32 GetLog(int32 Width, int32 Height)
00488 {
00489         int32   LWidth = SnapToPower2(max(Width, Height));
00490         
00491         return Log2(LWidth);
00492 }

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