- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_stack.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 12/17/2008
    00006 //
    00007 // Filename: src-IL/src/il_stack.c
    00008 //
    00009 // Description: The main image stack
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013 // Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion
    00014 //      of not letting the user use ILimage structs but instead binding images
    00015 //      like OpenGL.
    00016
    00017 #include "il_internal.h"
    00018 #include "il_stack.h"
    00019
    00021 void ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images)
    00022 {
    00023         ILsizei Index = 0;
    00024         iFree   *TempFree = FreeNames;
    00025
    00026         if (Num < 1 || Images == NULL) {
    00027                 ilSetError(IL_INVALID_VALUE);
    00028                 return;
    00029         }
    00030
    00031         // No images have been generated yet, so create the image stack.
    00032         if (ImageStack == NULL)
    00033                 if (!iEnlargeStack())
    00034                         return;
    00035
    00036         do {
    00037                 if (FreeNames != NULL) {  // If any have been deleted, then reuse their image names.
    00038                         TempFree = (iFree*)FreeNames->Next;
    00039                         Images[Index] = FreeNames->Name;
    00040                         ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1);
    00041                         ifree(FreeNames);
    00042                         FreeNames = TempFree;
    00043                 } else {
    00044                         if (LastUsed >= StackSize)
    00045                                 if (!iEnlargeStack())
    00046                                         return;
    00047                         Images[Index] = LastUsed;
    00048                         // Must be all 1's instead of 0's, because some functions would divide by 0.
    00049                         ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1);
    00050                         LastUsed++;
    00051                 }
    00052         } while (++Index < Num);
    00053
    00054         return;
    00055 }
    00056
    00057 ILuint ILAPIENTRY ilGenImage()
    00058 {
    00059     ILuint i;
    00060     ilGenImages(1,&i);
    00061     return i;
    00062 }
    00063
    00065 void ILAPIENTRY ilBindImage(ILuint Image)
    00066 {
    00067         if (ImageStack == NULL || StackSize == 0) {
    00068                 if (!iEnlargeStack()) {
    00069                         return;
    00070                 }
    00071         }
    00072
    00073         // If the user requests a high image name.
    00074         while (Image >= StackSize) {
    00075                 if (!iEnlargeStack()) {
    00076                         return;
    00077                 }
    00078         }
    00079
    00080         if (ImageStack[Image] == NULL) {
    00081                 ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1);
    00082                 if (Image >= LastUsed) // >= ?
    00083                         LastUsed = Image + 1;
    00084         }
    00085
    00086         iCurImage = ImageStack[Image];
    00087         CurName = Image;
    00088
    00089         ParentImage = IL_TRUE;
    00090
    00091         return;
    00092 }
    00093
    00094
    00096 void ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images)
    00097 {
    00098         iFree   *Temp = FreeNames;
    00099         ILuint  Index = 0;
    00100
    00101         if (Num < 1) {
    00102                 //ilSetError(IL_INVALID_VALUE);
    00103                 return;
    00104         }
    00105         if (StackSize == 0)
    00106                 return;
    00107
    00108         do {
    00109                 if (Images[Index] > 0 && Images[Index] < LastUsed) {  // <= ?
    00110                         /*if (FreeNames != NULL) {  // Terribly inefficient
    00111                                 Temp = FreeNames;
    00112                                 do {
    00113                                         if (Temp->Name == Images[Index]) {
    00114                                                 continue;  // Sufficient?
    00115                                         }
    00116                                 } while ((Temp = Temp->Next));
    00117                         }*/
    00118
    00119                         // Already has been deleted or was never used.
    00120                         if (ImageStack[Images[Index]] == NULL)
    00121                                 continue;
    00122
    00123                         // Find out if current image - if so, set to default image zero.
    00124                         if (Images[Index] == CurName || Images[Index] == 0) {
    00125                                 iCurImage = ImageStack[0];
    00126                                 CurName = 0;
    00127                         }
    00128
    00129                         // Should *NOT* be NULL here!
    00130                         ilCloseImage(ImageStack[Images[Index]]);
    00131                         ImageStack[Images[Index]] = NULL;
    00132
    00133                         // Add to head of list - works for empty and non-empty lists
    00134                         Temp = (iFree*)ialloc(sizeof(iFree));
    00135                         if (!Temp) {
    00136                                 return;
    00137                         }
    00138                         Temp->Name = Images[Index];
    00139                         Temp->Next = FreeNames;
    00140                         FreeNames = Temp;
    00141                 }
    00142                 /*else {  // Shouldn't set an error...just continue onward.
    00143                         ilSetError(IL_ILLEGAL_OPERATION);
    00144                 }*/
    00145         } while (++Index < (ILuint)Num);
    00146 }
    00147
    00148
    00149 void ILAPIENTRY ilDeleteImage(const ILuint Num) {
    00150     ilDeleteImages(1,&Num);
    00151 }
    00152
    00154 ILboolean ILAPIENTRY ilIsImage(ILuint Image)
    00155 {
    00156         //iFree *Temp = FreeNames;
    00157
    00158         if (ImageStack == NULL)
    00159                 return IL_FALSE;
    00160         if (Image >= LastUsed || Image == 0)
    00161                 return IL_FALSE;
    00162
    00163         /*do {
    00164                 if (Temp->Name == Image)
    00165                         return IL_FALSE;
    00166         } while ((Temp = Temp->Next));*/
    00167
    00168         if (ImageStack[Image] == NULL)  // Easier check.
    00169                 return IL_FALSE;
    00170
    00171         return IL_TRUE;
    00172 }
    00173
    00174
    00176 ILAPI void ILAPIENTRY ilCloseImage(ILimage *Image)
    00177 {
    00178         if (Image == NULL)
    00179                 return;
    00180
    00181         if (Image->Data != NULL) {
    00182                 ifree(Image->Data);
    00183                 Image->Data = NULL;
    00184         }
    00185
    00186         if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) {
    00187                 ifree(Image->Pal.Palette);
    00188                 Image->Pal.Palette = NULL;
    00189         }
    00190
    00191         if (Image->Next != NULL) {
    00192                 ilCloseImage(Image->Next);
    00193                 Image->Next = NULL;
    00194         }
    00195
    00196         if (Image->Faces != NULL) {
    00197                 ilCloseImage(Image->Faces);
    00198                 Image->Mipmaps = NULL;
    00199         }
    00200
    00201         if (Image->Mipmaps != NULL) {
    00202                 ilCloseImage(Image->Mipmaps);
    00203                 Image->Mipmaps = NULL;
    00204         }
    00205
    00206         if (Image->Layers != NULL) {
    00207                 ilCloseImage(Image->Layers);
    00208                 Image->Layers = NULL;
    00209         }
    00210
    00211         if (Image->AnimList != NULL && Image->AnimSize != 0) {
    00212                 ifree(Image->AnimList);
    00213                 Image->AnimList = NULL;
    00214         }
    00215
    00216         if (Image->Profile != NULL && Image->ProfileSize != 0) {
    00217                 ifree(Image->Profile);
    00218                 Image->Profile = NULL;
    00219                 Image->ProfileSize = 0;
    00220         }
    00221
    00222         if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) {
    00223                 ifree(Image->DxtcData);
    00224                 Image->DxtcData = NULL;
    00225                 Image->DxtcFormat = IL_DXT_NO_COMP;
    00226                 Image->DxtcSize = 0;
    00227         }
    00228
    00229         ifree(Image);
    00230         Image = NULL;
    00231
    00232         return;
    00233 }
    00234
    00235
    00236 ILAPI ILboolean ILAPIENTRY ilIsValidPal(ILpal *Palette)
    00237 {
    00238         if (Palette == NULL)
    00239                 return IL_FALSE;
    00240         if (Palette->PalSize == 0 || Palette->Palette == NULL)
    00241                 return IL_FALSE;
    00242         switch (Palette->PalType)
    00243         {
    00244                 case IL_PAL_RGB24:
    00245                 case IL_PAL_RGB32:
    00246                 case IL_PAL_RGBA32:
    00247                 case IL_PAL_BGR24:
    00248                 case IL_PAL_BGR32:
    00249                 case IL_PAL_BGRA32:
    00250                         return IL_TRUE;
    00251         }
    00252         return IL_FALSE;
    00253 }
    00254
    00255
    00257 ILAPI void ILAPIENTRY ilClosePal(ILpal *Palette)
    00258 {
    00259         if (Palette == NULL)
    00260                 return;
    00261         if (!ilIsValidPal(Palette))
    00262                 return;
    00263         ifree(Palette->Palette);
    00264         ifree(Palette);
    00265         return;
    00266 }
    00267
    00268
    00269 ILimage *iGetBaseImage()
    00270 {
    00271         return ImageStack[ilGetCurName()];
    00272 }
    00273
    00274
    00276 ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number)
    00277 {
    00278         ILuint Current;
    00279     ILimage *iTempImage;
    00280
    00281         if (iCurImage == NULL) {
    00282                 ilSetError(IL_ILLEGAL_OPERATION);
    00283                 return IL_FALSE;
    00284         }
    00285
    00286         if (Number == 0) {
    00287                 return IL_TRUE;
    00288         }
    00289
    00290     iTempImage = iCurImage;
    00291         iCurImage = iCurImage->Mipmaps;
    00292         if (iCurImage == NULL) {
    00293                 iCurImage = iTempImage;
    00294                 ilSetError(IL_ILLEGAL_OPERATION);
    00295                 return IL_FALSE;
    00296         }
    00297
    00298         for (Current = 1; Current < Number; Current++) {
    00299                 iCurImage = iCurImage->Mipmaps;
    00300                 if (iCurImage == NULL) {
    00301                         ilSetError(IL_ILLEGAL_OPERATION);
    00302                         iCurImage = iTempImage;
    00303                         return IL_FALSE;
    00304                 }
    00305         }
    00306
    00307         ParentImage = IL_FALSE;
    00308
    00309         return IL_TRUE;
    00310 }
    00311
    00312
    00314 ILboolean ILAPIENTRY ilActiveImage(ILuint Number)
    00315 {
    00316         ILuint Current;
    00317     ILimage *iTempImage;
    00318
    00319         if (iCurImage == NULL) {
    00320                 ilSetError(IL_ILLEGAL_OPERATION);
    00321                 return IL_FALSE;
    00322         }
    00323
    00324         if (Number == 0) {
    00325                 return IL_TRUE;
    00326         }
    00327
    00328     iTempImage = iCurImage;
    00329         iCurImage = iCurImage->Next;
    00330         if (iCurImage == NULL) {
    00331                 iCurImage = iTempImage;
    00332                 ilSetError(IL_ILLEGAL_OPERATION);
    00333                 return IL_FALSE;
    00334         }
    00335
    00336         Number--;  // Skip 0 (parent image)
    00337         for (Current = 0; Current < Number; Current++) {
    00338                 iCurImage = iCurImage->Next;
    00339                 if (iCurImage == NULL) {
    00340                         ilSetError(IL_ILLEGAL_OPERATION);
    00341                         iCurImage = iTempImage;
    00342                         return IL_FALSE;
    00343                 }
    00344         }
    00345
    00346         ParentImage = IL_FALSE;
    00347
    00348         return IL_TRUE;
    00349 }
    00350
    00351
    00353 ILboolean ILAPIENTRY ilActiveFace(ILuint Number)
    00354 {
    00355         ILuint Current;
    00356     ILimage *iTempImage;
    00357
    00358         if (iCurImage == NULL) {
    00359                 ilSetError(IL_ILLEGAL_OPERATION);
    00360                 return IL_FALSE;
    00361         }
    00362
    00363         if (Number == 0) {
    00364                 return IL_TRUE;
    00365         }
    00366
    00367     iTempImage = iCurImage;
    00368         iCurImage = iCurImage->Faces;
    00369         if (iCurImage == NULL) {
    00370                 iCurImage = iTempImage;
    00371                 ilSetError(IL_ILLEGAL_OPERATION);
    00372                 return IL_FALSE;
    00373         }
    00374
    00375         //Number--;  // Skip 0 (parent image)
    00376         for (Current = 1; Current < Number; Current++) {
    00377                 iCurImage = iCurImage->Faces;
    00378                 if (iCurImage == NULL) {
    00379                         ilSetError(IL_ILLEGAL_OPERATION);
    00380                         iCurImage = iTempImage;
    00381                         return IL_FALSE;
    00382                 }
    00383         }
    00384
    00385         ParentImage = IL_FALSE;
    00386
    00387         return IL_TRUE;
    00388 }
    00389
    00390
    00391
    00393 ILboolean ILAPIENTRY ilActiveLayer(ILuint Number)
    00394 {
    00395         ILuint Current;
    00396     ILimage *iTempImage;
    00397
    00398         if (iCurImage == NULL) {
    00399                 ilSetError(IL_ILLEGAL_OPERATION);
    00400                 return IL_FALSE;
    00401         }
    00402
    00403         if (Number == 0) {
    00404                 return IL_TRUE;
    00405         }
    00406
    00407     iTempImage = iCurImage;
    00408         iCurImage = iCurImage->Layers;
    00409         if (iCurImage == NULL) {
    00410                 iCurImage = iTempImage;
    00411                 ilSetError(IL_ILLEGAL_OPERATION);
    00412                 return IL_FALSE;
    00413         }
    00414
    00415         //Number--;  // Skip 0 (parent image)
    00416         for (Current = 1; Current < Number; Current++) {
    00417                 iCurImage = iCurImage->Layers;
    00418                 if (iCurImage == NULL) {
    00419                         ilSetError(IL_ILLEGAL_OPERATION);
    00420                         iCurImage = iTempImage;
    00421                         return IL_FALSE;
    00422                 }
    00423         }
    00424
    00425         ParentImage = IL_FALSE;
    00426
    00427         return IL_TRUE;
    00428 }
    00429
    00430
    00431 ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num)
    00432 {
    00433         ILimage *SubImage;
    00434         ILuint  Count ;  // Create one before we go in the loop.
    00435
    00436         if (iCurImage == NULL) {
    00437                 ilSetError(IL_ILLEGAL_OPERATION);
    00438                 return 0;
    00439         }
    00440         if (Num == 0)  {
    00441                 return 0;
    00442         }
    00443
    00444         switch (Type)
    00445         {
    00446                 case IL_SUB_NEXT:
    00447                         if (iCurImage->Next)
    00448                                 ilCloseImage(iCurImage->Next);
    00449                         iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
    00450                         SubImage = iCurImage->Next;
    00451                         break;
    00452
    00453                 case IL_SUB_MIPMAP:
    00454                         if (iCurImage->Mipmaps)
    00455                                 ilCloseImage(iCurImage->Mipmaps);
    00456                         iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
    00457                         SubImage = iCurImage->Mipmaps;
    00458                         break;
    00459
    00460                 case IL_SUB_LAYER:
    00461                         if (iCurImage->Layers)
    00462                                 ilCloseImage(iCurImage->Layers);
    00463                         iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1);
    00464                         SubImage = iCurImage->Layers;
    00465                         break;
    00466
    00467                 default:
    00468                         ilSetError(IL_INVALID_ENUM);
    00469                         return IL_FALSE;
    00470         }
    00471
    00472         if (SubImage == NULL) {
    00473                 return 0;
    00474         }
    00475
    00476         for (Count = 1; Count < Num; Count++) {
    00477                 SubImage->Next = ilNewImage(1, 1, 1, 1, 1);
    00478                 SubImage = SubImage->Next;
    00479                 if (SubImage == NULL)
    00480                         return Count;
    00481         }
    00482
    00483         return Count;
    00484 }
    00485
    00486
    00487 // Returns the current index.
    00488 ILAPI ILuint ILAPIENTRY ilGetCurName()
    00489 {
    00490         if (iCurImage == NULL || ImageStack == NULL || StackSize == 0)
    00491                 return 0;
    00492         return CurName;
    00493 }
    00494
    00495
    00496 // Returns the current image.
    00497 ILAPI ILimage* ILAPIENTRY ilGetCurImage()
    00498 {
    00499         return iCurImage;
    00500 }
    00501
    00502
    00503 // To be only used when the original image is going to be set back almost immediately.
    00504 ILAPI void ILAPIENTRY ilSetCurImage(ILimage *Image)
    00505 {
    00506         iCurImage = Image;
    00507         return;
    00508 }
    00509
    00510
    00511 // Completely replaces the current image and the version in the image stack.
    00512 ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image)
    00513 {
    00514         if (iCurImage) {
    00515                 ilActiveImage(0);
    00516                 ilCloseImage(iCurImage);
    00517         }
    00518         ImageStack[ilGetCurName()] = Image;
    00519         iCurImage = Image;
    00520         ParentImage = IL_TRUE;
    00521         return;
    00522 }
    00523
    00524
    00525 // Like realloc but sets new memory to 0.
    00526 void* ILAPIENTRY ilRecalloc(void *Ptr, ILuint OldSize, ILuint NewSize)
    00527 {
    00528         void *Temp = ialloc(NewSize);
    00529         ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize;
    00530
    00531         if (Temp != NULL) {
    00532                 if (Ptr != NULL) {
    00533                         memcpy(Temp, Ptr, CopySize);
    00534                         ifree(Ptr);
    00535                 }
    00536
    00537                 Ptr = Temp;
    00538
    00539                 if (OldSize < NewSize)
    00540                         imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize);
    00541         }
    00542
    00543         return Temp;
    00544 }
    00545
    00546
    00547 // Internal function to enlarge the image stack by I_STACK_INCREMENT members.
    00548 ILboolean iEnlargeStack()
    00549 {
    00550         // 02-05-2001:  Moved from ilGenImages().
    00551         // Puts the cleanup function on the exit handler once.
    00552         if (!OnExit) {
    00553                 #ifdef _MEM_DEBUG
    00554                         AddToAtexit();  // So iFreeMem doesn't get called after unfreed information.
    00555                 #endif//_MEM_DEBUG
    00556 #if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
    00557                         atexit((void*)ilShutDown);
    00558 #endif
    00559                 OnExit = IL_TRUE;
    00560         }
    00561
    00562         if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) {
    00563                 return IL_FALSE;
    00564         }
    00565         StackSize += I_STACK_INCREMENT;
    00566         return IL_TRUE;
    00567 }
    00568
    00569
    00570 static ILboolean IsInit = IL_FALSE;
    00571
    00572 // ONLY call at startup.
    00573 void ILAPIENTRY ilInit()
    00574 {
    00575         // if it is already initialized skip initialization
    00576         if (IsInit == IL_TRUE )
    00577                 return;
    00578
    00579         //ilSetMemory(NULL, NULL);  Now useless 3/4/2006 (due to modification in il_alloc.c)
    00580         ilSetError(IL_NO_ERROR);
    00581         ilDefaultStates();  // Set states to their defaults.
    00582         // Sets default file-reading callbacks.
    00583         ilResetRead();
    00584         ilResetWrite();
    00585 #if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
    00586         atexit((void*)ilRemoveRegistered);
    00587 #endif
    00588         //_WIN32_WCE
    00589         //ilShutDown();
    00590         iSetImage0();  // Beware!  Clears all existing textures!
    00591         iBindImageTemp();  // Go ahead and create the temporary image.
    00592         IsInit = IL_TRUE;
    00593         return;
    00594 }
    00595
    00596
    00597 // Frees any extra memory in the stack.
    00598 //      - Called on exit
    00599 void ILAPIENTRY ilShutDown()
    00600 {
    00601         // if it is not initialized do not shutdown
    00602         iFree* TempFree = (iFree*)FreeNames;
    00603         ILuint i;
    00604
    00605         if (!IsInit)
    00606                 return;
    00607
    00608         if (!IsInit) {  // Prevent from being called when not initialized.
    00609                 ilSetError(IL_ILLEGAL_OPERATION);
    00610                 return;
    00611         }
    00612
    00613         while (TempFree != NULL) {
    00614                 FreeNames = (iFree*)TempFree->Next;
    00615                 ifree(TempFree);
    00616                 TempFree = FreeNames;
    00617         }
    00618
    00619         //for (i = 0; i < LastUsed; i++) {
    00620         for (i = 0; i < StackSize; i++) {
    00621                 if (ImageStack[i] != NULL)
    00622                         ilCloseImage(ImageStack[i]);
    00623         }
    00624
    00625         if (ImageStack)
    00626                 ifree(ImageStack);
    00627         ImageStack = NULL;
    00628         LastUsed = 0;
    00629         StackSize = 0;
    00630         IsInit = IL_FALSE;
    00631         return;
    00632 }
    00633
    00634
    00635 // Initializes the image stack's first entry (default image) -- ONLY CALL ONCE!
    00636 void iSetImage0()
    00637 {
    00638         if (ImageStack == NULL)
    00639                 if (!iEnlargeStack())
    00640                         return;
    00641
    00642         LastUsed = 1;
    00643         CurName = 0;
    00644         ParentImage = IL_TRUE;
    00645         if (!ImageStack[0])
    00646                 ImageStack[0] = ilNewImage(1, 1, 1, 1, 1);
    00647         iCurImage = ImageStack[0];
    00648         ilDefaultImage();
    00649
    00650         return;
    00651 }
    00652
    00653
    00654 ILAPI void ILAPIENTRY iBindImageTemp()
    00655 {
    00656         if (ImageStack == NULL || StackSize <= 1)
    00657                 if (!iEnlargeStack())
    00658                         return;
    00659
    00660         if (LastUsed < 2)
    00661                 LastUsed = 2;
    00662         CurName = 1;
    00663         ParentImage = IL_TRUE;
    00664         if (!ImageStack[1])
    00665                 ImageStack[1] = ilNewImage(1, 1, 1, 1, 1);
    00666         iCurImage = ImageStack[1];
    00667
    00668         return;
    00669 }