00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00032 geBoolean THandle_Startup(void)
00033 {
00034
00035 return GE_TRUE;
00036 }
00037
00038
00039
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
00064
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
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
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
00189 THandle->Flags |= THANDLE_UPDATE_LM;
00190 THandle->InvScale = 1.0f / (GLfloat)((1<<Log)<<4);
00191 }
00192
00193
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
00235 geBoolean DRIVERCC THandle_Lock(geRDriver_THandle *THandle, int32 MipLevel, void **Data)
00236 {
00237
00238
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
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
00283
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
00300
00301
00302 if(MipLevel == 0)
00303 {
00304 THandle->Flags |= THANDLE_UPDATE;
00305 }
00306
00307 return GE_TRUE;
00308 }
00309
00310
00311
00312
00313
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
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
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 }