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

bitmap.c

Go to the documentation of this file.
00001 //bitmap.z
00002 /****************************************************************************************/
00003 /*  Bitmap.c                                                                            */
00004 /*                                                                                      */
00005 /*  Author: Charles Bloom                                                               */
00006 /*  Description:  Abstract Bitmap system                                                */
00007 /*                                                                                      */
00008 /*  The contents of this file are subject to the Genesis3D Public License               */
00009 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00010 /*  compliance with the License. You may obtain a copy of the License at                */
00011 /*  http://www.genesis3d.com                                                            */
00012 /*                                                                                      */
00013 /*  Software distributed under the License is distributed on an "AS IS"                 */
00014 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00015 /*  the License for the specific language governing rights and limitations              */
00016 /*  under the License.                                                                  */
00017 /*                                                                                      */
00018 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00019 /*Genesis3D Version 1.1 released November 15, 1999                            */
00020 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00021 /*                                                                                      */
00022 /****************************************************************************************/
00023 
00024 /*}{ *************** head *******************/
00025 
00026 /**********
00027 ***
00028 *
00029 
00030 see @@ for urgent todos !
00031 see <> for todos
00032 see {} for notes/long-term-todos
00033 
00034 -------
00035 
00036 {} when palettizing lots of mips, blit them together, so we only make
00037         one closestPal palInfo for all the blits (big speedup).
00038         (for UpdateMips too)
00039         perhaps the only way is to keep a cache of the last palInfo made and
00040         check the palette to see if its reusable.  Check on memory cost of the palInfo.
00041 
00042 {} when we blit from one set of mips to another, we could copy the palette (or build the palette!)
00043         many times.  We must do this in general, because the mips could all have different palettes.
00044         The answer is to keep track of "palette was just copied from X"
00045         (actually, setting different palettes on two locked mips will cause bad data!!)
00046 
00047 {} make a _BlitOnto which merges with alpha?
00048 
00049 *
00050 ***
00051  ********/
00052 #include        <math.h>
00053 #include        <time.h>
00054 #include        <stdio.h>
00055 #include        <assert.h>
00056 #include        <stdlib.h>
00057 #include        <string.h>
00058 
00059 #include        "basetype.h"
00060 #include        "getypes.h"
00061 #include        "ram.h"
00062 
00063 #include        "vfile.h"
00064 #include        "ErrorLog.h"
00065 #include        "Log.h"
00066 #include        "mempool.h"
00067 
00068 #include        "bitmap.h"
00069 #include        "bitmap._h"
00070 #include        "bitmap.__h"
00071 #include        "bitmap_blitdata.h"
00072 #include        "bitmap_gamma.h"
00073 
00074 #include        "palcreate.h"
00075 #include        "palettize.h"
00076 
00077 #ifdef DO_TIMER
00078 #include        "timer.h"
00079 #endif
00080 
00081 #define allocate(ptr)   ptr = geRam_Allocate(sizeof(*ptr))
00082 #define clear(ptr)              memset(ptr,0,sizeof(*ptr))
00083 
00084 #define SHIFT_R_ROUNDUP(val,shift)      (((val)+(1<<(shift)) - 1)>>(shift))
00085 
00086 /*}{ ************* statics *****************/
00087 
00088 //#define DO_TIMER
00089 
00090 //#define DONT_USE_ASM
00091 
00092 #ifdef _DEBUG
00093 #define Debug(x)        x
00094 static int _Bitmap_Debug_ActiveCount = 0;
00095 static int _Bitmap_Debug_ActiveRefs = 0;
00096 #else
00097 #define Debug(x)
00098 #endif
00099 
00100 static int BitmapInit_RefCount = 0;
00101 static MemPool * BitmapPool = NULL;
00102 
00103 void geBitmap_Start(void)
00104 {
00105         if ( BitmapInit_RefCount == 0 )
00106         {
00107                 BitmapPool = MemPool_Create(sizeof(geBitmap),100,100);
00108                 assert(BitmapPool);
00109                 Palettize_Start();
00110                 PalCreate_Start();
00111         }
00112         BitmapInit_RefCount ++;
00113 }
00114 
00115 void geBitmap_Stop(void)
00116 {
00117         assert(BitmapInit_RefCount > 0 );
00118         BitmapInit_RefCount --;
00119         if ( BitmapInit_RefCount == 0 )
00120         {
00121                 assert(BitmapPool);
00122                 MemPool_Destroy(&BitmapPool);
00123                 Palettize_Stop();
00124                 PalCreate_Stop();
00125         }
00126 }
00127 
00128 /*}{ ******** Creator Functions **********************/
00129 
00130 geBitmap * geBitmap_Create_Base(void)
00131 {
00132 geBitmap * Bmp;
00133 
00134         geBitmap_Start();
00135 
00136         Bmp = MemPool_GetHunk(BitmapPool);
00137 
00138         Bmp->RefCount = 1;
00139 
00140         Bmp->DriverGamma = Bmp->DriverGammaLast = 1.0f;
00141 
00142         Debug(_Bitmap_Debug_ActiveRefs ++);
00143         Debug(_Bitmap_Debug_ActiveCount ++);
00144 
00145 return Bmp;
00146 }
00147 
00148 void geBitmap_Destroy_Base(geBitmap *Bmp)
00149 {
00150         assert(Bmp);
00151         assert(Bmp->RefCount == 0);
00152         Debug(_Bitmap_Debug_ActiveCount --);
00153 
00154         MemPool_FreeHunk(BitmapPool,Bmp);
00155 
00156         geBitmap_Stop();
00157 }
00158 
00159 GENESISAPI void GENESISCC       geBitmap_CreateRef(geBitmap *Bmp)
00160 {
00161         assert(Bmp);
00162         Bmp->RefCount ++;
00163         Debug(_Bitmap_Debug_ActiveRefs ++);
00164 }
00165 
00166 GENESISAPI geBitmap *   GENESISCC       geBitmap_Create(
00167         int                                      Width,
00168         int                                      Height,
00169         int                                      MipCount,
00170         gePixelFormat Format)
00171 {
00172 geBitmap * Bmp;
00173 
00174         Bmp = geBitmap_Create_Base();
00175         if ( ! Bmp )
00176                 return NULL;
00177 
00178         assert( Width > 0 );
00179         assert( Height > 0 );
00180         if ( MipCount == 0 )
00181                 MipCount = 1;
00182         assert( MipCount > 0 );
00183 
00184         Bmp->Info.Width = Width;
00185         Bmp->Info.Stride = Width;
00186         Bmp->Info.Height = Height;
00187         Bmp->Info.Format = Format;
00188 
00189         Bmp->Info.MinimumMip = 0;
00190         Bmp->Info.MaximumMip = 0;
00191         Bmp->Info.HasColorKey = GE_FALSE;
00192 
00193         Bmp->SeekMipCount = MipCount;
00194 
00195         if ( Format == GE_PIXELFORMAT_WAVELET )
00196         {
00197                 geErrorLog_AddString(-1,"Genesis3D 1.0 does not support Wavelet Images",NULL);
00198                 return NULL;
00199         }
00200 
00201 return Bmp;
00202 }
00203 
00204 GENESISAPI geBitmap *   GENESISCC       geBitmap_CreateFromInfo(const geBitmap_Info * pInfo)
00205 {
00206 geBitmap * Bmp;
00207 
00208         assert(pInfo);
00209         assert(geBitmap_Info_IsValid(pInfo));
00210 
00211         Bmp = geBitmap_Create_Base();
00212         if ( ! Bmp )
00213                 return NULL;
00214 
00215         Bmp->Info = *pInfo;
00216 
00217         if ( Bmp->Info.Stride < Bmp->Info.Width )
00218                 Bmp->Info.Stride = Bmp->Info.Width;
00219 
00220         if ( Bmp->Info.Palette )
00221                 geBitmap_Palette_CreateRef(Bmp->Info.Palette);
00222 
00223         if ( Bmp->Info.Format == GE_PIXELFORMAT_WAVELET )
00224         {
00225                 geErrorLog_AddString(-1,"Genesis3D 1.0 does not support Wavelet Images",NULL);
00226                 return NULL;
00227         }
00228 
00229 return Bmp;
00230 }
00231 
00232 GENESISAPI geBoolean    GENESISCC        geBitmap_Destroy(geBitmap **Bmp)
00233 {
00234 int                     i;
00235 geBitmap *      Bitmap;
00236 
00237         assert(Bmp);
00238 
00239         Bitmap = *Bmp;
00240 
00241         if ( Bitmap )
00242         {
00243                 if ( Bitmap->LockOwner )
00244                 {
00245                         return geBitmap_UnLock(Bitmap);
00246                 }
00247 
00248                 if ( Bitmap->RefCount <= 1 )
00249                 {
00250                         if ( Bitmap->DataOwner )
00251                         {
00252                                 geBitmap_Destroy(&(Bitmap->DataOwner));
00253                                 Bitmap->DataOwner = NULL;
00254                         }
00255                         else
00256                         {
00257                                 if ( Bitmap->Driver )
00258                                 {
00259                                         geBitmap_DetachDriver(Bitmap,GE_FALSE);
00260                                 }
00261 
00262                                 for     (i = Bitmap->Info.MinimumMip; i <= Bitmap->Info.MaximumMip; i++)
00263                                 {
00264                                         if      (Bitmap->Data[i])
00265                                                 geRam_Free(Bitmap->Data[i]);
00266                                 }
00267                         }
00268                 }
00269 
00270                 Debug(assert(_Bitmap_Debug_ActiveRefs > 0));
00271                 Debug(_Bitmap_Debug_ActiveRefs --);
00272 
00273                 Bitmap->RefCount --;
00274 
00275                 if ( Bitmap->RefCount <= 0 )
00276                 {
00277                         if      (Bitmap->Alpha)
00278                         {
00279                                 geBitmap_Destroy(&Bitmap->Alpha);
00280                         }
00281 
00282                         if      (Bitmap->Info.Palette)
00283                         {
00284                                 geBitmap_Palette_Destroy(&(Bitmap->Info.Palette));
00285                         }
00286 
00287                         if      (Bitmap->DriverInfo.Palette)
00288                         {
00289                                 geBitmap_Palette_Destroy(&(Bitmap->DriverInfo.Palette));
00290                         }
00291 
00292                         geBitmap_Destroy_Base(Bitmap);
00293 
00294                         *Bmp = NULL;
00295 
00296                         return GE_TRUE;
00297                 }
00298         }
00299 
00300 return GE_FALSE;
00301 }
00302 
00303 geBoolean geBitmap_AllocSystemMip(geBitmap *Bmp,int mip)
00304 {
00305         if ( ! Bmp )
00306         {
00307                 return GE_FALSE;
00308         }
00309 
00310         if ( Bmp->LockOwner && mip != 0 ) return GE_FALSE;
00311 
00312         if ( ! Bmp->Data[mip] )
00313         {
00314         int bytes;
00315                 bytes = geBitmap_MipBytes(Bmp,mip);
00316                 if ( bytes == 0 )
00317                 {
00318                         Bmp->Data[mip] = NULL;
00319                         return GE_TRUE;
00320                 }
00321                 Bmp->Data[mip] = geRam_Allocate( bytes );
00322         }
00323 
00324 return (Bmp->Data[mip]) ? GE_TRUE : GE_FALSE;
00325 }
00326 
00327 geBoolean geBitmap_AllocPalette(geBitmap *Bmp,gePixelFormat Format,DRV_Driver * Driver)
00328 {
00329 geBitmap_Info * BmpInfo;
00330         assert(Bmp);
00331 
00332         if ( Driver )
00333                 BmpInfo = &(Bmp->DriverInfo);
00334         else
00335                 BmpInfo = &(Bmp->Info);
00336 
00337         if ( ! gePixelFormat_IsRaw(Format) )
00338                 Format = GE_PIXELFORMAT_32BIT_XRGB;
00339 
00340         if ( ! BmpInfo->Palette )
00341         {
00342                 assert( BmpInfo->Format == GE_PIXELFORMAT_8BIT_PAL );
00343 
00344                 if ( Driver )
00345                 {
00346                 geBoolean BmpHasAlpha;
00347                         
00348                         BmpHasAlpha = GE_FALSE;
00349                         if ( gePixelFormat_HasGoodAlpha(Bmp->Info.Format) )
00350                                 BmpHasAlpha = GE_TRUE;
00351                         else if ( Bmp->Info.Palette && gePixelFormat_HasGoodAlpha(Bmp->Info.Palette->Format) )
00352                                 BmpHasAlpha = GE_TRUE;
00353 
00354                         if ( BmpHasAlpha || (Bmp->Info.HasColorKey && ! Bmp->DriverInfo.HasColorKey ) )
00355                                 Format = GE_PIXELFORMAT_32BIT_ARGB;
00356 
00357                         BmpInfo->Palette = geBitmap_Palette_CreateFromDriver(Driver,Format,256);
00358                 }
00359                 else
00360                 {                       
00361                         BmpInfo->Palette = geBitmap_Palette_Create(Format,256);
00362                 }
00363         }
00364 
00365         if ( ! BmpInfo->Palette )
00366                 return GE_FALSE;
00367 
00368         if ( BmpInfo->HasColorKey )
00369         {
00370                 if ( ! BmpInfo->Palette->HasColorKey )
00371                 {
00372                         BmpInfo->Palette->HasColorKey = GE_TRUE;
00373                         BmpInfo->Palette->ColorKey = 1; // <>
00374                 }
00375                 BmpInfo->Palette->ColorKeyIndex = BmpInfo->ColorKey;
00376         }
00377 
00378         if ( Driver )
00379         {
00380                 assert( Bmp->DriverHandle );
00381                 assert( BmpInfo->Palette->DriverHandle );
00382                 if ( ! Driver->THandle_SetPalette(Bmp->DriverHandle,BmpInfo->Palette->DriverHandle) )
00383                 {
00384                         geErrorLog_AddString(-1,"AllocPal : THandle_SetPalette", NULL);
00385                         return GE_FALSE;
00386                 }
00387         }
00388 
00389         if ( ! Bmp->Info.Palette )
00390         {
00391                 Bmp->Info.Palette = geBitmap_Palette_CreateCopy(BmpInfo->Palette);
00392         }
00393 
00394 return GE_TRUE;
00395 }
00396 
00397 /*}{ *************** Locks *******************/
00398 
00399 GENESISAPI geBoolean    GENESISCC        geBitmap_LockForWrite(
00400         geBitmap *                      Bmp,
00401         geBitmap **                     Target,
00402         int                                     MinimumMip,
00403         int                                     MaximumMip)
00404 {
00405 int mip;
00406 
00407         assert( geBitmap_IsValid(Bmp) );
00408         assert( Target);
00409         assert(MaximumMip >= MinimumMip);
00410         assert( &Bmp != Target );
00411 
00412         if ( Bmp->LockCount || Bmp->LockOwner )
00413         {
00414                 geErrorLog_AddString(-1,"LockForWrite : already locked", NULL);
00415                 return GE_FALSE;
00416         }
00417 
00418         if ( Bmp->DriverHandle )
00419         {
00420                 if ( (MinimumMip < Bmp->DriverInfo.MinimumMip) ||
00421                          (MaximumMip > Bmp->DriverInfo.MaximumMip) )
00422                 {
00423                         geErrorLog_AddString(-1,"LockForWrite : Driver : invalid mip", NULL);
00424                         return GE_FALSE;
00425                 }
00426         }
00427         else
00428         {
00429                 if ( (MinimumMip < Bmp->Info.MinimumMip) ||
00430                          (MaximumMip >= MAXMIPLEVELS) )
00431                 {
00432                         geErrorLog_AddString(-1,"LockForWrite : System : invalid mip", NULL);
00433                         return GE_FALSE;
00434                 }
00435 
00436                 if ( MaximumMip > Bmp->Info.MaximumMip )
00437                 {
00438                         if ( ! geBitmap_MakeSystemMips(Bmp,Bmp->Info.MaximumMip,MaximumMip) )
00439                                 return GE_FALSE;
00440                         Bmp->Info.MaximumMip = MaximumMip;
00441                 }
00442         }
00443         
00444         for(mip=MinimumMip;mip <= MaximumMip;mip ++)
00445         {
00446                 if ( Bmp->DriverHandle )
00447                 {
00448                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipOnDriver(Bmp,mip,-1);
00449                 }
00450                 else
00451                 {
00452                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipSystem(Bmp,mip,-1);
00453                 }
00454                 if ( ! Target[ mip - MinimumMip ] )
00455                 {
00456                         geErrorLog_AddString(-1,"LockForWrite : CreateLockFromMip failed", NULL);
00457                         mip--;
00458                         while(mip >= MinimumMip )
00459                         {
00460                                 geBitmap_Destroy( & Target[ mip - MinimumMip ] );
00461                                 mip--;
00462                         }
00463                         return GE_FALSE;
00464                 }
00465         }
00466 
00467         assert( Bmp->LockCount == - (MaximumMip - MinimumMip + 1) );
00468 
00469 return GE_TRUE;
00470 }
00471 
00472 GENESISAPI geBoolean    GENESISCC geBitmap_LockForWriteFormat(
00473         geBitmap *                      Bmp,
00474         geBitmap **                     Target,
00475         int                                     MinimumMip,
00476         int                                     MaximumMip,
00477         gePixelFormat           Format)
00478 {
00479 int mip;
00480 
00481         assert( geBitmap_IsValid(Bmp) );
00482         assert( Target);
00483         assert(MaximumMip >= MinimumMip);
00484         assert( &Bmp != Target );
00485         
00486         if ( Bmp->LockCount || Bmp->LockOwner )
00487         {
00488                 geErrorLog_AddString(-1,"LockForWrite : already locked", NULL);
00489                 return GE_FALSE;
00490         }
00491 
00492         if ( Format != Bmp->Info.Format && Format != Bmp->DriverInfo.Format )
00493         {
00494                 geErrorLog_AddString(-1,"LockForWriteFormat : must be System or Driver Format !", NULL);
00495                 return GE_FALSE;
00496         }
00497 
00498         if ( Format == Bmp->DriverInfo.Format )
00499         {
00500                 if ( MinimumMip < Bmp->DriverInfo.MinimumMip || MaximumMip > Bmp->DriverInfo.MaximumMip )
00501                 {
00502                         geErrorLog_AddString(-1,"LockForWrite : invalid Driver mip", NULL);
00503                         return GE_FALSE;
00504                 }
00505         }
00506         else
00507         {
00508                 assert( Format == Bmp->Info.Format );
00509 
00510                 if ( Bmp->DriverHandle )
00511                 {
00512                         if ( ! geBitmap_Update_DriverToSystem(Bmp) )
00513                         {
00514                                 geErrorLog_AddString(-1,"LockForWrite : Update_DriverToSystem", NULL);
00515                                 return GE_FALSE;
00516                         }
00517                 }
00518 
00519                 // create mips?
00520 
00521                 if ( MinimumMip < Bmp->Info.MinimumMip || MaximumMip >= MAXMIPLEVELS )
00522                 {
00523                         geErrorLog_AddString(-1,"LockForWrite : invalid System mip", NULL);
00524                         return GE_FALSE;
00525                 }
00526                 
00527                 if ( ! geBitmap_MakeSystemMips(Bmp,Bmp->Info.MaximumMip,MaximumMip) )
00528                         return GE_FALSE;
00529                 Bmp->Info.MaximumMip = MaximumMip;
00530         }
00531 
00532         for(mip=MinimumMip;mip <= MaximumMip;mip ++)
00533         {
00534                 if ( Bmp->DriverHandle && Format == Bmp->DriverInfo.Format )
00535                 {
00536                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipOnDriver(Bmp,mip,-1);
00537                 }
00538                 else
00539                 {
00540                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipSystem(Bmp,mip,-1);
00541                 }
00542 
00543                 if ( ! Target[ mip - MinimumMip ] )
00544                 {
00545                         geErrorLog_AddString(-1,"LockForWrite : CreateLockFromMip failed", NULL);
00546                         mip--;
00547                         while(mip >= MinimumMip )
00548                         {
00549                                 geBitmap_Destroy( & Target[ mip - MinimumMip ] );
00550                                 mip--;
00551                         }
00552                         return GE_FALSE;
00553                 }
00554         }
00555 
00556         assert( Bmp->LockCount == - (MaximumMip - MinimumMip + 1) );
00557 
00558 return GE_TRUE;
00559 }
00560 
00561 GENESISAPI geBoolean GENESISCC geBitmap_LockForReadNative(
00562         const geBitmap *        iBmp,
00563         geBitmap **                     Target,
00564         int                                     MinimumMip,
00565         int                                     MaximumMip)
00566 {
00567 int mip;
00568 geBitmap * Bmp = (geBitmap *)iBmp;
00569 
00570         assert( geBitmap_IsValid(Bmp) );
00571         assert( Target);
00572         assert(MaximumMip >= MinimumMip);
00573         assert( &Bmp != Target );
00574 
00575         if ( (MinimumMip < Bmp->Info.MinimumMip && MinimumMip < Bmp->DriverInfo.MinimumMip) ||
00576                  (MaximumMip >= MAXMIPLEVELS) )
00577         {
00578                 geErrorLog_AddString(-1,"LockForRead : invalid mip", NULL);
00579                 return GE_FALSE;
00580         }
00581 
00582         if ( Bmp->LockCount < 0 || Bmp->LockOwner )
00583         {
00584                 geErrorLog_AddString(-1,"LockForRead : already locked", NULL);
00585                 return GE_FALSE;
00586         }
00587 
00588         for(mip=MinimumMip;mip <= MaximumMip;mip ++)
00589         {
00590                 // err on the side of *not* choosing the driver data to read from !
00591                 if ( Bmp->DriverHandle && Bmp->DriverDataChanged
00592                         && mip <= Bmp->DriverInfo.MaximumMip && mip >= Bmp->DriverInfo.MinimumMip)
00593                 {
00594                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipOnDriver(Bmp,mip,1);
00595                 }
00596                 else
00597                 {
00598                         Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMipSystem(Bmp,mip,1);
00599                 }
00600                 if ( ! Target[ mip - MinimumMip ] )
00601                 {
00602                         geErrorLog_AddString(-1,"LockForRead : CreateLockFromMip failed", NULL);
00603                         mip--;
00604                         while(mip >= MinimumMip )
00605                         {
00606                                 geBitmap_Destroy( & Target[ mip - MinimumMip ] );
00607                                 mip--;
00608                         }
00609                         return GE_FALSE;
00610                 }
00611         }
00612 
00613 return GE_TRUE;
00614 }
00615 
00616 GENESISAPI geBoolean    GENESISCC geBitmap_LockForRead(
00617         const geBitmap *        iBmp,
00618         geBitmap **                     Target,
00619         int                                     MinimumMip,
00620         int                                     MaximumMip,
00621         gePixelFormat           Format,
00622         geBoolean                       HasColorKey,
00623         uint32                          ColorKey)
00624 {
00625 int mip;
00626 geBitmap * Bmp = (geBitmap *)iBmp;
00627 
00628         assert( geBitmap_IsValid(Bmp) );
00629         assert( Target);
00630         assert(MaximumMip >= MinimumMip);
00631         assert( &Bmp != Target );
00632 
00633         if ( MinimumMip < Bmp->Info.MinimumMip ||
00634 //               MaximumMip > Bmp->Info.MaximumMip
00635                 MaximumMip >= MAXMIPLEVELS )
00636         {
00637                 geErrorLog_AddString(-1,"LockForRead : invalid mip", NULL);
00638                 return GE_FALSE;
00639         }
00640 
00641         if ( Bmp->LockCount < 0 || Bmp->LockOwner )
00642         {
00643                 geErrorLog_AddString(-1,"LockForRead : already locked", NULL);
00644                 return GE_FALSE;
00645         }
00646         
00647         for(mip=MinimumMip;mip <= MaximumMip;mip ++)
00648         {
00649                 Target[ mip - MinimumMip ] = geBitmap_CreateLockFromMip(Bmp,mip, Format,HasColorKey,ColorKey,1);
00650                 if ( ! Target[ mip - MinimumMip ] )
00651                 {
00652                         geErrorLog_AddString(-1,"LockForRead : CreateLockFromMip failed", NULL);
00653                         mip--;
00654                         while(mip >= MinimumMip )
00655                         {
00656                                 geBitmap_Destroy( & Target[ mip - MinimumMip ] );
00657                                 mip--;
00658                         }
00659                         return GE_FALSE;
00660                 }
00661         }
00662 
00663 return GE_TRUE;
00664 }
00665 
00666 geBoolean geBitmap_UnLockArray_NoChange(geBitmap **Locks,int Size)
00667 {
00668 int i;
00669 geBoolean Ret = GE_TRUE;
00670         assert(Locks);
00671         for(i=0;i<Size;i++)
00672         {
00673                 if ( ! geBitmap_UnLock_NoChange(Locks[i]) )
00674                         Ret = GE_FALSE;
00675         }
00676 return Ret;
00677 }
00678 
00679 GENESISAPI geBoolean    GENESISCC geBitmap_UnLockArray(geBitmap **Locks,int Size)
00680 {
00681 int i;
00682 geBoolean Ret = GE_TRUE;
00683         assert(Locks);
00684         for(i=0;i<Size;i++)
00685         {
00686                 if ( ! geBitmap_UnLock(Locks[i]) )
00687                         Ret = GE_FALSE;
00688         }
00689 return Ret;
00690 }
00691 
00692 geBoolean geBitmap_UnLock_Internal(geBitmap *Bmp,geBoolean Apply)
00693 {
00694 geBoolean Ret = GE_TRUE;
00695 
00696         if ( ! Bmp )
00697         {
00698                 geErrorLog_AddString(-1,"UnLock : bad bmp", NULL);
00699                 return GE_FALSE;
00700         }
00701 
00702         assert( Bmp->LockCount == 0 );
00703 
00704         if ( Bmp->LockOwner )
00705         {
00706         int DoUpdate = 0;
00707 
00708                 assert(Bmp->LockOwner->LockCount != 0);
00709                 if ( Bmp->LockOwner->LockCount > 0 )
00710                 {
00711                         Bmp->LockOwner->LockCount --;
00712                 }
00713                 else if ( Bmp->LockOwner->LockCount < 0 )
00714                 {
00715                         Bmp->LockOwner->LockCount ++;
00716 
00717                         if ( Apply )
00718                         {
00719                         geBitmap_Palette * Pal;
00720 
00721                                 Bmp->LockOwner->Modified[Bmp->Info.MinimumMip] = GE_TRUE;
00722                         
00723                                 Pal = Bmp->DriverInfo.Palette ? Bmp->DriverInfo.Palette : Bmp->Info.Palette;
00724                                 if ( Pal )
00725                                         geBitmap_SetPalette(Bmp->LockOwner,Pal);
00726 
00727                                 // this palette will be destroyed later on
00728                         }
00729 
00730                         if ( Bmp->LockOwner->LockCount == 0 && Apply )
00731                         {
00732                                 // last unlock for write
00733                                 // if Bmp is on hardware, flag the Data[] as needing update
00734                                 if ( Bmp->DriverBitsLocked )
00735                                 {
00736                                         assert( Bmp->DriverHandle );
00737                                         Bmp->LockOwner->DriverDataChanged = GE_TRUE;
00738                                         DoUpdate = 1;
00739                                 }
00740                                 else
00741                                 {
00742                                         DoUpdate = -1;
00743                                 }
00744                         }
00745                 }
00746                 
00747                 if ( Bmp->DriverHandle && Bmp->DriverBitsLocked )
00748                 {
00749                         assert(Bmp->Driver);
00750                         if ( ! Bmp->Driver->THandle_UnLock(Bmp->DriverHandle, Bmp->DriverMipLock) )
00751                         {
00752                                 geErrorLog_AddString(-1,"UnLock : thandle_unlock", NULL);
00753                                 Ret = GE_FALSE;
00754                         }
00755                         Bmp->DriverBitsLocked = GE_FALSE;
00756                         Bmp->DriverMipLock = 0;
00757                 }
00758 
00759                 if ( Bmp->Alpha )
00760                 {
00761                         if ( ! geBitmap_UnLock(Bmp->Alpha) )
00762                                 Ret = GE_FALSE;
00763 
00764                         Bmp->Alpha = NULL;
00765                 }
00766 
00767                 if ( DoUpdate )
00768                 {
00769                         assert(Bmp->LockOwner->LockCount == 0 );
00770                         // we just finished unlocking a lock-for-write
00771                         if ( DoUpdate > 0 )
00772                         {
00773                         //      don't update from driver -> system, leaved the changed data on the driver
00774                         //      we've got DriverDataChanged
00775                         //      if ( ! geBitmap_Update_DriverToSystem(Bmp) )
00776                         //              Ret = GE_FALSE;
00777                         }
00778                         else
00779                         {
00780                                 if ( Bmp->LockOwner->DriverHandle )
00781                                         if ( ! geBitmap_Update_SystemToDriver(Bmp->LockOwner) )
00782                                                 Ret = GE_FALSE;
00783                         }
00784                 }
00785 
00786                 // we did a CreateRef on the lockowner
00787                 geBitmap_Destroy(&(Bmp->LockOwner));
00788                 Bmp->LockOwner = NULL;
00789 
00790         }
00791         // else fail ?
00792 
00793         assert(Bmp->RefCount == 1);
00794 
00795         geBitmap_Destroy(&Bmp);
00796 
00797         assert(Bmp == NULL);
00798 
00799 return Ret;
00800 }
00801 
00802 GENESISAPI geBoolean    GENESISCC geBitmap_UnLock(geBitmap *Bmp)
00803 {
00804 return geBitmap_UnLock_Internal(Bmp,GE_TRUE);
00805 }
00806 
00807 geBoolean geBitmap_UnLock_NoChange(geBitmap *Bmp)
00808 {
00809 return geBitmap_UnLock_Internal(Bmp,GE_FALSE);
00810 }
00811 
00812 GENESISAPI void *       GENESISCC geBitmap_GetBits(geBitmap *Bmp)
00813 {
00814 void * bits;
00815 
00816         assert( geBitmap_IsValid(Bmp) );
00817 
00818         if ( ! Bmp )
00819         {
00820                 geErrorLog_AddString(-1,"GetBits : bad bmp", NULL);
00821                 return NULL;
00822         }
00823 
00824         if ( ! Bmp->LockOwner ) // must be a lock!
00825         {
00826                 geErrorLog_AddString(-1,"GetBits : not a lock", NULL);
00827                 return NULL;
00828         }
00829 
00830         if ( Bmp->DriverHandle )
00831         {
00832                 assert(Bmp->Driver);
00833                 if ( ! Bmp->Driver->THandle_Lock(Bmp->DriverHandle,Bmp->DriverMipLock,&bits) )
00834                 {
00835                         geErrorLog_AddString(-1,"GetBits : THandle_Lock", NULL);
00836                         return NULL;
00837                 }
00838 
00839                 Bmp->DriverBitsLocked = GE_TRUE;
00840         }
00841         else
00842         {
00843                 bits = Bmp->Data[0];
00844         }
00845 
00846 return bits;
00847 }
00848 
00849 /*}{ ************* _CreateLock_#? *********************/
00850 
00851 geBitmap * geBitmap_CreateLock_CopyInfo(geBitmap *BmpSrc,int LockCnt,int mip)
00852 {
00853 geBitmap * Bmp;
00854 
00855         assert( geBitmap_IsValid(BmpSrc) );
00856 
00857         // all _CreateLocks go through here
00858 
00859         Bmp = geBitmap_Create_Base();
00860         if ( ! Bmp )
00861                 return NULL;
00862 
00863         geBitmap_MakeMipInfo(&(BmpSrc->Info),mip,&(Bmp->Info));
00864         geBitmap_MakeMipInfo(&(BmpSrc->DriverInfo),mip,&(Bmp->DriverInfo));
00865         Bmp->DriverFlags = BmpSrc->DriverFlags;
00866         Bmp->DriverGamma = BmpSrc->DriverGamma;
00867         Bmp->DriverGammaLast = BmpSrc->DriverGammaLast;
00868                 
00869         Bmp->Info.Palette = NULL;
00870         Bmp->DriverInfo.Palette = NULL;
00871 
00872         Bmp->Driver     = BmpSrc->Driver;
00873         Bmp->PreferredFormat= BmpSrc->PreferredFormat;
00874 
00875         Bmp->LockOwner = BmpSrc;
00876         geBitmap_CreateRef(BmpSrc); // we do a _Destroy() in UnLock()
00877 
00878         BmpSrc->LockCount += LockCnt;
00879 
00880 return Bmp;
00881 }
00882 
00883 void geBitmap_MakeMipInfo(geBitmap_Info *Src,int mip,geBitmap_Info * Target)
00884 {
00885         assert( Src && Target );
00886         assert( mip >= 0 && mip < MAXMIPLEVELS );
00887         *Target = *Src;
00888 
00889         Target->Width  = SHIFT_R_ROUNDUP(Target->Width,mip);
00890         Target->Height = SHIFT_R_ROUNDUP(Target->Height,mip);
00891         Target->Stride = SHIFT_R_ROUNDUP(Target->Stride,mip);
00892         Target->MinimumMip = Target->MaximumMip = mip;
00893 }
00894 
00895 geBitmap * geBitmap_CreateLockFromMip(geBitmap *Src,int mip,
00896         gePixelFormat Format,
00897         geBoolean       HasColorKey,
00898         uint32          ColorKey,
00899         int                     LockCnt)
00900 {
00901 geBitmap * Ret;
00902 
00903         assert( geBitmap_IsValid(Src) );
00904         if ( mip < 0 || mip >= MAXMIPLEVELS )
00905                 return NULL;
00906 
00907         // LockForRead always goes through here
00908 
00909         if ( gePixelFormat_BytesPerPel(Format) < 1 )
00910                 return NULL;
00911 
00912         if ( Src->DriverInfo.Format == Format &&
00913                  GE_BOOLSAME(Src->DriverInfo.HasColorKey,HasColorKey) &&
00914                  (!HasColorKey || Src->DriverInfo.ColorKey == ColorKey) &&
00915                  mip >= Src->DriverInfo.MinimumMip && mip <= Src->DriverInfo.MaximumMip )
00916         {
00917                 return geBitmap_CreateLockFromMipOnDriver(Src,mip,LockCnt);
00918         }
00919 
00920         if ( Src->DriverHandle )
00921         {
00922                 if ( ! geBitmap_Update_DriverToSystem(Src) )
00923                 {
00924                         return NULL;
00925                 }
00926         }
00927                 
00928         if ( ! Src->Data[mip] )
00929         {
00930                 if ( ! geBitmap_MakeSystemMips(Src,mip,mip) )
00931                         return NULL;
00932         }
00933 
00934         if ( Src->Info.Format == Format &&
00935                  GE_BOOLSAME(Src->Info.HasColorKey,HasColorKey) &&
00936                  (!HasColorKey || Src->Info.ColorKey == ColorKey) )
00937         {
00938                 return geBitmap_CreateLockFromMipSystem(Src,mip,LockCnt);
00939         }
00940 
00941         Ret = geBitmap_CreateLock_CopyInfo(Src,LockCnt,mip);
00942 
00943         if ( ! Ret )
00944                 return NULL;
00945 
00946         Ret->Info.Stride = Ret->Info.Width;     // {} ?
00947 
00948         Ret->Info.Format = Format;
00949         Ret->Info.ColorKey = ColorKey;
00950         Ret->Info.HasColorKey = HasColorKey;
00951 
00952         if ( gePixelFormat_HasPalette(Format) && Src->Info.Palette )
00953         {
00954                 Ret->Info.Palette = Src->Info.Palette;
00955                 geBitmap_Palette_CreateRef(Ret->Info.Palette);
00956         }
00957 
00958         assert( Ret->Alpha == NULL );
00959         if ( ! gePixelFormat_HasGoodAlpha(Format) && Src->Alpha )
00960         {
00961                 if ( ! geBitmap_LockForRead(Src->Alpha,&(Ret->Alpha),mip,mip,GE_PIXELFORMAT_8BIT_GRAY,0,0) )
00962                 {
00963                         geErrorLog_AddString(-1,"CreateLockFromMip : LockForRead failed", NULL);
00964                         geBitmap_Destroy(&Ret);
00965                         return NULL;
00966                 }
00967                 assert( Ret->Alpha );
00968         }
00969 
00970         assert( geBitmap_IsValid(Ret) );
00971 
00972         if ( ! geBitmap_AllocSystemMip(Ret,0) )
00973         {
00974                 geBitmap_Destroy(&Ret);
00975                 return NULL;
00976         }
00977 
00978         if ( ! geBitmap_BlitMip( Src, mip, Ret, 0 ) )
00979         {
00980                 geErrorLog_AddString(-1,"CreateLockFromMip : BlitMip failed", NULL);
00981                 geBitmap_Destroy(&Ret);
00982                 return NULL;
00983         }
00984 
00985 return Ret;
00986 }
00987 
00988 geBitmap * geBitmap_CreateLockFromMipSystem(geBitmap *Src,int mip,int LockCnt)
00989 {
00990 geBitmap * Ret;
00991 
00992         assert( geBitmap_IsValid(Src) );
00993         if ( mip < Src->Info.MinimumMip || mip >= MAXMIPLEVELS )
00994                 return NULL;
00995 
00996         if ( gePixelFormat_BytesPerPel(Src->Info.Format) < 1 )
00997                 return NULL;
00998 
00999         if ( ! Src->Data[mip] )
01000         {
01001                 if ( ! geBitmap_MakeSystemMips(Src,mip,mip) )
01002                         return NULL;
01003         }
01004 
01005         Ret = geBitmap_CreateLock_CopyInfo(Src,LockCnt,mip);
01006 
01007         if ( ! Ret ) return NULL;
01008 
01009         Ret->Data[0] = Src->Data[mip];
01010 
01011         Ret->Info.Palette = Src->Info.Palette;
01012         if ( Ret->Info.Palette )
01013                 geBitmap_Palette_CreateRef(Ret->Info.Palette);
01014 
01015         Ret->DataOwner = Src;
01016         geBitmap_CreateRef(Src);
01017 
01018         assert( Ret->Alpha == NULL );
01019         if ( ! gePixelFormat_HasGoodAlpha(Src->Info.Format) && Src->Alpha )
01020         {
01021                 if ( ! geBitmap_LockForRead(Src->Alpha,&(Ret->Alpha),mip,mip,GE_PIXELFORMAT_8BIT_GRAY,0,0) )
01022                 {
01023                         geErrorLog_AddString(-1,"CreateLockFromMipSystem : LockForRead failed", NULL);
01024                         geBitmap_Destroy(&Ret);
01025                         return NULL;
01026                 }
01027                 assert( Ret->Alpha );
01028         }
01029 
01030         assert( geBitmap_IsValid(Ret) );
01031 
01032 return Ret;
01033 }
01034 
01035 geBitmap * geBitmap_CreateLockFromMipOnDriver(geBitmap *Src,int mip,int LockCnt)
01036 {
01037 geBitmap * Ret;
01038 
01039         assert( geBitmap_IsValid(Src) );
01040         if ( ! Src->DriverHandle || ! Src->Driver || Src->DriverMipLock || mip < Src->DriverInfo.MinimumMip || mip > Src->DriverInfo.MaximumMip )
01041                 return NULL;
01042 
01043         // the driver can never have Wavelet data
01044         // {} it could have S3TC data, though..
01045         assert( gePixelFormat_BytesPerPel(Src->DriverInfo.Format) > 0);
01046 
01047         Ret = geBitmap_CreateLock_CopyInfo(Src,LockCnt,mip);
01048 
01049         if ( ! Ret ) return NULL;
01050 
01051         Ret->DriverMipLock = mip;
01052         Ret->DriverHandle = Src->DriverHandle;
01053 
01054         Ret->DataOwner = Src;
01055         geBitmap_CreateRef(Src);
01056 
01057         Ret->DriverInfo.Palette = Src->DriverInfo.Palette;
01058 
01059         if ( ! geBitmap_MakeDriverLockInfo(Ret,mip,&(Ret->DriverInfo)) )
01060         {
01061                 geErrorLog_AddString(-1,"CreateLockFromMipOnDriver : UpdateInfo failed", NULL);
01062                 geBitmap_Destroy(&Ret);
01063                 return NULL;
01064         }
01065 
01066         assert(Ret->DriverInfo.Palette == Src->DriverInfo.Palette);
01067 
01068         Ret->Info = Ret->DriverInfo;    //{} shouldn't be necessary
01069         
01070         if ( Ret->DriverInfo.Palette )
01071                 geBitmap_Palette_CreateRef(Ret->DriverInfo.Palette);
01072         if ( Ret->Info.Palette )
01073                 geBitmap_Palette_CreateRef(Ret->Info.Palette);
01074 
01075         assert( geBitmap_IsValid(Ret) );
01076 
01077 return Ret;
01078 }
01079 
01080 /*}{ ************* Driver Attachment *********************/
01081 
01082 #define MAX_DRIVER_FORMATS (100)
01083 
01084 static geBoolean EnumPFCB(geRDriver_PixelFormat *pFormat,void *Context)
01085 {
01086 geRDriver_PixelFormat **pDriverFormatsPtr;
01087         pDriverFormatsPtr = Context;
01088         **pDriverFormatsPtr = *pFormat;
01089         (*pDriverFormatsPtr) += 1;
01090 return GE_TRUE;
01091 }
01092 
01093 static int NumBitsOn(uint32 val)
01094 {
01095 uint32 count = 0;
01096         while(val)
01097         {
01098                 count += val&1;
01099                 val >>= 1;
01100         }
01101 return count;
01102 }
01103 
01104 static geBoolean IsInArray(uint32 Val,uint32 *Array,int Len)
01105 {
01106         while(Len--)
01107         {
01108                 if ( Val == *Array )
01109                         return GE_TRUE;
01110                 Array--;
01111         }
01112 return GE_FALSE;
01113 }
01114 
01115 geBoolean geBitmap_ChooseDriverFormat(
01116         gePixelFormat   SeekFormat1,
01117         gePixelFormat   SeekFormat2,
01118         geBoolean               SeekCK,
01119         geBoolean               SeekAlpha,
01120         geBoolean               SeekSeparates,
01121         uint32                  SeekFlags,
01122         geRDriver_PixelFormat *DriverFormatsArray,int ArrayLen,
01123         geRDriver_PixelFormat *pTarget)
01124 {
01125 int i,rating;
01126 int FormatRating[MAX_DRIVER_FORMATS];
01127 geRDriver_PixelFormat * DriverPalFormat;
01128 geRDriver_PixelFormat * pf;
01129 geBoolean FoundAlpha;
01130 uint32 SeekMajor,SeekMinor;
01131 const gePixelFormat_Operations *seekops,*pfops;
01132 
01133         assert(pTarget && DriverFormatsArray && ArrayLen > 0);
01134 
01135         if ( SeekAlpha )
01136                 SeekCK = GE_FALSE;      // you can't have both
01137 
01138         if ( SeekFlags & RDRIVER_PF_ALPHA )
01139                 SeekFlags = RDRIVER_PF_ALPHA;
01140         else if ( SeekFlags & RDRIVER_PF_PALETTE )
01141                 SeekFlags = RDRIVER_PF_PALETTE;
01142 
01143         SeekMajor = SeekFlags & RDRIVER_PF_MAJOR_MASK;
01144         SeekMinor = SeekFlags - SeekMajor;
01145 
01146         pf = DriverFormatsArray;
01147         DriverPalFormat = NULL;
01148         for(i=0;i<ArrayLen;i++)
01149         {
01150                 if ( pf->Flags & RDRIVER_PF_PALETTE )
01151                 {
01152                         if ( ! DriverPalFormat || gePixelFormat_HasGoodAlpha(pf->PixelFormat) )
01153                                 DriverPalFormat = pf;
01154                 }
01155                 pf++;
01156         }
01157 
01158         seekops = gePixelFormat_GetOperations(SeekFormat1);
01159 
01160         for(i=0;i<ArrayLen;i++)
01161         {
01162                 pf = DriverFormatsArray + i;
01163                 rating = 0;
01164 
01165                 /***
01166                 {}
01167 
01168                 this is the code to try to pick the closest format the driver has to offer
01169                 the choosing precedence is :
01170 
01171                         1. if want alpha, get alpha
01172                         2. match the _3D_ type flags exactly (PF_MAJOR)
01173                         3. match PreferredFormat
01174                         4. match the bitmap's system format
01175                         5. match up the pixel formats masks
01176 
01177                 we use fuzzy logic : we apply rating to all the matches and then choose
01178                 the one with the best rating.
01179 
01180                 possible todos :
01181                         1. be aware of memory use and format-conversion times, and penalize
01182                                 or favor formats accordingly
01183 
01184                 note : we currently try to use 1555 for colorkey.
01185 
01186                 ***/
01187 
01188                 if ( (pf->Flags & RDRIVER_PF_MAJOR_MASK) == SeekMajor )
01189                 {
01190                         rating += 1<<23;
01191                 }
01192                 else if ( (pf->Flags & SeekMajor) != SeekMajor )
01193                 {
01194                     FormatRating[i] = 0;
01195                         continue;
01196                 }
01197                 else
01198                 {
01199                         // advantage to as few different major flags as possible
01200                         // higher priority than similarity of pixelformats
01201                         rating += (32 - NumBitsOn( (pf->Flags ^ SeekFlags) & RDRIVER_PF_MAJOR_MASK ))<<6;
01202                 }
01203 
01204                 pfops = gePixelFormat_GetOperations(pf->PixelFormat);
01205 
01206                 if ( pf->PixelFormat == SeekFormat1 )
01207                 {
01208                         rating += 1<<16;
01209                 }
01210                 else if ( pf->PixelFormat == SeekFormat2 )
01211                 {
01212                         rating += 1<<15;
01213                 }
01214                 else if ( gePixelFormat_IsRaw(SeekFormat1) && gePixelFormat_IsRaw(pf->PixelFormat) )
01215                 {
01216                 int R,G,B,A;
01217                         // measure similarity
01218                         R = (seekops->RMask >> seekops->RShift) ^ (pfops->RMask >> pfops->RShift);
01219                         G = (seekops->GMask >> seekops->GShift) ^ (pfops->GMask >> pfops->GShift);
01220                         B = (seekops->BMask >> seekops->BShift) ^ (pfops->BMask >> pfops->BShift);
01221                         A = (seekops->AMask >> seekops->AShift) ^ (pfops->AMask >> pfops->AShift);
01222                         R = 8 - NumBitsOn(R);
01223                         G = 8 - NumBitsOn(G);
01224                         B = 8 - NumBitsOn(B);
01225                         A = 4*(8 - NumBitsOn(A)); // right number of A bits is molto importante
01226                         rating += (R + G + B + A);
01227                 }
01228                 else
01229                 {
01230                         // one of the formats is not raw
01231                         // palettized ? compressed ?
01232                         rating += 16;
01233                 }
01234 
01235                 FoundAlpha = GE_FALSE;
01236 
01237                 if ( NumBitsOn(pfops->AMask) > 2 )
01238                         FoundAlpha = GE_TRUE;
01239 
01240                 if ( gePixelFormat_HasPalette(pf->PixelFormat) )
01241                 {
01242             // if Pixelformat is 8BIT_PAL , look at the palette's format to see if it
01243                         //              had alpha!
01244                         assert(DriverPalFormat);
01245                         if ( gePixelFormat_HasGoodAlpha(DriverPalFormat->PixelFormat) )
01246                                 FoundAlpha = GE_TRUE;
01247                 }
01248 
01249                 if ( SeekAlpha && FoundAlpha )
01250                         rating += 1<<24; // HIGHEST ! (except separates)
01251                 else if ( (!SeekAlpha) && (!FoundAlpha) )
01252                         rating += 1<<10; // LOWEST
01253                 else if ( SeekAlpha )
01254                 {
01255                         if ( NumBitsOn(pfops->AMask) || pf->Flags & RDRIVER_PF_CAN_DO_COLORKEY )
01256                         {
01257                                 // sought Alpha, found CK
01258                                 rating += 1<<19;
01259                         }
01260                 }
01261 
01262                 if ( (pf->Flags & RDRIVER_PF_HAS_ALPHA) && SeekSeparates )
01263                 {
01264                         // separates doesn't count as alpha unless we asked for it !
01265                         rating += 1<<25; // VERY HIGHEST !
01266                 }
01267         
01268                 if ( SeekCK ) 
01269                 {
01270                         if ( pf->PixelFormat == GE_PIXELFORMAT_16BIT_1555_ARGB )
01271                         {
01272                                 rating += 1<<23; // just lower than alpha
01273                         }
01274                         else if ( FoundAlpha ) //better than nothing!
01275                         {
01276                                 rating += 1<<18;        // higher than !FoundAlpha
01277                         }
01278                 }
01279 
01280                 if ( GE_BOOLSAME((pf->Flags & RDRIVER_PF_CAN_DO_COLORKEY),SeekCK) )
01281                 {
01282                         rating += 1<<17;
01283                 }
01284 
01285                 FormatRating[i] = rating;
01286         }
01287 
01288         rating = 0;
01289 
01290         for(i=0;i<ArrayLen;i++)
01291         {
01292                 if ( FormatRating[i] > rating )
01293                 {
01294                         rating = FormatRating[i];
01295                         *pTarget = DriverFormatsArray[i];
01296                 }
01297         }
01298 
01299         if ( rating == 0)
01300         {
01301                 geErrorLog_AddString(-1,"ChooseDriverFormat : no valid formats found!", NULL);
01302                 return GE_FALSE;
01303         }
01304 
01305         return GE_TRUE;
01306 }
01307 #if 0
01308 geBoolean geBitmap_ChooseDriverFormat(
01309         gePixelFormat   SeekFormat1,
01310         gePixelFormat   SeekFormat2,
01311         geBoolean               SeekCK,
01312         geBoolean               SeekAlpha,
01313         geBoolean               SeekSeparates,
01314         uint32                  SeekFlags,
01315         geRDriver_PixelFormat *DriverFormatsArray,int ArrayLen,
01316         geRDriver_PixelFormat *pTarget)
01317 {
01318 int i,rating;
01319 int FormatRating[MAX_DRIVER_FORMATS];
01320 geRDriver_PixelFormat * DriverPalFormat;
01321 geRDriver_PixelFormat * pf;
01322 geBoolean FoundAlpha;
01323 uint32 SeekMajor,SeekMinor;
01324 const gePixelFormat_Operations *seekops,*pfops;
01325 
01326         assert(pTarget && DriverFormatsArray && ArrayLen > 0);
01327 
01328 #if 0 // @@
01329         if ( SeekAlpha )
01330                 SeekCK = GE_FALSE;      // you can't have both, you bastard!
01331 #endif
01332 
01333         if ( SeekFlags & RDRIVER_PF_ALPHA )
01334                 SeekFlags = RDRIVER_PF_ALPHA;
01335         else if ( SeekFlags & RDRIVER_PF_PALETTE )
01336                 SeekFlags = RDRIVER_PF_PALETTE;
01337 
01338         if ( ! SeekFormat1 )
01339                 SeekFormat1 = SeekFormat2;
01340 
01341         SeekMajor = SeekFlags & RDRIVER_PF_MAJOR_MASK;
01342         SeekMinor = SeekFlags - SeekMajor;
01343 
01344         pf = DriverFormatsArray;
01345         DriverPalFormat = NULL;
01346         for(i=0;i<ArrayLen;i++)
01347         {
01348                 if ( pf->Flags & RDRIVER_PF_PALETTE )
01349                 {
01350                         assert( gePixelFormat_IsRaw(pf->PixelFormat) );
01351                         if ( ! DriverPalFormat || gePixelFormat_HasGoodAlpha(pf->PixelFormat) )
01352                                 DriverPalFormat = pf;
01353                 }
01354                 pf++;
01355         }
01356 
01357         seekops = gePixelFormat_GetOperations(SeekFormat1);
01358 
01359         for(i=0;i<ArrayLen;i++)
01360         {
01361                 pf = DriverFormatsArray + i;
01362                 rating = 0;
01363 
01364                 /***
01365                 {}
01366 
01367                 this is the code to try to pick the closest format the driver has to offer
01368                 the choosing precedence is :
01369 
01370                         1. if want alpha, get alpha
01371                         2. match the _3D_ type flags exactly
01372                         3. match PreferredFormat
01373                         4. match the bitmap's system format
01374                         5. match up the formats masks
01375 
01376                 ***/
01377 
01378                 if ( (pf->Flags & RDRIVER_PF_MAJOR_MASK) == SeekMajor )
01379                 {
01380                         rating += 1<<23;
01381                 }
01382                 else if ( (pf->Flags & SeekMajor) != SeekMajor )
01383                 {
01384                     FormatRating[i] = 0;
01385                         continue;
01386                 }
01387                 else
01388                 {
01389                         // advantage to as few different major flags as possible
01390                         // higher priority than similarity of pixelformats
01391                         rating += (32 - NumBitsOn( (pf->Flags ^ SeekFlags) & RDRIVER_PF_MAJOR_MASK )) <<6;
01392                 }
01393 
01394                 pfops = gePixelFormat_GetOperations(pf->PixelFormat);
01395 
01396                 if ( pf->PixelFormat == SeekFormat1 )
01397                 {
01398                         rating += 1<<22;
01399                 }
01400                 else if ( pf->PixelFormat == SeekFormat2 )
01401                 {
01402                         rating += 1<<21;
01403                 }
01404                 else if ( gePixelFormat_IsRaw(SeekFormat1) && gePixelFormat_IsRaw(pf->PixelFormat) )
01405                 {
01406                 int R,G,B,A;
01407                         // measure similarity
01408                         R = (seekops->RMask >> seekops->RShift) ^ (pfops->RMask >> pfops->RShift);
01409                         G = (seekops->GMask >> seekops->GShift) ^ (pfops->GMask >> pfops->GShift);
01410                         B = (seekops->BMask >> seekops->BShift) ^ (pfops->BMask >> pfops->BShift);
01411                         A = (seekops->AMask >> seekops->AShift) ^ (pfops->AMask >> pfops->AShift);
01412                         R = 8 - NumBitsOn(R);
01413                         G = 8 - NumBitsOn(G);
01414                         B = 8 - NumBitsOn(B);
01415                         A = 4*(8 - NumBitsOn(A)); // right number of A bits is molto importante
01416                         rating += R + G + B + A;
01417                 }
01418 
01419                 FoundAlpha = GE_FALSE;
01420 
01421                 if ( NumBitsOn(pfops->AMask) > 2 )
01422                         FoundAlpha = GE_TRUE;
01423 
01424                 if ( gePixelFormat_HasPalette(pf->PixelFormat) )
01425                 {
01426                         // if Pixelformat is 8BIT_PAL , look at the palette's format to see if it
01427                         //              had alpha!
01428                         assert(DriverPalFormat);
01429                         if ( gePixelFormat_HasGoodAlpha(DriverPalFormat->PixelFormat) )
01430                                 FoundAlpha = GE_TRUE;
01431                 }
01432 
01433                 if ( SeekAlpha && FoundAlpha )
01434                         rating += 1<<24; // HIGHEST ! (except separates)
01435                 else if ( (!SeekAlpha) && (!FoundAlpha) )
01436                         rating += 1<<16; // LOWEST
01437 
01438                 if ( (pf->Flags & RDRIVER_PF_HAS_ALPHA) && SeekSeparates )
01439                 {
01440                         // separates doesn't count as alpha unless we asked for it !
01441                         rating += 1<<25; // VERY HIGHEST !
01442                 }
01443         
01444                 if ( (pf->PixelFormat == GE_PIXELFORMAT_16BIT_1555_ARGB) && SeekCK )
01445                 {
01446                         rating += 1<<23; // just lower than alpha
01447                 }
01448                 else if ( GE_BOOLSAME((pf->Flags & RDRIVER_PF_CAN_DO_COLORKEY),SeekCK) )
01449                 {
01450                         rating += 1<<20;
01451                 }
01452 
01453                 if ( SeekCK && FoundAlpha ) //better than nothing!
01454                 {
01455                         rating += 1<<17;        // higher than !FoundAlpha
01456                 }
01457 
01458                 FormatRating[i] = rating;
01459         }
01460 
01461         rating = 0;
01462 
01463         for(i=0;i<ArrayLen;i++)
01464         {
01465                 if ( FormatRating[i] > rating )
01466                 {
01467                         rating = FormatRating[i];
01468                         *pTarget = DriverFormatsArray[i];
01469                 }
01470         }
01471 
01472         if ( rating == 0)
01473         {
01474                 geErrorLog_AddString(-1,"ChooseDriverFormat : no valid formats found!", NULL);
01475                 return GE_FALSE;
01476         }
01477 
01478         return GE_TRUE;
01479 }
01480 #endif
01481 
01482 geRDriver_THandle * geBitmap_CreateTHandle(DRV_Driver *Driver,int Width,int Height,int NumMipLevels,
01483                         gePixelFormat SeekFormat1,gePixelFormat SeekFormat2,geBoolean SeekCK,geBoolean SeekAlpha,geBoolean SeekSeparates,uint32 DriverFlags)
01484 {
01485 geRDriver_PixelFormat DriverFormats[MAX_DRIVER_FORMATS];
01486 geRDriver_PixelFormat *DriverFormatsPtr;
01487 int DriverFormatsCount;
01488 geRDriver_PixelFormat DriverFormat;
01489 geRDriver_THandle * Ret;
01490 
01491         DriverFormatsPtr = DriverFormats;
01492         Driver->EnumPixelFormats(EnumPFCB,&DriverFormatsPtr);
01493         DriverFormatsCount = ((uint32)DriverFormatsPtr - (uint32)DriverFormats)/sizeof(*DriverFormatsPtr);
01494         assert(DriverFormatsCount < MAX_DRIVER_FORMATS && DriverFormatsCount >= 0);
01495 
01496         if ( DriverFormatsCount == 0 )
01497         {
01498                 geErrorLog_AddString(-1,"Bitmap_CreateTHandle : no formats found!", NULL);
01499                 return NULL;
01500         }
01501 
01502         if ( ! SeekFormat1 )
01503                 SeekFormat1 = SeekFormat2;
01504         else if ( ! SeekFormat2 )
01505                 SeekFormat2 = SeekFormat1;
01506 
01507         assert( gePixelFormat_IsValid(SeekFormat1) );
01508         assert( gePixelFormat_IsValid(SeekFormat2) );
01509 
01510         // now choose DriverFormat
01511         if ( ! geBitmap_ChooseDriverFormat(SeekFormat1,SeekFormat2,SeekCK,SeekAlpha,SeekSeparates,DriverFlags,
01512                                                                                 DriverFormats,DriverFormatsCount,&DriverFormat) )
01513                 return NULL;
01514 
01515         assert( gePixelFormat_IsValid(DriverFormat.PixelFormat) );
01516 
01517 #if 1 //{
01518         Log_Printf("Bitmap : Chose %s for %s",
01519                 gePixelFormat_Description(DriverFormat.PixelFormat),
01520                 gePixelFormat_Description(SeekFormat1));
01521 
01522         if ( SeekFormat1 != SeekFormat2 )
01523                 Log_Printf(" (%s)",gePixelFormat_Description(SeekFormat2));
01524         if ( SeekCK )
01525                 Log_Printf(" (sought CK)");
01526         if ( SeekAlpha )
01527                 Log_Printf(" (sought Alpha)");
01528         if ( DriverFormat.Flags & RDRIVER_PF_2D )
01529                 Log_Printf(" (2D)");
01530         if ( DriverFormat.Flags & RDRIVER_PF_3D )
01531                 Log_Printf(" (3D)");
01532         if ( DriverFormat.Flags & RDRIVER_PF_CAN_DO_COLORKEY )
01533                 Log_Printf(" (can CK)");
01534         if ( DriverFormat.Flags & RDRIVER_PF_PALETTE )
01535                 Log_Printf(" (Palette)");
01536         if ( DriverFormat.Flags & RDRIVER_PF_ALPHA )
01537                 Log_Printf(" (Alpha)");
01538         if ( DriverFormat.Flags & RDRIVER_PF_LIGHTMAP )
01539                 Log_Printf(" (Lightmap)");
01540 
01541         Log_Printf("\n");
01542 #endif //}
01543 
01544         Ret = Driver->THandle_Create(
01545                 Width,Height,
01546                 NumMipLevels,
01547                 &DriverFormat);
01548 
01549         if ( ! Ret )
01550         {
01551                 geErrorLog_AddString(-1, Driver->LastErrorStr, NULL);
01552                 geErrorLog_AddString(-1,"Bitmap_CreateTHandle : Driver->THandle_Create failed", NULL);
01553         }
01554 
01555 return Ret;
01556 }
01557 
01558 GENESISAPI      geBoolean       GENESISCC       geBitmap_HasAlpha(const geBitmap * Bmp)
01559 {
01560         assert( geBitmap_IsValid(Bmp) );
01561         
01562         if ( Bmp->Alpha )
01563                 return GE_TRUE;
01564 
01565         if ( gePixelFormat_HasGoodAlpha(Bmp->Info.Format) )
01566                 return GE_TRUE;
01567 
01568         if ( gePixelFormat_HasPalette(Bmp->Info.Format) && Bmp->Info.Palette )
01569         {
01570                 if ( gePixelFormat_HasGoodAlpha(Bmp->Info.Palette->Format) )
01571                         return GE_TRUE;
01572         }       
01573 
01574 return GE_FALSE;
01575 }
01576 
01577 geBoolean       BITMAP_GENESIS_INTERNAL geBitmap_AttachToDriver(geBitmap *Bmp, 
01578         DRV_Driver * Driver, uint32 DriverFlags)
01579 {
01580 
01581         /**************
01582         * When you want to change the Driver,
01583         * I still need a copy of the old one to get the bits out
01584         * of the old THandles.  That is:
01585         * 
01586         *       AttachDriver(Bmp,Driver)
01587         *       <do stuff>
01588         *       Change Driver Entries
01589         *       AttachDriver(Bmp,Driver)
01590         * 
01591         * is forbidden!  The two different options are :
01592         * 
01593         *       1.
01594         * 
01595         *       AttachDriver(Bmp,Driver)
01596         *       <do stuff>
01597         *       DetachDriver(Bmp)
01598         *       Change Driver Entries
01599         *       AttachDriver(Bmp,Driver)
01600         * 
01601         *       2.
01602         * 
01603         *       AttachDriver(Bmp,Driver1)
01604         *       <do stuff>
01605         *       Driver2 = copy of Driver1
01606         *       Change Driver2 Entries
01607         *       AttachDriver(Bmp,Driver2)
01608         *       Free Driver1
01609         * 
01610         * This isn't so critical when just changing modes,
01611         * but is critical when changing drivers.
01612         * 
01613         ****************/
01614 
01615         assert( geBitmap_IsValid(Bmp) );
01616 
01617         if ( Bmp->LockOwner || Bmp->DataOwner || Bmp->LockCount )
01618         {
01619                 geErrorLog_AddString(-1,"AttachToDriver : not an isolated bitmap", NULL);
01620                 return GE_FALSE;
01621         }
01622 
01623         if ( Bmp->DriverHandle && Bmp->Driver == Driver )
01624         {
01625                 assert( DriverFlags == 0 || DriverFlags == Bmp->DriverFlags );
01626                 return GE_TRUE;
01627         }
01628 
01629         if ( ! geBitmap_DetachDriver(Bmp,GE_TRUE) )
01630         {
01631                 geErrorLog_AddString(-1,"AttachToDriver : detach failed", NULL);
01632                 return GE_FALSE;
01633         }
01634 
01635         if ( DriverFlags == 0 )
01636         {
01637                 DriverFlags = Bmp->DriverFlags;
01638                 if ( ! DriverFlags )
01639                 {
01640                         //      return GE_FALSE;
01641                         // ? {}
01642                         DriverFlags = RDRIVER_PF_3D;
01643                 }
01644         }
01645 
01646         if ( Driver )
01647         {
01648         int NumMipLevels;
01649         int Width,Height;
01650         geBoolean WantAlpha;
01651         geRDriver_THandle * DriverHandle;
01652 
01653 //              if ( Bmp->DriverFlags & RDRIVER_PF_COMBINE_LIGHTMAP )
01654 //                      Bmp->SeekMipCount = max(Bmp->SeekMipCount,4);
01655 
01656                 NumMipLevels = max(Bmp->SeekMipCount,(Bmp->Info.MaximumMip + 1));
01657                 if ( NumMipLevels > 4 ) NumMipLevels = 4; // {} kind of a hack, our drivers ignore mips > 4
01658 
01659                 // make sizes power-of-two and square
01660                 // {} note : must let drivers do this to correctly scale UV's 
01661                 Width   = Bmp->Info.Width;
01662                 Height  = Bmp->Info.Height;
01663 
01664                 WantAlpha = geBitmap_HasAlpha(Bmp);
01665                 if ( gePixelFormat_HasGoodAlpha(Bmp->PreferredFormat) )
01666                         WantAlpha = GE_TRUE;
01667 
01668                 assert( geBitmap_IsValid(Bmp) );
01669 
01670                 DriverHandle = geBitmap_CreateTHandle(Driver,Width,Height,NumMipLevels,
01671                         Bmp->PreferredFormat,Bmp->Info.Format,Bmp->Info.HasColorKey,
01672                         WantAlpha, (Bmp->Alpha) ? GE_TRUE : GE_FALSE,
01673                         DriverFlags);
01674 
01675                 assert( geBitmap_IsValid(Bmp) );
01676 
01677                 if ( ! DriverHandle )
01678                         return GE_FALSE;
01679 
01680                 Bmp->DriverHandle = DriverHandle;
01681                 Bmp->Driver = Driver;
01682                 Bmp->DriverFlags = DriverFlags;
01683 
01684 #ifdef _DEBUG
01685                 Bmp->DriverInfo = Bmp->Info;
01686                 assert( geBitmap_IsValid(Bmp) );
01687 #endif
01688                 clear(&(Bmp->DriverInfo));
01689 
01690                 if ( ! geBitmap_MakeDriverLockInfo(Bmp,0,&(Bmp->DriverInfo)) )
01691                 {
01692                         geErrorLog_AddString(-1,"AttachToDriver : updateinfo", NULL);
01693                         return GE_FALSE;
01694                 }
01695 
01696                 Bmp->DriverInfo.MinimumMip = 0;
01697                 Bmp->DriverInfo.MaximumMip = NumMipLevels - 1;
01698                 
01699                 assert( geBitmap_IsValid(Bmp) );
01700 
01701                 assert( geBitmap_IsValid(Bmp) );
01702 
01703                 if ( ! geBitmap_Update_SystemToDriver(Bmp) )
01704                 {
01705                         geErrorLog_AddString(-1,"AttachToDriver : Update_SystemToDriver", NULL);
01706                         Driver->THandle_Destroy(Bmp->DriverHandle);
01707                         Bmp->DriverHandle = NULL;
01708                         return GE_FALSE;
01709                 }
01710 
01711                 // {} Palette : Update_System calls Blit_Data, which should build it for us 
01712                 //              if Driver is pal & System isn't
01713         }
01714 
01715 return GE_TRUE;
01716 }
01717 
01718 geBoolean geBitmap_FixDriverFlags(uint32 *pFlags)
01719 {
01720 uint32 DriverFlags;
01721         assert(pFlags);
01722         DriverFlags = *pFlags;
01723         
01724         if ( DriverFlags & RDRIVER_PF_COMBINE_LIGHTMAP )
01725                 DriverFlags |= RDRIVER_PF_3D;
01726         if ( DriverFlags & RDRIVER_PF_CAN_DO_COLORKEY )
01727         {
01728                 // <> someone is doing this!
01729                 // bad!
01730                 DriverFlags ^= RDRIVER_PF_CAN_DO_COLORKEY;
01731                 //      return GE_FALSE;
01732         }
01733         if ( (DriverFlags & RDRIVER_PF_COMBINE_LIGHTMAP) &&
01734                 (DriverFlags & (RDRIVER_PF_LIGHTMAP | RDRIVER_PF_PALETTE) ) )
01735                 return GE_FALSE;
01736         if ( NumBitsOn(DriverFlags & RDRIVER_PF_MAJOR_MASK) == 0 )
01737                 return GE_FALSE;
01738         *pFlags = DriverFlags;
01739 return GE_TRUE;
01740 }
01741 
01742 geBoolean BITMAP_GENESIS_INTERNAL geBitmap_SetDriverFlags(geBitmap *Bmp,uint32 Flags)
01743 {
01744         assert( geBitmap_IsValid(Bmp) );
01745         assert(Flags);
01746         if ( ! geBitmap_FixDriverFlags(&Flags) )
01747         {
01748                 Bmp->DriverFlags = 0;
01749                 return GE_FALSE;
01750         }
01751         Bmp->DriverFlags = Flags;
01752 return GE_TRUE;
01753 }
01754 
01755 geBoolean BITMAP_GENESIS_INTERNAL geBitmap_DetachDriver(geBitmap *Bmp,geBoolean DoUpdate)
01756 {
01757 geBoolean Ret = GE_TRUE;
01758 
01759         assert(geBitmap_IsValid(Bmp) );
01760 
01761         if ( Bmp->LockOwner || Bmp->DataOwner || Bmp->LockCount )
01762         {
01763                 geErrorLog_AddString(-1,"DetachDriver : not an isolated bitmap!", NULL);
01764                 return GE_FALSE;
01765         }
01766 
01767         if ( Bmp->RefCount > 1 )
01768                 DoUpdate = GE_TRUE;
01769 
01770         if ( Bmp->Driver && Bmp->DriverHandle )
01771         {
01772                 if ( DoUpdate )
01773                 {
01774                         if ( ! geBitmap_Update_DriverToSystem(Bmp) )
01775                         {
01776                                 geErrorLog_AddString(-1,"DetachDriver : Update_DriverToSystem", NULL);
01777                                 Ret = GE_FALSE;
01778                         }
01779                         assert(Bmp->DriverDataChanged == GE_FALSE);
01780                 }
01781                         Bmp->Driver->THandle_Destroy(Bmp->DriverHandle);
01782                 Bmp->DriverHandle = NULL;
01783         }
01784 
01785         if ( Bmp->DriverInfo.Palette )
01786         {
01787                 // save it for later in case we re-attach
01788                 if ( ! Bmp->Info.Palette )
01789                 {
01790                 geBitmap_Palette * NewPal;
01791                 gePixelFormat Format;
01792                         Format = Bmp->DriverInfo.Palette->Format;
01793                         NewPal = geBitmap_Palette_Create(Format,256);
01794                         if ( NewPal )
01795                         {
01796                                 if ( geBitmap_Palette_Copy(Bmp->DriverInfo.Palette,NewPal) )
01797                                 {
01798                                         Bmp->Info.Palette = NewPal;
01799                                 }
01800                                 else
01801                                 {
01802                                         geBitmap_Palette_Destroy(&NewPal);
01803                                 }
01804                         }
01805                 }
01806 
01807                 geBitmap_Palette_Destroy(&(Bmp->DriverInfo.Palette));
01808         }
01809 
01810         if ( Bmp->Alpha )
01811         {
01812                 if ( ! geBitmap_DetachDriver(Bmp->Alpha,DoUpdate) )
01813                 {
01814                         geErrorLog_AddString(-1,"DetachDriver : detach alpha", NULL);
01815                         Ret = GE_FALSE;
01816                 }
01817         }
01818 
01819         Bmp->DriverInfo.Width = Bmp->DriverInfo.Height = Bmp->DriverInfo.Stride = 0;
01820         Bmp->DriverInfo.MinimumMip = Bmp->DriverInfo.MaximumMip = 0;
01821         Bmp->DriverInfo.ColorKey = Bmp->DriverInfo.HasColorKey = Bmp->DriverInfo.Format = 0;
01822         Bmp->DriverInfo.Palette = NULL;
01823         Bmp->DriverMipLock = 0;
01824         Bmp->DriverBitsLocked = GE_FALSE;
01825         Bmp->DriverDataChanged = GE_FALSE;
01826         Bmp->DriverHandle = NULL;
01827         Bmp->Driver = NULL;
01828 
01829         //Bmp->DriverFlags left intentionally !
01830 
01831 return Ret;
01832 }
01833 
01834 geBoolean GENESISCC geBitmap_SetGammaCorrection_DontChange(geBitmap *Bmp,geFloat Gamma)
01835 {
01836         assert(geBitmap_IsValid(Bmp));
01837         assert( Gamma > 0.0f );
01838 
01839         if ( ! Bmp->DriverGammaSet )
01840         {
01841                 Bmp->DriverGammaLast = Bmp->DriverGamma;
01842                 Bmp->DriverGamma = Gamma;
01843         }
01844 
01845 return GE_TRUE;
01846 }
01847 
01848 GENESISAPI geBoolean GENESISCC geBitmap_SetGammaCorrection(geBitmap *Bmp,geFloat Gamma,geBoolean Apply)
01849 {
01850         assert(geBitmap_IsValid(Bmp));
01851         assert( Gamma > 0.0f );
01852 
01853         /***
01854 
01855         there are actually some anomalies involved in exposing this to the user:
01856                 if the driver's gamma correction is turned on, then this Gamma will be applied *in addition* to the driver gamma.
01857         There's no easy way to avoid that problem.
01858 
01859         we like to expose this to the user so that they can disable software gamma correction on some bitmaps
01860                 (eg. procedurals)
01861         perhaps provide a Bitmap_DisableGamma(Bmp) instead of SetGamma ?
01862 
01863         **/
01864 
01865         if ( Apply && Bmp->DriverHandle )
01866         {
01867                 if ( fabs(Bmp->DriverGamma - Gamma) > 0.1f )
01868                 {
01869                         if ( gePixelFormat_BytesPerPel(Bmp->Info.Format) == 0 && Bmp->DriverHandle )
01870                         {
01871                                 // system format is compressed, and Bmp is on the card
01872 
01873                                 if ( (Bmp->DriverGammaLast >= Bmp->DriverGamma && Bmp->DriverGamma >= Gamma) ||
01874                                          (Bmp->DriverGammaLast <= Bmp->DriverGamma && Bmp->DriverGamma <= Gamma) )
01875                                 {
01876                                         // moving in the same direction
01877 
01878                                         // invert the old
01879                                         if ( ! geBitmap_Gamma_Apply(Bmp,GE_TRUE) )
01880                                                 return GE_FALSE;
01881 
01882                                         Bmp->DriverGammaLast = Bmp->DriverGamma;
01883                                         Bmp->DriverGamma = Gamma;
01884 
01885                                         // apply the new
01886                                         if ( ! geBitmap_Gamma_Apply(Bmp,GE_FALSE) )
01887                                                 return GE_FALSE;
01888                                 }
01889                                 else
01890                                 {
01891                                         // changed direction so must do an update
01892 
01893                                         if ( ! geBitmap_Update_DriverToSystem(Bmp) )
01894                                                 return GE_FALSE;
01895 
01896                                         Bmp->DriverGammaLast = Bmp->DriverGamma = Gamma;
01897                                         
01898                                         if ( ! geBitmap_Update_SystemToDriver(Bmp) )
01899                                                 return GE_FALSE;
01900                                 }
01901                         }
01902                         else
01903                         {
01904                                 if ( ! geBitmap_Update_DriverToSystem(Bmp) )
01905                                         return GE_FALSE;
01906 
01907                                 Bmp->DriverGammaLast = Bmp->DriverGamma = Gamma;
01908                                 
01909                                 if ( ! geBitmap_Update_SystemToDriver(Bmp) )
01910                                         return GE_FALSE;
01911                         }
01912                 }
01913         }
01914         else
01915         {
01916                 Bmp->DriverGamma = Gamma;
01917         }
01918         Bmp->DriverGammaSet = GE_TRUE;
01919 
01920 return GE_TRUE;
01921 }
01922 
01923 geRDriver_THandle * BITMAP_GENESIS_INTERNAL geBitmap_GetTHandle(const geBitmap *Bmp)
01924 {
01925 //      assert( geBitmap_IsValid(Bmp) );
01926 
01927         return Bmp->DriverHandle;
01928 }
01929 
01930 geBoolean geBitmap_Update_SystemToDriver(geBitmap *Bmp)
01931 {
01932 geBitmap * SrcLocks[MAXMIPLEVELS];
01933 geBoolean Ret,MipsChanged;
01934 int mip,mipMin,mipMax;
01935 geRDriver_THandle * SaveDriverHandle;
01936 geBitmap * SaveAlpha;
01937 int SaveMaxMip;
01938         
01939         assert( geBitmap_IsValid(Bmp) );
01940 
01948         if ( Bmp->LockOwner )
01949                 Bmp = Bmp->LockOwner;
01950 
01951         if ( Bmp->LockCount > 0 || Bmp->DataOwner )
01952         {
01953                 geErrorLog_AddString(-1,"Update_SystemToDriver : not an original bitmap", NULL);
01954                 return GE_FALSE;
01955         }
01956 
01957         if ( ! Bmp->DriverHandle )
01958         {
01959                 geErrorLog_AddString(-1,"Update_SystemToDriver : no driver data", NULL);
01960                 return GE_FALSE;
01961         }
01962 
01963         MipsChanged = GE_FALSE;
01964         for(mip=Bmp->DriverInfo.MinimumMip;mip<=Bmp->DriverInfo.MaximumMip;mip++)
01965         {
01966                 if ( Bmp->Modified[mip] && mip != Bmp->Info.MinimumMip )
01967                 {
01968                         assert(Bmp->Data[mip]);
01969                         MipsChanged = GE_TRUE;
01970                 }
01971         }
01972 
01973         //make mips after driver blit
01974         
01975 #if 0 
01976         MipsChanged = GE_TRUE;
01977 #endif
01978 
01979         mipMin = Bmp->DriverInfo.MinimumMip;
01980 
01981         if ( MipsChanged )
01982                 mipMax = Bmp->DriverInfo.MaximumMip;
01983         else
01984                 mipMax = mipMin;
01985 
01986 
01987         SaveDriverHandle = Bmp->DriverHandle;
01988         Bmp->DriverHandle = NULL;       // so Lock() won't use the driver data
01989 
01990         SaveAlpha = Bmp->Alpha;
01991 
01992         if ( Bmp->Alpha && ! gePixelFormat_HasGoodAlpha(Bmp->DriverInfo.Format) && 
01993                         (Bmp->DriverFlags & RDRIVER_PF_HAS_ALPHA) )
01994         {
01995                 // hide the alpha so that it won't be used to make a colorkey in the target
01996                 // we'll blit it independently later
01997                 Bmp->Alpha = NULL;
01998         }
01999 
02000         if ( ! geBitmap_LockForReadNative(Bmp,SrcLocks,mipMin,mipMax) )
02001         {
02002                 geErrorLog_AddString(-1,"Update_SystemToDriver : LockForReadNative", NULL);
02003                 return GE_FALSE;
02004         }
02005 
02006         Ret = GE_TRUE;
02007         Bmp->DriverHandle = SaveDriverHandle;
02008         Bmp->Alpha = NULL;
02009 
02010         // we should have always updated the driver to system before fiddling the system
02011         assert( ! Bmp->DriverDataChanged );
02012 
02021         for(mip=mipMin;mip <=mipMax;mip++)
02022         {
02023         geBitmap *SrcMip;
02024         void * SrcBits,*DstBits;
02025         geBitmap_Info DstInfo;
02026 
02027                 SrcMip = SrcLocks[mip - mipMin];
02028                 SrcBits = geBitmap_GetBits(SrcMip);
02029 
02030                 DstInfo = Bmp->DriverInfo;
02031 
02032                 if ( ! geBitmap_MakeDriverLockInfo(Bmp,mip,&DstInfo) )
02033                 {
02034                         geErrorLog_AddString(-1,"Update_SystemToDriver : MakeInfo", NULL);
02035                         Ret = GE_FALSE;
02036                         continue;
02037                 }
02038 
02039                 // Zooma! THandle_Lock might lock the Win16 Lock !
02040                 //      this is really bad when _BlitData is a wavelet decompress !
02041                 // {} try this : decompress to a buffer in memory (on a thread)
02042                 //      then THandle_Lock and just do a (prefetching) memcpy
02043                 //#pragma message("Bitmap : minimize time spent in a THandle_Lock!")
02044 
02045                 if ( ! Bmp->Driver->THandle_Lock(SaveDriverHandle,mip,&DstBits) )
02046                 {
02047                         geErrorLog_AddString(-1,"Update_SystemToDriver : THandle_Lock", NULL);
02048                         Ret = GE_FALSE;
02049                         continue;
02050                 }
02051 
02052                 if ( ! SrcBits || ! DstBits )
02053                 {
02054                         geErrorLog_AddString(-1,"Update_SystemToDriver : No Bits", NULL);
02055                         Ret = GE_FALSE;
02056                         continue;
02057                 }
02058 
02059                 assert( DstInfo.Palette == Bmp->DriverInfo.Palette );
02060 
02061                 if ( ! geBitmap_BlitData(       &(SrcMip->Info),SrcBits,SrcMip,
02062                                                                         &DstInfo,               DstBits,Bmp,
02063                                                                         SrcMip->Info.Width,SrcMip->Info.Height) )
02064                 {
02065                         geErrorLog_AddString(-1,"Update_SystemToDriver : BlitData", NULL);
02066                         //assert(0);
02067                         Ret = GE_FALSE;
02068                         continue;
02069                 }
02070 
02071                 if ( ! Bmp->Driver->THandle_UnLock(SaveDriverHandle,mip) )
02072                 {
02073                         geErrorLog_AddString(-1,"Update_SystemToDriver : THandle_UnLock", NULL);
02074                         Ret = GE_FALSE;
02075                         continue;
02076                 }
02077 
02078                 // normally this would be done by the Bitmap_UnLock ,
02079                 //  but since we don't lock ..
02080                 if ( DstInfo.Palette != Bmp->DriverInfo.Palette )
02081                 {
02082                         //assert( OldDstPal == NULL );
02083                         geBitmap_SetPalette(Bmp,DstInfo.Palette);
02084                         geBitmap_Palette_Destroy(&(DstInfo.Palette));
02085                         // must destroy here, since DstInfo is on the stack!
02086                 }
02087         }
02088 
02089         Bmp->Alpha = SaveAlpha;
02090         Bmp->DriverBitsLocked = GE_FALSE;
02091         Bmp->DriverMipLock = 0;
02092         Bmp->DriverDataChanged = GE_FALSE;
02093 
02094         geBitmap_UnLockArray(SrcLocks, mipMax - mipMin + 1 );
02095 
02096         if ( ! Ret )
02097         {
02098                 geErrorLog_AddString(-1,"Update_SystemToDriver : Locking and Blitting error", NULL);
02099         }
02100 
02101         if ( Bmp->Alpha && ! gePixelFormat_HasGoodAlpha(Bmp->DriverInfo.Format) && 
02102                         (Bmp->DriverFlags & RDRIVER_PF_HAS_ALPHA) )
02103         {
02104         geRDriver_THandle * AlphaTH;
02105 
02106                 // blit the alpha surface to the separate alpha
02107 
02108                 AlphaTH = Bmp->Driver->THandle_GetAlpha(Bmp->DriverHandle);
02109                 if ( !AlphaTH || AlphaTH != Bmp->Alpha->DriverHandle)
02110                 {
02111                         if ( ! geBitmap_AttachToDriver(Bmp->Alpha,Bmp->Driver,Bmp->Alpha->DriverFlags | RDRIVER_PF_ALPHA) )
02112                         {
02113                                 geErrorLog_AddString(-1,"AttachToDriver : attach Alpha", NULL);
02114                                 return GE_FALSE;
02115                         }
02116 
02117                         assert(Bmp->Alpha->DriverHandle);
02118                         if ( ! Bmp->Driver->THandle_SetAlpha(Bmp->DriverHandle,Bmp->Alpha->DriverHandle) )
02119                         {
02120                                 geErrorLog_AddString(-1,"AttachToDriver : THandle_SetAlpha", NULL);
02121                                 geBitmap_DetachDriver(Bmp->Alpha,GE_FALSE);
02122                                 geBitmap_DetachDriver(Bmp,GE_FALSE);
02123                                 return GE_FALSE;
02124                         }
02125                         
02126                         AlphaTH = Bmp->Driver->THandle_GetAlpha(Bmp->DriverHandle);
02127                         assert(AlphaTH == Bmp->Alpha->DriverHandle);
02128                 }
02129         }
02130 
02131         // now bits are on driver , gamma correct them
02132 
02133         //for gamma : just Gamma up to mipMax then make mips from it
02134         //      seems to work
02135 
02136         SaveMaxMip = Bmp->DriverInfo.MaximumMip;
02137         Bmp->DriverInfo.MaximumMip = mipMax;
02138         if ( ! geBitmap_Gamma_Apply(Bmp,GE_FALSE) )
02139         {
02140                 geErrorLog_AddString(-1,"AttachToDriver : Gamma_Apply failed!", NULL);
02141                 Ret = GE_FALSE;
02142         }
02143         Bmp->DriverInfo.MaximumMip = SaveMaxMip;
02144 
02145         if ( ! MipsChanged && mipMax < Bmp->DriverInfo.MaximumMip )
02146         {
02147                 for(mip=mipMax+1;mip<= Bmp->DriverInfo.MaximumMip; mip++)
02148                 {
02149                         if ( ! geBitmap_UpdateMips(Bmp,mip-1,mip) )
02150                         {
02151                                 geErrorLog_AddString(-1,"AttachToDriver : UpdateMips on driver failed!", NULL);
02152                                 return GE_FALSE;
02153                         }
02154                 }
02155         }
02156 
02157         Bmp->DriverDataChanged = GE_FALSE; // in case _SetPal freaks us out
02158 
02159 return Ret;
02160 }
02161 
02162 geBoolean geBitmap_Update_DriverToSystem(geBitmap *Bmp)
02163 {
02164 geBitmap *DriverLocks[MAXMIPLEVELS];
02165 geBoolean Ret;
02166 int mip;
02167         
02168         assert( geBitmap_IsValid(Bmp) );
02169 
02170         if ( Bmp->LockOwner )
02171                 Bmp = Bmp->LockOwner;
02172 
02173         if ( Bmp->LockCount > 0 || Bmp->DataOwner )
02174         {
02175                 geErrorLog_AddString(-1,"Update_DriverToSystem : not an original bitmap", NULL);
02176                 return GE_FALSE;
02177         }
02178 
02179         if ( ! Bmp->DriverHandle )
02180         {
02181                 geErrorLog_AddString(-1,"Update_DriverToSystem : no driver data", NULL);
02182                 return GE_FALSE;
02183         }
02184 
02185         if ( ! Bmp->DriverDataChanged )
02186                 return GE_TRUE;
02187 
02188         // bits are on driver; undo the gamma to copy them home
02189 
02190         Log_Puts("Bitmap : Doing Update_DriverToSystem");
02191 
02192         if ( ! geBitmap_Gamma_Apply(Bmp,GE_TRUE) ) // undo the gamma!
02193                 return GE_FALSE;
02194 
02195         if ( Bmp->Info.Palette && Bmp->DriverInfo.Palette )
02196         {
02197                 if ( ! geBitmap_Palette_Copy(Bmp->DriverInfo.Palette,Bmp->Info.Palette) )
02198                 {
02199                         geErrorLog_AddString(-1,"Update_DriverToSystem : Palette_Copy", NULL);
02200                 }
02201         }
02202 
02203         if ( geBitmap_LockForReadNative(Bmp,DriverLocks,
02204                         Bmp->DriverInfo.MinimumMip,Bmp->DriverInfo.MaximumMip) )
02205         {
02206                 Ret = GE_TRUE;
02207 
02208                 for(mip=Bmp->DriverInfo.MinimumMip;mip <=Bmp->DriverInfo.MaximumMip;mip++)
02209                 {       
02210                 geBitmap *MipBmp;
02211                 geBitmap_Info SystemInfo;
02212 
02213                         MipBmp = DriverLocks[mip];
02214 
02215                         if ( Bmp->Modified[mip] )
02216                         {
02217                         void *DriverBits,*SystemBits;
02218                                 DriverBits = geBitmap_GetBits(MipBmp);
02219                                 assert( MipBmp->DriverBitsLocked );
02220 
02221                                 if ( ! geBitmap_AllocSystemMip(Bmp,mip) )
02222                                         Ret = GE_FALSE;
02223 
02224                                 SystemBits = Bmp->Data[mip];
02225 
02226                                 geBitmap_MakeMipInfo(&(Bmp->Info),mip,&SystemInfo);
02227 
02228                                 if ( DriverBits && SystemBits )
02229                                 {
02230                                         // _Update_DriverToSystem
02231                                         // {} palette (not) made in AttachToDriver; must be made in here->
02232                                         if ( ! geBitmap_BlitData(       &(MipBmp->Info), DriverBits, MipBmp,
02233                                                                                                 &SystemInfo,    SystemBits, Bmp,
02234                                                                                                 SystemInfo.Width,SystemInfo.Height) )
02235                                                 Ret = GE_FALSE;
02236                                 }
02237                                 else
02238                                 {
02239                                         Ret = GE_FALSE;
02240                                 }
02241                         }
02242                         
02243                         geBitmap_UnLock(DriverLocks[mip]);
02244                 }
02245 
02246                 Bmp->DriverDataChanged = GE_FALSE;
02247         }
02248         else
02249         {
02250                 Ret = GE_FALSE;
02251         }
02252 
02253         if ( ! Ret )
02254         {
02255                 geErrorLog_AddString(-1,"Update_DriverToSystem : Locking and Blitting error", NULL);
02256         }
02257 
02258         if ( ! geBitmap_Gamma_Apply(Bmp,GE_FALSE) ) // redo the gamma!
02259                 return GE_FALSE;
02260 
02261 return Ret;
02262 }
02263 
02264 /*}{ ************* Mip Control *****************/
02265 
02266 // Note : all the Mip control 
02267 
02268 GENESISAPI geBoolean GENESISCC geBitmap_RefreshMips(geBitmap *Bmp)
02269 {
02270 int mip;
02271 
02272         assert( geBitmap_IsValid(Bmp) );
02273 
02274         if ( Bmp->LockOwner || Bmp->LockCount || Bmp->DataOwner )
02275                 return GE_FALSE;
02276 
02277         for(mip = (Bmp->Info.MinimumMip + 1);mip <= Bmp->Info.MaximumMip;mip++)
02278         {
02279                 if ( Bmp->Data[mip] && !(Bmp->Modified[mip]) )
02280                 {
02281                 int src;
02282                         src = mip-1;
02283                         while( ! Bmp->Data[src] )
02284                         {
02285                                 src--;
02286                                 if ( src < Bmp->Info.MinimumMip )
02287                                         return GE_FALSE;
02288                         }
02289                         if ( ! geBitmap_UpdateMips(Bmp,src,mip) )
02290                                 return GE_FALSE;
02291                 }
02292         }
02293 
02294 #if 0   // never turn off a modified flag
02295         for(mip=0;mip<MAXMIPLEVELS;mip++)
02296                 Bmp->Modified[mip] = GE_FALSE;
02297 #endif
02298 
02299 return GE_TRUE;
02300 }
02301 
02302 GENESISAPI geBoolean GENESISCC geBitmap_UpdateMips(geBitmap *Bmp,int fm,int to)
02303 {
02304 geBitmap * Locks[MAXMIPLEVELS];
02305 void *FmBits,*ToBits;
02306 geBitmap_Info FmInfo,ToInfo;
02307 geBoolean Ret = GE_FALSE;
02308 
02309         assert( geBitmap_IsValid(Bmp) );
02310 
02311         if ( Bmp->LockOwner || Bmp->LockCount > 0 || Bmp->DataOwner )
02312                 return GE_FALSE;
02313 
02314         if ( fm >= to )
02315                 return GE_FALSE;
02316 
02317         if ( Bmp->DriverHandle ) 
02318         {
02319                 //{} this version does *NOT* make new mips if to > Bmp->DriverInfo.MaximumMip
02320 
02321                 if ( ! geBitmap_LockForWrite(Bmp,Locks,fm,to) )
02322                         return GE_FALSE;
02323 
02324                 if ( geBitmap_GetInfo(Locks[0],&FmInfo,NULL) && geBitmap_GetInfo(Locks[to - fm],&ToInfo,NULL) )
02325                 {
02326                         FmBits = geBitmap_GetBits(Locks[0]);
02327                         ToBits = geBitmap_GetBits(Locks[to - fm]);
02328                 
02329                         if ( FmBits && ToBits )
02330                         {
02331                                 Ret = geBitmap_UpdateMips_Data( &FmInfo, FmBits, 
02332                                                                                                 &ToInfo, ToBits );
02333                         }
02334                 }
02335 
02336                 geBitmap_UnLockArray_NoChange(Locks,to - fm + 1);
02337         }
02338         else
02339         {
02340                 Ret = geBitmap_UpdateMips_System(Bmp,fm,to);
02341         }
02342 
02343 return Ret;
02344 }
02345 
02346 geBoolean geBitmap_UpdateMips_System(geBitmap *Bmp,int fm,int to)
02347 {
02348 geBitmap_Info FmInfo,ToInfo;
02349 geBoolean Ret;
02350 
02351         assert( geBitmap_IsValid(Bmp) );
02352 
02353         // this is called to create new mips in LockFor* -> CreateLockFrom* (through MakeSystemMips)
02354 
02355         if ( Bmp->LockOwner )
02356                 Bmp = Bmp->LockOwner;
02357 //      if ( Bmp->LockCount > 0 )
02358 //              return GE_FALSE;
02359         if ( Bmp->DataOwner )
02360                 return GE_FALSE;
02361 
02362         // {} for compressed data, just don't make mips and say we did!
02363         if ( gePixelFormat_BytesPerPel(Bmp->Info.Format) < 1 )
02364                 return GE_TRUE;
02365 
02366         while(Bmp->Data[fm] == NULL || fm == to )
02367         {
02368                 fm--;
02369                 if ( fm < 0 )
02370                         return GE_FALSE;
02371         }
02372 
02373         if ( fm < Bmp->Info.MinimumMip || fm > Bmp->Info.MaximumMip ||
02374              to < fm || to >= MAXMIPLEVELS )
02375                 return GE_FALSE;
02376 
02377         if ( ! Bmp->Data[to] )
02378         {
02379                 if ( ! geBitmap_AllocSystemMip(Bmp,to) )
02380                         return GE_FALSE;
02381         }
02382 
02383         assert( to > fm && fm >= 0 );
02384 
02385         FmInfo = ToInfo = Bmp->Info;
02386 
02387         FmInfo.Width = SHIFT_R_ROUNDUP(Bmp->Info.Width ,fm);
02388         FmInfo.Height= SHIFT_R_ROUNDUP(Bmp->Info.Height,fm);
02389         FmInfo.Stride= SHIFT_R_ROUNDUP(Bmp->Info.Stride,fm);
02390         ToInfo.Width = SHIFT_R_ROUNDUP(Bmp->Info.Width ,to);
02391         ToInfo.Height= SHIFT_R_ROUNDUP(Bmp->Info.Height,to);
02392         ToInfo.Stride= SHIFT_R_ROUNDUP(Bmp->Info.Stride,to);
02393 
02394         Ret = geBitmap_UpdateMips_Data( &FmInfo, Bmp->Data[fm],
02395                                                                         &ToInfo, Bmp->Data[to]);
02396 
02397         Bmp->Info.MaximumMip = max(Bmp->Info.MaximumMip,to);
02398 
02399 return Ret;
02400 }
02401 
02402 geBoolean geBitmap_UpdateMips_Data(     geBitmap_Info * FmInfo,void * FmBits,
02403                                                                         geBitmap_Info * ToInfo,void * ToBits)
02404 {
02405 int fmxtra,tow,toh,toxtra,fmw,fmh,fmstep,x,y,bpp;
02406 
02407         assert( FmInfo && ToInfo && FmBits && ToBits );
02408         assert( FmInfo->Format == ToInfo->Format && FmInfo->HasColorKey == ToInfo->HasColorKey );
02409 
02410         tow = ToInfo->Width;
02411         toh = ToInfo->Height;
02412         toxtra = ToInfo->Stride - ToInfo->Width;
02413         
02414         x = ToInfo->Width;
02415         fmstep = 1;
02416         while( x < FmInfo->Width )
02417         {
02418                 fmstep += fmstep;
02419                 x += x;
02420         }
02421 
02422         fmw = FmInfo->Width;
02423         fmh = FmInfo->Height;
02424         fmxtra = (FmInfo->Stride - tow) * fmstep; // amazingly simple and correct! think about it!
02425 
02426         // fmh == 15
02427         // toh == 8
02428         // fmstep == 2
02429         // 7*2 <= 14 -> Ok
02430         if ( (toh-1)*fmstep > (fmh - 1) )
02431         {
02432                 geErrorLog_AddString(-1,"UpdateMips_Data : Vertical mip scaling doesn't match horizontal!", NULL);
02433                 return GE_FALSE;
02434         }
02435 
02436         // {} todo : average for some special cases (16rgb,24rgb,32rgb)
02437 
02438         bpp = gePixelFormat_BytesPerPel(FmInfo->Format);
02439 
02440         if ( fmstep == 2 && bpp > 1 )
02441         {
02442         int R1,G1,B1,A1,R2,G2,B2,A2,R3,G3,B3,A3,R4,G4,B4,A4;
02443         gePixelFormat_ColorGetter GetColor;
02444         gePixelFormat_ColorPutter PutColor;
02445         const gePixelFormat_Operations *ops;
02446         uint8 *fmp,*fmp2,*top;
02447 
02448                 fmp = FmBits;
02449                 top = ToBits;
02450 
02451                 ops = gePixelFormat_GetOperations(FmInfo->Format);
02452                 GetColor = ops->GetColor;
02453                 PutColor = ops->PutColor;
02454 
02455                 fmxtra *= bpp;
02456                 toxtra *= bpp;
02457 
02458                 if ( FmInfo->HasColorKey )
02459                 {
02460                 uint32 ck,p1,p2,p3,p4;
02461                 gePixelFormat_PixelGetter GetPixel;
02462                 gePixelFormat_PixelPutter PutPixel;
02463                 gePixelFormat_Decomposer DecomposePixel;
02464                 int32 PixelComposeRTable[]={0x696C6345,0x21657370};
02465 
02466                         assert( FmInfo->ColorKey == ToInfo->ColorKey );
02467                         ck = FmInfo->ColorKey;
02468                         GetPixel = ops->GetPixel;
02469                         PutPixel = ops->PutPixel;
02470                         DecomposePixel = ops->DecomposePixel;
02471                 
02472                         // {} the colorkey mip-subsampler
02473                         // slow; yet another reason to not use CK !
02474                         
02475                         for(y=toh;y--;)
02476                         {
02477                                 //y = 7, fmh = 15; y*2+1 == fmh : last line is not a double line
02478                                 if ( (y+y + 1) == fmh ) fmp2 = fmp;
02479                                 else                                    fmp2 = fmp + (FmInfo->Stride*bpp);
02480                                 for(x=tow;x--;)
02481                                 {
02482                                         p1 = GetPixel(&fmp);
02483                                         p2 = GetPixel(&fmp);
02484                                         p3 = GetPixel(&fmp2);
02485                                         p4 = GetPixel(&fmp2);
02486                                         if ( p1 == ck || p4 == ck )
02487                                         {
02488                                                 PutPixel(&top,ck);
02489                                         }
02490                                         else
02491                                         {
02492                                                 // p1 and p4 are not ck;
02493                                                 if ( p2 == ck ) p2 = p1;
02494                                                 if ( p3 == ck ) p3 = p4;
02495                                                 DecomposePixel(p1,&R1,&G1,&B1,&A1);
02496                                                 DecomposePixel(p2,&R2,&G2,&B2,&A2);
02497                                                 DecomposePixel(p3,&R3,&G3,&B3,&A3);
02498                                                 DecomposePixel(p4,&R4,&G4,&B4,&A4);
02499                                                 PutColor(&top,(R1+R2+R3+R4+2)>>2,(G1+G2+G3+G4+2)>>2,(B1+B2+B3+B4+2)>>2,(A1+A2+A3+A4+2)>>2);
02500                                         }
02501                                 }
02502                                 fmp += fmxtra;
02503                                 top += toxtra;
02504                         }
02505                 }
02506                 else
02507                 {
02508                         for(y=toh;y--;)
02509                         {
02510                                 //y = 7, fmh = 15; y*2+1 == fmh : last line is not a double line
02511                                 if ( (y+y + 1) == fmh ) fmp2 = fmp;
02512                                 else                                    fmp2 = fmp + (FmInfo->Stride*bpp);
02513                                 for(x=tow;x--;)
02514                                 {
02515                                         GetColor(&fmp ,&R1,&G1,&B1,&A1);
02516                                         GetColor(&fmp ,&R2,&G2,&B2,&A2);
02517                                         GetColor(&fmp2,&R3,&G3,&B3,&A3);
02518                                         GetColor(&fmp2,&R4,&G4,&B4,&A4);
02519                                         PutColor(&top,(R1+R2+R3+R4+2)>>2,(G1+G2+G3+G4+2)>>2,(B1+B2+B3+B4+2)>>2,(A1+A2+A3+A4+2)>>2);
02520                                 }
02521                                 fmp += fmxtra;
02522                                 top += toxtra;
02523                         }
02524                 }
02525 
02526                 assert( top == (((uint8 *)ToBits) + ToInfo->Stride * ToInfo->Height * bpp ) );
02527                 assert( fmp == (((uint8 *)FmBits) + FmInfo->Stride * ToInfo->Height * 2 * bpp ) );
02528         }
02529         else if ( fmstep == 2 && gePixelFormat_HasPalette(FmInfo->Format) )
02530         {
02531         int R,G,B;
02532         uint8 *fmp,*fmp2,*top;
02533         uint8 paldata[768],*palptr;
02534         int p;
02535         palInfo * PalInfo;
02536 
02537                 assert(bpp == 1);
02538                 assert(FmInfo->Palette);
02539 
02540                 if ( ! geBitmap_Palette_GetData(FmInfo->Palette,paldata,GE_PIXELFORMAT_24BIT_RGB,256) )
02541                         return GE_FALSE;
02542 
02543                 if ( ! (PalInfo = closestPalInit(paldata)) )
02544                         return GE_FALSE;
02545 
02546                 fmp = FmBits;
02547                 top = ToBits;
02548 
02549                 // @@ colorkey?
02550 
02551                 for(y=toh;y--;)
02552                 {
02553                         //y = 7, fmh = 15; y*2+1 == fmh : last line is not a double line
02554                         if ( (y*2 + 1) == fmh ) fmp2 = fmp;
02555                         else                                    fmp2 = fmp + (FmInfo->Stride*bpp);
02556 
02557                         for(x=tow;x--;)
02558                         {
02559                                 p = *fmp++;
02560                                 palptr = paldata + p*3;
02561                                 R  = palptr[0]; G  = palptr[1]; B  = palptr[2]; 
02562                                 p = *fmp++;
02563                                 palptr = paldata + p*3;
02564                                 R += palptr[0]; G += palptr[1]; B += palptr[2]; 
02565                                 p = *fmp2++;
02566                                 palptr = paldata + p*3;
02567                                 R += palptr[0]; G += palptr[1]; B += palptr[2]; 
02568                                 p = *fmp2++;
02569                                 palptr = paldata + p*3;
02570                                 R += palptr[0]; G += palptr[1]; B += palptr[2]; 
02571 
02572                                 R = (R+2)>>2;
02573                                 G = (G+2)>>2;
02574                                 B = (B+2)>>2;
02575 
02576                                 p = closestPal(R,G,B,PalInfo);
02577                                 *top++ = p;
02578                         }
02579                         fmp += fmxtra;
02580                         top += toxtra;
02581                 }
02582 
02583                 closestPalFree(PalInfo);
02584 
02585                 assert( top == (((uint8 *)ToBits) + ToInfo->Stride * ToInfo->Height * bpp ) );
02586                 assert( fmp == (((uint8 *)FmBits) + FmInfo->Stride * ToInfo->Height * 2 * bpp ) );
02587         }
02588         else
02589         {
02590                 // we just sub-sample to make mips, so we don't have to
02591                 //      know anything about pixelformat.
02592                 // (btw this spoils the whole point of mips, so we might as well kill the mip!)
02593 
02594                 //{} Blend correctly !?
02595 
02596                 switch( bpp )
02597                 {
02598                         default:
02599                         {
02600                                 return GE_FALSE;
02601                         }
02602                         case 1:
02603                         {
02604                                 uint8 *fmp,*top;
02605                                 fmp = FmBits;
02606                                 top = ToBits;
02607                                 for(y=toh;y--;)
02608                                 {
02609                                         for(x=tow;x--;)
02610                                         {
02611                                                 *top++ = *fmp;
02612                                                 fmp += fmstep;
02613                                         }
02614                                         fmp += fmxtra;
02615                                         top += toxtra;
02616                                 }
02617                                 break;
02618                         }
02619                         case 2:
02620                         {
02621                                 uint16 *fmp,*top;
02622                                 fmp = FmBits;
02623                                 top = ToBits;
02624                                 for(y=toh;y--;)
02625                                 {
02626                                         for(x=tow;x--;)
02627                                         {
02628                                                 *top++ = *fmp;
02629                                                 fmp += fmstep;
02630                                         }
02631                                         fmp += fmxtra;
02632                                         top += toxtra;
02633                                 }
02634                                 break;
02635                         }
02636                         case 4:
02637                         {
02638                                 uint32 *fmp,*top;
02639                                 fmp = FmBits;
02640                                 top = ToBits;
02641                                 for(y=toh;y--;)
02642                                 {
02643                                         for(x=tow;x--;)
02644                                         {
02645                                                 *top++ = *fmp;
02646                                                 fmp += fmstep;
02647                                         }
02648                                         fmp += fmxtra;
02649                                         top += toxtra;
02650                                 }
02651                                 break;
02652                         }
02653                         case 3:
02654                         {
02655                                 uint8 *fmp,*top;
02656                                 fmp = FmBits;
02657                                 top = ToBits;
02658                                 fmstep = (fmstep - 1) * 3;
02659                                 fmxtra *= 3;
02660                                 toxtra *= 3;
02661                                 for(y=toh;y--;)
02662                                 {
02663                                         for(x=tow;x--;)
02664                                         {
02665                                                 *top++ = *fmp++;
02666                                                 *top++ = *fmp++;
02667                                                 *top++ = *fmp++;
02668                                                 fmp += fmstep;
02669                                         }
02670                                         fmp += fmxtra;
02671                                         top += toxtra;
02672                                 }
02673                                 break;
02674                         }
02675                 }
02676         }
02677 
02678 return GE_TRUE;
02679 }
02680 
02681 GENESISAPI geBoolean GENESISCC geBitmap_ClearMips(geBitmap *Bmp)
02682 {
02683 int mip;
02684 DRV_Driver * Driver;
02685 
02686         // WARNING ! This destroys any mips!
02687 
02688         assert( geBitmap_IsValid(Bmp) );
02689 
02690         if ( Bmp->LockOwner || Bmp->LockCount || Bmp->DataOwner )
02691                 return GE_FALSE;
02692 
02693         if ( Bmp->SeekMipCount == 0 && Bmp->Info.MaximumMip == 0 )
02694                 return GE_TRUE;
02695 
02696         Driver = Bmp->Driver;
02697         if ( Driver )
02698         {
02699                 if ( ! geBitmap_DetachDriver(Bmp,GE_TRUE) )
02700                         return GE_FALSE;
02701         }
02702         assert(Bmp->Driver == NULL);
02703 
02704         mip = Bmp->Info.MinimumMip;
02705         if ( mip == 0 ) 
02706                 mip++;
02707 
02708         Bmp->SeekMipCount = mip;
02709 
02710         for( ; mip <= Bmp->Info.MaximumMip ; mip++)
02711         {
02712                 if ( Bmp->Data[mip] )
02713                 {
02714                         geRam_Free( Bmp->Data[mip] );
02715                         Bmp->Data[mip] = NULL;
02716                 }
02717         }
02718 
02719         Bmp->Info.MaximumMip = Bmp->Info.MinimumMip;
02720 
02721         if ( Driver )
02722         {
02723                 if ( ! geBitmap_AttachToDriver(Bmp,Driver,0) )
02724                         return GE_FALSE;
02725         }
02726 
02727 return GE_TRUE;
02728 }
02729 
02730 GENESISAPI geBoolean    GENESISCC       geBitmap_SetMipCount(geBitmap *Bmp,int Count)
02731 {
02732 DRV_Driver * Driver;
02733 
02734         assert( geBitmap_IsValid(Bmp) );
02735 
02736         if ( Bmp->LockOwner || Bmp->LockCount || Bmp->DataOwner )
02737                 return GE_FALSE;
02738 
02739         if ( Bmp->SeekMipCount == Count )
02740         {
02741                 Driver = NULL;
02742         }
02743         else
02744         {
02745                 Driver = Bmp->Driver;
02746                 if ( Driver )
02747                 {
02748                         if ( ! geBitmap_DetachDriver(Bmp,GE_TRUE) )
02749                                 return GE_FALSE;
02750                 }
02751                 assert(Bmp->Driver == NULL);
02752         }
02753 
02754         Bmp->SeekMipCount = Count;
02755 
02756 // @@ don't do this ?
02757 //      if ( Bmp->Info.MaximumMip < (Count-1) )
02758 //              geBitmap_MakeSystemMips(Bmp,0,Count-1);
02759 //
02760 
02761         if ( Driver )
02762         {
02763                 if ( ! geBitmap_AttachToDriver(Bmp,Driver,0) )
02764                         return GE_FALSE;
02765         }
02766 
02767 return GE_TRUE;
02768 }
02769 
02770 geBoolean geBitmap_MakeSystemMips(geBitmap *Bmp,int low,int high)
02771 {
02772 int mip;
02773 
02774         assert( geBitmap_IsValid(Bmp) );
02775 
02776         // this is that CreateLockFromMip uses to make its new data
02777 
02778         if ( Bmp->LockOwner )
02779                 Bmp = Bmp->LockOwner;
02780 //      if ( Bmp->LockCount > 0 )
02781 //              return GE_FALSE;
02782         if ( Bmp->DataOwner )
02783                 return GE_FALSE;
02784 
02785         // {} for compressed data, just don't make mips and say we did!
02786         if ( gePixelFormat_BytesPerPel(Bmp->Info.Format) < 1 )
02787                 return GE_TRUE;
02788 
02789         if ( low < 0 || high >= MAXMIPLEVELS || low > high )
02790                 return GE_FALSE;
02791 
02792         for( mip = low; mip <= high; mip++)
02793         {
02794                 if ( ! Bmp->Data[mip] )
02795                 {
02796                         if ( ! geBitmap_AllocSystemMip(Bmp,mip) )
02797                                 return GE_FALSE;
02798         
02799                         if ( mip != 0 )
02800                         {
02801                                 if ( ! geBitmap_UpdateMips_System(Bmp,mip-1,mip) )
02802                                         return GE_FALSE;
02803                         }
02804                 }
02805         }
02806 
02807         Bmp->Info.MinimumMip = min(Bmp->Info.MinimumMip,low);
02808         Bmp->Info.MaximumMip = max(Bmp->Info.MaximumMip,high);
02809 
02810 return GE_TRUE;
02811 }
02812 
02813 /*}{ ******* Miscellany ***********/
02814 
02815 GENESISAPI uint32 GENESISCC geBitmap_MipBytes(const geBitmap *Bmp,int mip)
02816 {
02817 uint32 bytes;
02818         if ( ! Bmp )
02819                 return 0;
02820         bytes = gePixelFormat_BytesPerPel(Bmp->Info.Format) * 
02821                                                 SHIFT_R_ROUNDUP(Bmp->Info.Stride,mip) *
02822                                                 SHIFT_R_ROUNDUP(Bmp->Info.Height,mip);
02823 return bytes;
02824 }
02825 
02826 GENESISAPI geBoolean GENESISCC geBitmap_GetInfo(const geBitmap *Bmp, geBitmap_Info *Info, geBitmap_Info *SecondaryInfo)
02827 {
02828         assert( geBitmap_IsValid(Bmp) );
02829 
02830         assert(Info);
02831 
02832         if ( Bmp->DriverHandle )
02833         {
02834                 *Info = Bmp->DriverInfo;
02835         }
02836         else
02837         {
02838                 *Info = Bmp->Info;
02839         }
02840 
02841         if ( SecondaryInfo )
02842                 *SecondaryInfo = Bmp->Info;
02843 
02844         return GE_TRUE;
02845 }
02846 
02847 geBoolean geBitmap_MakeDriverLockInfo(geBitmap *Bmp,int mip,geBitmap_Info *Into)
02848 {
02849 geRDriver_THandleInfo TInfo;
02850 
02851         // MakeDriverLockInfo also doesn't full out the full info, so it must be a valid info first!
02852         // Bmp also gets some stuff written into him.
02853 
02854         assert(Bmp && Into); // not necessarily valid
02855 
02856         if ( ! Bmp->DriverHandle || ! Bmp->Driver || mip < Bmp->DriverInfo.MinimumMip || mip > Bmp->DriverInfo.MaximumMip )
02857                 return GE_FALSE;
02858 
02859         if ( ! Bmp->Driver->THandle_GetInfo(Bmp->DriverHandle,mip,&TInfo) )
02860         {
02861                 geErrorLog_AddString(-1,"MakeDriverLockInfo : THandle_GetInfo", NULL);
02862                 return GE_FALSE;
02863         }
02864 
02865         Bmp->DriverMipLock      = mip;
02866         Bmp->DriverFlags        = TInfo.PixelFormat.Flags;
02867 
02868         Into->Width                     = TInfo.Width;
02869         Into->Height            = TInfo.Height;
02870         Into->Stride            = TInfo.Stride;
02871         Into->Format            = TInfo.PixelFormat.PixelFormat;
02872         Into->ColorKey          = TInfo.ColorKey;
02873 
02874         if ( TInfo.Flags & RDRIVER_THANDLE_HAS_COLORKEY )
02875                 Into->HasColorKey = GE_TRUE;
02876         else
02877                 Into->HasColorKey = GE_FALSE;
02878 
02879         Into->MinimumMip = Into->MaximumMip = mip;
02880 
02881         if ( gePixelFormat_HasPalette(Into->Format) && Into->Palette && Into->Palette->HasColorKey )
02882         {
02883                 Into->HasColorKey = GE_TRUE;
02884                 Into->ColorKey = Into->Palette->ColorKeyIndex;
02885         }
02886 
02887 return GE_TRUE;
02888 }
02889 
02890 GENESISAPI int GENESISCC        geBitmap_Width(const geBitmap *Bmp)
02891 {
02892         assert(Bmp);
02893 return(Bmp->Info.Width);
02894 }
02895 
02896 GENESISAPI int GENESISCC        geBitmap_Height(const geBitmap *Bmp)
02897 {
02898         assert(Bmp);
02899 return(Bmp->Info.Height);
02900 }
02901 
02902 GENESISAPI geBoolean GENESISCC geBitmap_Blit(const geBitmap *Src, int SrcPositionX, int SrcPositionY,
02903                                                 geBitmap *Dst, int DstPositionX, int DstPositionY,
02904                                                 int SizeX, int SizeY )
02905 {
02906         assert( geBitmap_IsValid(Src) );
02907         assert( geBitmap_IsValid(Dst) );
02908         return geBitmap_BlitMipRect(Src,0,SrcPositionX,SrcPositionY,
02909                                                                 Dst,0,DstPositionX,DstPositionY,
02910                                                                 SizeX,SizeY);
02911 }
02912 
02913 GENESISAPI geBoolean GENESISCC geBitmap_BlitBitmap(const geBitmap * Src, geBitmap * Dst )
02914 {
02915         assert( geBitmap_IsValid(Src) );
02916         assert( geBitmap_IsValid(Dst) );
02917         assert( Src != Dst );
02918         return geBitmap_BlitMipRect(Src,0,0,0,Dst,0,0,0,-1,-1);
02919 }
02920 
02921 GENESISAPI geBoolean GENESISCC geBitmap_BlitBestMip(const geBitmap * Src, geBitmap * Dst )
02922 {
02923 int Width,Mip;
02924         assert( geBitmap_IsValid(Src) );
02925         assert( geBitmap_IsValid(Dst) );
02926         assert( Src != Dst );
02927         for(Mip=0;      (Width = SHIFT_R_ROUNDUP(Src->Info.Width,Mip)) > Dst->Info.Width ; Mip++) ;
02928         return geBitmap_BlitMipRect(Src,Mip,0,0,Dst,0,0,0,-1,-1);
02929 }
02930 
02931 GENESISAPI geBoolean GENESISCC geBitmap_BlitMip(const geBitmap * Src, int SrcMip, geBitmap * Dst, int DstMip )
02932 {
02933         assert( geBitmap_IsValid(Src) );
02934         assert( geBitmap_IsValid(Dst) );
02935         return geBitmap_BlitMipRect(Src,SrcMip,0,0,Dst,DstMip,0,0,-1,-1);
02936 }
02937 
02938 geBoolean geBitmap_BlitMipRect(const geBitmap * Src, int SrcMip, int SrcX,int SrcY,
02939                                                                          geBitmap * Dst, int DstMip, int DstX,int DstY,
02940                                                         int SizeX,int SizeY)
02941 {
02942 geBitmap * SrcLock=NULL,* DstLock=NULL;
02943 geBoolean SrcUnLock,DstUnLock;
02944 geBitmap_Info *SrcLockInfo,*DstLockInfo;
02945 uint8 *SrcBits,*DstBits;
02946         
02947         assert(Src && Dst);
02948         assert( Src != Dst );
02949         // <> if Src == Dst we could still do this, but we assert SrcMip != DstMip & be smart
02950 
02951         SrcUnLock = DstUnLock = GE_FALSE;
02952 
02953         if ( Src->LockOwner )
02954         {
02955                 assert( Src->LockOwner->LockCount );
02956                 if ( SrcMip != 0 )
02957                 {
02958                         geErrorLog_AddString(-1,"BlitMipRect : Src is a lock and mip != 0", NULL);
02959                         goto fail;
02960                 }
02961 
02962                 SrcLock = (geBitmap *)Src;
02963         }
02964         else
02965         {
02966                 if ( ! geBitmap_LockForReadNative((geBitmap *)Src,&SrcLock,SrcMip,SrcMip) )
02967                 {
02968                         geErrorLog_AddString(-1,"BlitMipRect : LockForReadNative", NULL);
02969                         goto fail;
02970                 }
02971                 SrcUnLock = GE_TRUE;
02972         }
02973 
02974         if ( Dst->LockOwner )
02975         {
02976                 if ( DstMip != 0 )
02977                         goto fail;
02978 //              if ( Dst->LockOwner->LockCount >= 0 )
02979 //                      goto fail;
02980 //              {} can't check this, cuz we use _BlitMip to create locks for read
02981                 DstLock = Dst;
02982         }
02983         else
02984         {
02985                 if ( ! geBitmap_LockForWrite(Dst,&DstLock,DstMip,DstMip) )
02986                 {
02987                         geErrorLog_AddString(-1,"BlitMipRect : LockForWrite", NULL);
02988                         goto fail;
02989                 }
02990                 DstUnLock = GE_TRUE;
02991         }
02992 
02993         Src = Dst = NULL;
02994 
02995         if ( SrcLock->DriverHandle ) 
02996                 SrcLockInfo = &(SrcLock->DriverInfo);
02997         else
02998                 SrcLockInfo = &(SrcLock->Info);
02999 
03000         if ( DstLock->DriverHandle ) 
03001                 DstLockInfo = &(DstLock->DriverInfo);
03002         else
03003                 DstLockInfo = &(DstLock->Info);
03004 
03005         if ( ! (SrcBits = geBitmap_GetBits(SrcLock)) || 
03006                  ! (DstBits = geBitmap_GetBits(DstLock)) )
03007         {
03008                 geErrorLog_AddString(-1,"BlitMipRect : GetBits", NULL);
03009                 goto fail;
03010         }
03011 
03012         if ( SizeX < 0 )
03013                 SizeX = min(SrcLockInfo->Width,DstLockInfo->Width);
03014         if ( SizeY < 0 )
03015                 SizeY = min(SrcLockInfo->Height,DstLockInfo->Height);
03016 
03017         if (( (SrcX + SizeX) > SrcLockInfo->Width ) ||
03018                 ( (SrcY + SizeY) > SrcLockInfo->Height) ||
03019                 ( (DstX + SizeX) > DstLockInfo->Width ) ||
03020                 ( (DstY + SizeY) > DstLockInfo->Height))
03021         {
03022                 geErrorLog_AddString(-1,"BlitMipRect : dimensions bad", NULL);
03023                 goto fail;
03024         }
03025 
03026         SrcBits += gePixelFormat_BytesPerPel(SrcLockInfo->Format) * ( SrcY * SrcLockInfo->Stride + SrcX );
03027         DstBits += gePixelFormat_BytesPerPel(DstLockInfo->Format) * ( DstY * DstLockInfo->Stride + DstX );
03028 
03029         // _BlitMipRect : made palette
03030         if ( ! geBitmap_BlitData(       SrcLockInfo,SrcBits,SrcLock,
03031                                                                 DstLockInfo,DstBits,DstLock,
03032                                                                 SizeX,SizeY) )
03033         {
03034                 goto fail;
03035         }
03036 
03037         if ( SrcUnLock ) geBitmap_UnLock(SrcLock);
03038         if ( DstUnLock ) geBitmap_UnLock(DstLock);
03039 
03040         return GE_TRUE;
03041 
03042         fail:
03043 
03044         if ( SrcUnLock ) geBitmap_UnLock(SrcLock);
03045         if ( DstUnLock ) geBitmap_UnLock(DstLock);
03046 
03047         return GE_FALSE;
03048 }
03049 
03050 GENESISAPI geBoolean    GENESISCC       geBitmap_SetFormatMin(geBitmap *Bmp,gePixelFormat NewFormat)
03051 {
03052 geBitmap_Palette * Pal;
03053 
03054         assert(geBitmap_IsValid(Bmp));
03055 
03056         Pal = geBitmap_GetPalette(Bmp);
03057         if ( Bmp->Info.HasColorKey )
03058         {
03059         uint32 CK=0;
03060                 if ( gePixelFormat_IsRaw(NewFormat) )
03061                 {
03062                         if ( gePixelFormat_IsRaw(Bmp->Info.Format) )
03063                         {
03064                                 CK = gePixelFormat_ConvertPixel(Bmp->Info.Format,Bmp->Info.ColorKey,NewFormat);
03065                         }
03066                         else if ( gePixelFormat_HasPalette(Bmp->Info.Format) )
03067                         {
03068                                 assert(Pal);
03069                                 geBitmap_Palette_GetEntry(Pal,Bmp->Info.ColorKey,&CK);
03070                                 CK = gePixelFormat_ConvertPixel(Pal->Format,CK,NewFormat);
03071                                 if ( ! CK ) CK = 1;
03072                         }
03073                 }
03074                 else
03075                 {
03076                         if ( gePixelFormat_HasPalette(NewFormat) )
03077                         {
03078                                 CK = 255;
03079                         }
03080                         else
03081                         {
03082                                 CK = 1;
03083                         }
03084                 }
03085                 
03086                 return geBitmap_SetFormat(Bmp,NewFormat,GE_TRUE,CK,Pal);
03087         }
03088         else
03089         {
03090                 return geBitmap_SetFormat(Bmp,NewFormat,GE_FALSE,0,Pal);
03091         }
03092 }
03093 
03094 GENESISAPI geBoolean GENESISCC geBitmap_SetFormat(geBitmap *Bmp, 
03095                                                         gePixelFormat NewFormat, 
03096                                                         geBoolean HasColorKey, uint32 ColorKey,
03097                                                         const geBitmap_Palette *Palette )
03098 {
03099         assert( geBitmap_IsValid(Bmp) );
03100 
03101         if ( Bmp->LockOwner || Bmp->LockCount || Bmp->DataOwner )
03102         {
03103                 geErrorLog_AddString(-1,"SetFormat : not an original bitmap", NULL);
03104                 return GE_FALSE;        
03105         }
03106         // can't do _SetFormat on a locked mip, cuz it would change the size of all the locked mips = no good
03107 
03108         // always affects the non-Driver copy
03109 
03110         if ( NewFormat == GE_PIXELFORMAT_WAVELET )
03111         {
03112                 geErrorLog_AddString(-1,"Genesis3D 1.0 does not support Wavelet Images",NULL);
03113                 return GE_FALSE;
03114         }
03115 
03116         if ( NewFormat == Bmp->Info.Format )
03117         {
03118                 // but not wavelet
03119 
03120                 if ( gePixelFormat_HasPalette(NewFormat) && Palette )
03121                 {
03122                         if ( ! geBitmap_SetPalette(Bmp,(geBitmap_Palette *)Palette) )
03123                                 return GE_FALSE;
03124                 }
03125 
03126                 if ( (! HasColorKey )
03127                         || ( HasColorKey && Bmp->Info.HasColorKey && ColorKey == Bmp->Info.ColorKey ) )
03128                 {
03129                         Bmp->Info.HasColorKey = HasColorKey;
03130                         Bmp->Info.ColorKey = ColorKey;
03131                         return GE_TRUE;
03132                 }
03133                 else
03134                 {
03135                 geBitmap_Info OldInfo;
03136 
03137                         OldInfo = Bmp->Info;
03138 
03139                         assert(HasColorKey);
03140 
03141                         // just change the colorkey
03142 
03143                         Bmp->Info.HasColorKey = HasColorKey;
03144                         Bmp->Info.ColorKey = ColorKey;
03145 
03146                         if ( Bmp->Data[Bmp->Info.MinimumMip] == NULL )
03147                                 return GE_TRUE;
03148                 
03149                         assert(Bmp->Info.MinimumMip == 0); //{} this is just out of laziness
03150 
03151                         // _SetFormat : same format
03152                         if ( ! geBitmap_BlitData(       &OldInfo,               Bmp->Data[Bmp->Info.MinimumMip], NULL,
03153                                                                                 &(Bmp->Info),   Bmp->Data[Bmp->Info.MinimumMip], NULL,
03154                                                                                 Bmp->Info.Width, Bmp->Info.Height) )
03155                         {
03156                                 return GE_FALSE;
03157                         }
03158 
03159                         return GE_TRUE;
03160                 }
03161         }
03162         else
03163         {
03164         geBitmap_Info OldInfo;
03165         int OldBPP,NewBPP;
03166         int OldMaxMips;
03167         DRV_Driver * Driver;
03168 
03169                 if ( gePixelFormat_HasPalette(NewFormat) )
03170                 {
03171                         if ( Palette )
03172                         {
03173                                 if ( ! geBitmap_SetPalette(Bmp,(geBitmap_Palette *)Palette) )
03174                                         return GE_FALSE;
03175                         }
03176                         else
03177                         {
03178                                 if ( ! geBitmap_GetPalette(Bmp) && ! gePixelFormat_HasPalette(Bmp->Info.Format) )
03179                                 {
03180                                 geBitmap_Palette *NewPal;
03181                                         NewPal = geBitmap_Palette_CreateFromBitmap(Bmp,GE_FALSE);
03182                                         if ( ! NewPal )
03183                                         {
03184                                                 geErrorLog_AddString(-1,"_SetFormat : createPaletteFromBitmap failed", NULL);
03185                                                 return GE_FALSE;
03186                                         }
03187                                         if ( ! geBitmap_SetPalette(Bmp,NewPal) )
03188                                                 return GE_FALSE;
03189                                         geBitmap_Palette_Destroy(&NewPal);
03190                                 }
03191                         }
03192                 }
03193 
03194                 Driver = Bmp->Driver;
03195                 if ( Driver )
03196                         if ( ! geBitmap_DetachDriver(Bmp,GE_TRUE) )
03197                                 return GE_FALSE;
03198 
03199                 OldBPP = gePixelFormat_BytesPerPel(Bmp->Info.Format);
03200                 NewBPP = gePixelFormat_BytesPerPel(NewFormat);
03201 
03202                 OldInfo = Bmp->Info;
03203                 Bmp->Info.Format = NewFormat;
03204                 Bmp->Info.HasColorKey = HasColorKey;
03205                 Bmp->Info.ColorKey = ColorKey;
03206 
03207                 // {} this is not very polite; we do restore them later, though...
03208                 OldMaxMips = max(Bmp->Info.MaximumMip,Bmp->DriverInfo.MaximumMip);
03209                 geBitmap_ClearMips(Bmp);                
03210 
03211                 if ( Bmp->Data[Bmp->Info.MinimumMip] == NULL && 
03212                                 Bmp->DriverHandle == NULL )
03213                         return GE_TRUE;
03214 
03215                 if ( OldBPP == NewBPP )
03216                 {
03217                 geBitmap * Lock;
03218                 void * Bits;
03219                         // can work in place
03220                         if ( ! geBitmap_LockForWrite(Bmp,&Lock,0,0) )
03221                                 return GE_FALSE;
03222 
03223                         if ( ! (Bits = geBitmap_GetBits(Lock)) )
03224                         {
03225                                 geBitmap_UnLock(Lock);
03226                                 return GE_FALSE;
03227                         }
03228 
03229                         // _SetFormat : new format
03230                         if ( ! geBitmap_BlitData(       &OldInfo,               Bits, Lock,
03231                                                                                 &(Lock->Info),  Bits, Lock,
03232                                                                                 Lock->Info.Width, Lock->Info.Height) )
03233                         {
03234                                 geBitmap_UnLock(Lock);
03235                                 return GE_FALSE;
03236                         }
03237 
03238                         geBitmap_UnLock(Lock);
03239                 }
03240                 else // NewFormat is raw && != OldFormat
03241                 {
03242                 geBitmap OldBmp;
03243                 geBitmap *Lock,*SrcLock;
03244                 void *Bits,*OldBits;
03245 
03246                         OldBmp = *Bmp;
03247                         OldBmp.Info = OldInfo;
03248 
03249                         // clear out the Bmp for putting the new format in
03250                         Bmp->Info.Stride = Bmp->Info.Width;
03251                         Bmp->Data[0] = NULL;
03252                         Bmp->Alpha = NULL;
03253 
03254                         if ( ! geBitmap_AllocSystemMip(Bmp,0) )
03255                                 return GE_FALSE;
03256 
03257                         if ( ! geBitmap_LockForReadNative(&OldBmp,&SrcLock,0,0) )
03258                                 return GE_FALSE;
03259 
03260                         if ( ! geBitmap_LockForWrite(Bmp,&Lock,0,0) )
03261                                 return GE_FALSE;
03262 
03263                         if ( ! (Bits = geBitmap_GetBits(Lock)) )
03264                         {
03265                                 geBitmap_UnLock(Lock);
03266                                 return GE_FALSE;
03267                         }
03268                         if ( ! (OldBits = geBitmap_GetBits(SrcLock)) )
03269                         {
03270                                 geBitmap_UnLock(Lock);
03271                                 return GE_FALSE;
03272                         }
03273 
03274                         // _SetFormat : new format
03275                         if ( ! geBitmap_BlitData(       &OldInfo,               OldBits,                SrcLock,
03276                                                                                 &(Lock->Info),  Bits,                   Lock,
03277                                                                                 Lock->Info.Width, Lock->Info.Height) )
03278                         {
03279                                 // try to undo as well as possible
03280                                 return GE_FALSE;
03281                         }
03282                 
03283                         geBitmap_UnLock(Lock);
03284                         geBitmap_UnLock(SrcLock);
03285 
03286                         if ( OldBmp.Data[0] )
03287                         {
03288                                 geRam_Free(OldBmp.Data[0]);
03289                                 OldBmp.Data[0] = NULL;
03290                         }
03291 
03292                         if ( gePixelFormat_HasGoodAlpha(NewFormat) )
03293                         {
03294                                 geBitmap_Destroy(&(OldBmp.Alpha));
03295                         }
03296                         else
03297                         {
03298                                 Bmp->Alpha = OldBmp.Alpha;
03299                         }
03300                 }
03301 
03302                 {
03303                 int mip;
03304                         mip = Bmp->Info.MinimumMip;
03305                         while( mip < OldMaxMips )
03306                         {
03307                                 geBitmap_UpdateMips(Bmp,mip,mip+1);
03308                                 mip++;
03309                         }
03310                 }
03311 
03312                 if ( Driver )
03313                 {               
03314                         if ( ! geBitmap_AttachToDriver(Bmp,Driver,0) )
03315                                 return GE_FALSE;
03316                 }
03317         }
03318 
03319 return GE_TRUE;
03320 }
03321 
03322 GENESISAPI geBoolean GENESISCC geBitmap_SetColorKey(geBitmap *Bmp, geBoolean HasColorKey, uint32 ColorKey , geBoolean Smart)
03323 {
03324         assert( geBitmap_IsValid(Bmp) );
03325 
03326         if ( Bmp->LockOwner || Bmp->LockCount || Bmp->DataOwner )
03327         {
03328                 geErrorLog_AddString(-1,"SetColorKey : not an original bitmap", NULL);
03329                 return GE_FALSE;        
03330         }
03331 
03332         // see comments in SetFormat
03333 
03334         if ( Bmp->DriverHandle )
03335                 geBitmap_Update_DriverToSystem(Bmp);
03336 
03337         if ( HasColorKey && 
03338                         ((uint32)ColorKey>>1) >= ((uint32)1<<(gePixelFormat_BytesPerPel(Bmp->Info.Format)*8 - 1)) )
03339         {
03340                 geErrorLog_AddString(-1,"geBitmap_SetColorKey : invalid ColorKey pixel!", NULL);
03341                 return GE_FALSE;
03342         }
03343         if ( HasColorKey && gePixelFormat_HasAlpha(Bmp->Info.Format) )
03344         {
03345                 geErrorLog_AddString(-1,"geBitmap_SetColorKey : non-fatal : Alpha and ColorKey together won't work right", NULL);
03346         }
03347 
03348         if ( HasColorKey && Smart && Bmp->Data[0] )
03349         {
03350                 Bmp->Info.HasColorKey = GE_TRUE;
03351                 Bmp->Info.ColorKey = ColorKey;
03352                 if ( ! geBitmap_UsesColorKey(Bmp) )
03353                 {
03354                         Bmp->Info.HasColorKey = GE_FALSE;
03355                         Bmp->Info.ColorKey = 1;
03356                 }
03357         }
03358         else
03359         {
03360                 Bmp->Info.HasColorKey = HasColorKey;
03361                 Bmp->Info.ColorKey = ColorKey;
03362         }
03363 
03364         if ( Bmp->DriverHandle )
03365                 geBitmap_Update_SystemToDriver(Bmp);
03366 
03367 return GE_TRUE;
03368 }
03369 
03370 geBoolean geBitmap_UsesColorKey(const geBitmap * Bmp)
03371 {
03372 void * Bits;
03373 const gePixelFormat_Operations * ops;
03374 int x,y,w,h,s;
03375 uint32 pel,ColorKey;
03376 
03377         if ( ! Bmp->Info.HasColorKey )
03378                 return GE_FALSE;
03379 
03380         if ( ! Bmp->Data[0] )
03381         {
03382                 geErrorLog_AddString(-1,"UsesColorKey : no data!", NULL);
03383                 return GE_TRUE;
03384         }
03385 
03386         assert( Bmp->Info.MinimumMip == 0 );
03387 
03388         Bits = Bmp->Data[0];
03389         ops = gePixelFormat_GetOperations(Bmp->Info.Format);
03390         assert(ops);
03391 
03392         w = Bmp->Info.Width;
03393         h = Bmp->Info.Height;
03394         s = Bmp->Info.Stride;
03395 
03396         ColorKey = Bmp->Info.ColorKey;
03397 
03398         switch(ops->BytesPerPel)
03399         {
03400                 case 0:
03401                         geErrorLog_AddString(-1,"UsesColorKey : invalid format", NULL);
03402                         return GE_TRUE;
03403 //Start Dec2001DCS - Added new case 3 below
03404 //              case 3:
03405 //                      #pragma message("Bitmap : UsesColorKey : no 24bit Smart ColorKey")
03406 //                      geErrorLog_AddString(-1,"UsesColorKey : no 24bit Smart ColorKey", NULL);
03407 //                      return GE_TRUE; 
03408 //End Dec2001DCS
03409                 case 1:
03410                 {
03411                 uint8 * ptr;
03412                         ptr = Bits;
03413                         for(y=h;y--;)
03414                         {
03415                                 for(x=w;x--;)
03416                                 {
03417                                         pel = *ptr++;
03418                                         if ( pel == ColorKey )
03419                                         {
03420                                                 return GE_TRUE; 
03421                                         }
03422                                 }
03423                                 ptr += (s-w);
03424                         }
03425                         break;
03426                 }
03427                 case 2:
03428                 {
03429                 uint16 * ptr;
03430                         ptr = Bits;
03431                         for(y=h;y--;)
03432                         {
03433                                 for(x=w;x--;)
03434                                 {
03435                                         pel = *ptr++;
03436                                         if ( pel == ColorKey )
03437                                         {
03438                                                 return GE_TRUE; 
03439                                         }
03440                                 }
03441                                 ptr += (s-w);
03442                         }
03443                         break;
03444                 }
03445 //Start Dec2001DCS - Added new case 3 
03446                 case 3:
03447                 {
03448                 uint8 * ptr;
03449          uint8   ckR, ckG, ckB;
03450 
03451          ckB = (uint8) (ColorKey & 0x000000ff);
03452          ckG = (uint8) ((ColorKey >> 8) & 0x000000ff);
03453          ckR = (uint8) ((ColorKey >> 16) & 0x000000ff);
03454                         ptr = Bits;
03455                         for(y=h;y--;)
03456                         {
03457                                 for(x=w;x--;)
03458                                 {
03459                                         if ((*ptr == ckR) && (*(ptr+1) == ckG) && (*(ptr+2) == ckB))
03460                                         {
03461                                                 return GE_TRUE; 
03462                                         }
03463                ptr += 3;
03464                                 }
03465                                 ptr += ((s-w)*3);
03466                         }
03467                         break;
03468                 }
03469 //End Dec2001DCS
03470                 case 4:
03471                 {
03472                 uint32 * ptr;
03473                         ptr = Bits;
03474                         for(y=h;y--;)
03475                         {
03476                                 for(x=w;x--;)
03477                                 {
03478                                         pel = *ptr++;
03479                                         if ( pel == ColorKey )
03480                                         {
03481                                                 return GE_TRUE; 
03482                                         }
03483                                 }
03484                                 ptr += (s-w);
03485                         }
03486                         break;
03487                 }
03488         }
03489 return GE_FALSE;
03490 }
03491 
03492 
03493 GENESISAPI geBoolean GENESISCC geBitmap_SetPalette(geBitmap *Bmp, const geBitmap_Palette *Palette)
03494 {
03495         assert(Bmp); // not nec. valid
03496         assert( geBitmap_Palette_IsValid(Palette) );
03497 
03498         if ( Bmp->LockOwner )
03499                 Bmp = Bmp->LockOwner;
03500 
03501 /* //{} breaks PalCreate
03502         if ( Bmp->LockCount > 0 || Bmp->DataOwner )
03503         {
03504                 geErrorLog_AddString(-1,"SetPalette : not an original bitmap", NULL);
03505                 return GE_FALSE;
03506         }
03507 */
03508 
03509         // warning : Bitmap_Blitdata calls us when it auto-creates a palette!
03510 
03511         // note that when we _SetPalette on a bitmap, all its write-locked children
03512         //      also get new palettes
03513 
03514         if ( Bmp->Info.Palette != Palette )
03515         {
03516                 // save the palette even if we're not palettized, for later use
03517                 if ( Palette->Driver )
03518                 {
03519                         if ( ! geBitmap_AllocPalette(Bmp,Palette->Format,NULL) )
03520                                 return GE_FALSE;
03521                         
03522                         if ( ! geBitmap_Palette_Copy(Palette,Bmp->Info.Palette) )
03523                                 return GE_FALSE;
03524                 }
03525                 else
03526                 {
03527                         if ( Bmp->Info.Palette )
03528                                 geBitmap_Palette_Destroy(&(Bmp->Info.Palette));
03529 
03530                         Bmp->Info.Palette = (geBitmap_Palette *)Palette;
03531                         geBitmap_Palette_CreateRef(Bmp->Info.Palette);
03532                 }
03533         }
03534 
03535         if ( gePixelFormat_HasPalette(Bmp->DriverInfo.Format) &&
03536                 Bmp->DriverInfo.Palette != Palette )
03537         {
03538                 if ( Palette->Driver == Bmp->Driver && 
03539                         ( ! Palette->HasColorKey || ! Bmp->DriverInfo.ColorKey ||
03540                                 (uint32)Palette->ColorKeyIndex == Bmp->DriverInfo.ColorKey ) )
03541                 {
03542                         if ( Bmp->DriverInfo.Palette )
03543                                 geBitmap_Palette_Destroy(&(Bmp->DriverInfo.Palette));
03544                         Bmp->DriverInfo.Palette = (geBitmap_Palette *)Palette;
03545                         geBitmap_Palette_CreateRef(Bmp->DriverInfo.Palette);
03546                 }
03547                 else if ( Bmp->DriverInfo.Palette )
03548                 {
03549                         if ( ! geBitmap_Palette_Copy(Palette,Bmp->DriverInfo.Palette) )
03550                                 return GE_FALSE;
03551                 }
03552                 else
03553                 {
03554                         if ( ! geBitmap_AllocPalette(Bmp,0,Bmp->Driver) )
03555                                 return GE_FALSE;
03556 
03557                         if ( ! geBitmap_Palette_Copy(Palette,Bmp->DriverInfo.Palette) )
03558                                 return GE_FALSE;
03559                 }
03560         }
03561 
03562         if ( Bmp->DriverHandle )
03563         {
03564                 // if one has pal and other doesn't this is real change!
03565                 if (    gePixelFormat_HasPalette(Bmp->Info.Format) &&
03566                           ! gePixelFormat_HasPalette(Bmp->DriverInfo.Format) )
03567                 {
03568                         // this over-rides any driver changes!
03569                         Bmp->DriverDataChanged = GE_FALSE;
03570                         if ( ! geBitmap_Update_SystemToDriver(Bmp) )
03571                                 return GE_FALSE;
03572                 }
03573                 else if ( ! gePixelFormat_HasPalette(Bmp->Info.Format) &&
03574                                 gePixelFormat_HasPalette(Bmp->DriverInfo.Format) )
03575                 {
03576                         Bmp->DriverDataChanged = GE_TRUE;
03577                 }
03578         }
03579 
03580         assert( geBitmap_IsValid(Bmp) );
03581 
03582 return GE_TRUE;
03583 }
03584 
03585 GENESISAPI geBitmap_Palette * GENESISCC geBitmap_GetPalette(const geBitmap *Bmp)
03586 {
03587         if ( ! Bmp ) return NULL;
03588 
03589         if ( Bmp->Driver && Bmp->DriverInfo.Palette )
03590         {
03591                 assert(Bmp->Info.Palette);
03592                 return Bmp->DriverInfo.Palette;
03593         }
03594 
03595         return Bmp->Info.Palette;
03596 }
03597 
03598 
03599 GENESISAPI geBitmap * GENESISCC geBitmap_GetAlpha(const geBitmap *Bmp)
03600 {
03601         if ( ! Bmp ) return NULL;
03602         return Bmp->Alpha;
03603 }
03604 
03605 GENESISAPI geBoolean GENESISCC geBitmap_SetAlpha(geBitmap *Bmp, const geBitmap *AlphaBmp)
03606 {
03607         assert( geBitmap_IsValid(Bmp) );
03608         
03609         if ( Bmp->LockOwner )
03610                 Bmp = Bmp->LockOwner;
03611         if ( Bmp->LockCount > 0 || Bmp->DataOwner )
03612         {
03613                 geErrorLog_AddString(-1,"SetAlpha : not an original bitmap", NULL);
03614                 return GE_FALSE;
03615         }
03616 
03617         if ( AlphaBmp == Bmp->Alpha )
03618                 return GE_TRUE;
03619 
03620         if ( Bmp->DriverHandle )
03621         {
03622                 geBitmap_Update_DriverToSystem(Bmp);
03623         }
03624 
03625         if ( Bmp->Alpha )
03626         {
03627                 geBitmap_Destroy(&(Bmp->Alpha));
03628         }
03629 
03630         Bmp->Alpha = (geBitmap *)AlphaBmp;
03631         if ( AlphaBmp )
03632         {
03633                 assert( geBitmap_IsValid(AlphaBmp) );
03634                 geBitmap_CreateRef(Bmp->Alpha);
03635         }
03636 
03637         if ( Bmp->DriverHandle )
03638         {
03639                 // upload the new alpha to the driver bitmap
03640                 geBitmap_Update_SystemToDriver(Bmp);
03641         }
03642 
03643 return GE_TRUE;
03644 }
03645 
03646 GENESISAPI geBoolean GENESISCC geBitmap_SetPreferredFormat(geBitmap *Bmp,gePixelFormat Format)
03647 {
03648 
03649         if ( Bmp->LockOwner )
03650                 Bmp = Bmp->LockOwner;
03651         if ( Bmp->LockCount > 0 || Bmp->DataOwner )
03652         {
03653                 geErrorLog_AddString(-1,"SetPrefferedFormat : not an original bitmap", NULL);
03654                 return GE_FALSE;
03655         }
03656 
03657         if ( Bmp->PreferredFormat != Format )
03658         {
03659         DRV_Driver * Driver;
03660                 Bmp->PreferredFormat = Format;
03661                 Driver = Bmp->Driver;
03662                 if ( Driver )
03663                 {
03664                         if ( ! geBitmap_DetachDriver(Bmp,GE_TRUE) )
03665                                 return GE_FALSE;
03666                         if ( ! geBitmap_AttachToDriver(Bmp,Driver,0) )
03667                                 return GE_FALSE;
03668                 }
03669         }
03670 
03671 return GE_TRUE;
03672 }
03673 
03674 GENESISAPI gePixelFormat GENESISCC geBitmap_GetPreferredFormat(const geBitmap *Bmp)
03675 {
03676         if ( ! Bmp ) return 0;
03677 return Bmp->PreferredFormat;
03678 }
03679 
03680 /*}{ ************** FILE I/O ************************/
03681 
03682 GENESISAPI geBitmap * GENESISCC geBitmap_CreateFromFileName(const geVFile *BaseFS,const char *Name)
03683 {
03684         geVFile * File;
03685         geBitmap * Bitmap;
03686 
03687 
03688         if ( BaseFS )
03689         {
03690                 File = geVFile_Open((geVFile *)BaseFS, Name, GE_VFILE_OPEN_READONLY);
03691         }
03692         else
03693         {
03694                 File = geVFile_OpenNewSystem(NULL,GE_VFILE_TYPE_DOS,Name,NULL,GE_VFILE_OPEN_READONLY);
03695         }
03696         if ( ! File )
03697                         return NULL;
03698         
03699         Bitmap = geBitmap_CreateFromFile(File);
03700         geVFile_Close(File);
03701                 
03702         return Bitmap;
03703 }
03704 
03705 GENESISAPI geBoolean GENESISCC geBitmap_WriteToFileName(const geBitmap * Bmp,const geVFile *BaseFS,const char *Name)
03706 {
03707 geVFile * File;
03708 geBoolean Ret;
03709 
03710         if ( BaseFS )
03711         {
03712                 File = geVFile_Open((geVFile *)BaseFS, Name, GE_VFILE_OPEN_CREATE);
03713         }
03714         else
03715         {
03716                 File = geVFile_OpenNewSystem(NULL,GE_VFILE_TYPE_DOS,Name,NULL,GE_VFILE_OPEN_CREATE);
03717         }
03718 
03719         if ( ! File )
03720                 return GE_FALSE;
03721 
03722         Ret = geBitmap_WriteToFile(Bmp,File);
03723 
03724         geVFile_Close(File);
03725 
03726 return Ret;
03727 }
03728 
03729 // GeBm Tag in 4 bytes {}
03730 typedef uint32                  geBmTag_t;
03731 #define GEBM_TAG                ((geBmTag_t)0x6D426547) // "GeBm"
03732 
03733 // version in a byte
03734 #define GEBM_VERSION                    (((uint32)GEBM_VERSION_MAJOR<<4) + (uint32)GEBM_VERSION_MINOR)
03735 #define VERSION_MAJOR(Version)  (((Version)>>4)&0x0F)
03736 #define VERSION_MINOR(Version)  ((Version)&0x0F)
03737 
03738 #define MIP_MASK                                (0xF)
03739 #define MIP_FLAG_COMPRESSED             (1<<4)
03740 #define MIP_FLAG_PAETH_FILTERED (1<<5)
03741 
03742 static geBoolean geBitmap_ReadFromBMP(geBitmap * Bmp,geVFile * F);
03743 // change QuestOfDreams
03744 static geBoolean geBitmap_IsTGA(geVFile * F);
03745 static geBoolean  geBitmap_ReadFromTGA(geBitmap * Bmp, geVFile * File);
03746 // end change QuestOfDreams
03747 GENESISAPI geBitmap * GENESISCC geBitmap_CreateFromFile(geVFile *F)
03748 {
03749         geBitmap *      Bmp;
03750         geBmTag_t Tag;
03751 
03752         assert(F);
03753 
03754         if ( ! geVFile_Read(F, &Tag, sizeof(Tag)) )
03755                 return NULL;
03756 
03757         Bmp = geBitmap_Create_Base();
03758         if ( ! Bmp )
03759                 return NULL;
03760 
03761         if ( Tag == GEBM_TAG )
03762         {
03763                 uint8 flags;
03764                 uint8 Version;
03765                 int mip;
03766 
03767                 // see WriteToFile for comments on the file format
03768 
03769                 if ( ! geVFile_Read(F, &Version, sizeof(Version)) )
03770                         goto fail;
03771 
03772                 if ( VERSION_MAJOR(Version) != VERSION_MAJOR(GEBM_VERSION) )
03773                 {
03774                         geErrorLog_AddString(-1,"CreateFromFile : incompatible GeBm version", NULL);    
03775                         goto fail;
03776                 }
03777 
03778                 if ( ! geBitmap_ReadInfo(Bmp,F) )
03779                         goto fail;
03780 
03781                 if ( Bmp->Info.Palette )
03782                 {
03783                         Bmp->Info.Palette = NULL;
03784                         if ( ! ( Bmp->Info.Palette = geBitmap_Palette_CreateFromFile(F)) )
03785                                 goto fail;
03786                 }
03787 
03788                 if ( Bmp->Info.Format == GE_PIXELFORMAT_WAVELET )
03789                 {
03790                         geErrorLog_AddString(-1,"Genesis3D 1.0 does not support Wavelet Images",NULL);
03791                 }
03792                 else
03793                 {
03794                         for(;;)
03795                         {
03796                                 if ( ! geVFile_Read(F, &flags, sizeof(flags)) )
03797                                         goto fail;
03798 
03799                                 mip = flags & MIP_MASK;
03800 
03801                                 if ( mip > Bmp->Info.MaximumMip )
03802                                         break;
03803 
03804                                 assert(mip >= Bmp->Info.MinimumMip );
03805                                 assert( Bmp->Info.Stride == Bmp->Info.Width );
03806 
03807                                 if ( ! geBitmap_AllocSystemMip(Bmp,mip) )
03808                                         goto fail;
03809 
03810                                 if ( flags & MIP_FLAG_COMPRESSED )
03811                                 {
03812                         #ifdef DO_LZ
03813                                 geVFile * LzF;
03814 
03815                                         LzF = geVFile_OpenNewSystem(F,GE_VFILE_TYPE_LZ,NULL,NULL,GE_VFILE_OPEN_READONLY);
03816                                         if ( ! LzF )
03817                                         {
03818                                                 geErrorLog_AddString(-1,"Bitmap_CreateFromFile : LZ File Open failed",NULL);
03819                                                 return GE_FALSE;
03820                                         }
03821 
03822                                         if ( ! geVFile_Read(LzF, Bmp->Data[mip], geBitmap_MipBytes(Bmp,mip) ) )
03823                                         {
03824                                                 geVFile_Close(LzF);
03825                                                 geErrorLog_AddString(-1,"Bitmap_CreateFromFile : LZ File Read failed",NULL);
03826                                                 return GE_FALSE;
03827                                         }
03828 
03829                                         if ( ! geVFile_Close(LzF) )
03830                                         {
03831                                                 geErrorLog_AddString(-1,"Bitmap_CreateFromFile : LZ File Close failed",NULL);
03832                                                 return GE_FALSE;
03833                                         }
03834                         #endif
03835                                 }
03836                                 else
03837                                 {
03838                                         if ( ! geVFile_Read(F, Bmp->Data[mip], geBitmap_MipBytes(Bmp,mip) ) )
03839                                                 goto fail;
03840                                 }
03841 
03842                                 if ( flags & MIP_FLAG_PAETH_FILTERED )
03843                                 {
03844                                         geErrorLog_AddString(-1,"Bitmap_CreateFromFile : Paeth Filter not supported in this version!",NULL);
03845                                         return GE_FALSE;
03846                                 }
03847 
03848                                 Bmp->Modified[mip] = GE_TRUE;
03849                         }
03850                 }
03851 
03852                 if( Bmp->Alpha )
03853                 {
03854                         if ( ! (Bmp->Alpha = geBitmap_CreateFromFile(F)) )
03855                                 goto fail;
03856                 }
03857         }       // end geBitmap reader
03858         else 
03859         {
03860                 if ( ! geVFile_Seek(F, - (int)sizeof(Tag), GE_VFILE_SEEKCUR) )
03861                         goto fail;
03862 
03863                 if ( (Tag&0xFFFF) == 0x4D42 )   // 'BM'
03864                 {
03865                 
03866                         if ( ! geBitmap_ReadFromBMP(Bmp,F) )
03867                                 goto fail;
03868                 }
03869                 else
03870                 {
03871                         
03872 // change QuestOfDreams
03873                         if (geBitmap_IsTGA(F))
03874                         {
03875                                 if( ! geBitmap_ReadFromTGA(Bmp, F))
03876                                         goto fail;
03877                         }
03878                         else 
03879                                 // geErrorLog_AddString(-1,"CreateFromFile : unknown format", NULL);
03880                                 goto fail;
03881 // end change QuestOfDreams
03882                 }
03883         }
03884 
03885         return Bmp;
03886 
03887 fail:
03888         assert(Bmp);
03889 
03890         geBitmap_Destroy(&Bmp);
03891         return NULL;
03892 }
03893 
03894 GENESISAPI geBoolean GENESISCC geBitmap_WriteToFile(const geBitmap *Bmp, geVFile *F)
03895 {
03896 geBmTag_t geBM_Tag;
03897 uint8  geBM_Version;
03898 uint8 flags;
03899 int mip;
03900         
03901         assert(Bmp && F);
03902         assert( geBitmap_IsValid(Bmp) );
03903 
03904         geBM_Tag = GEBM_TAG;
03905         geBM_Version = GEBM_VERSION;
03906 
03907         if ( Bmp->DriverHandle )
03908         {
03909                 if ( ! geBitmap_Update_DriverToSystem((geBitmap *)Bmp) )
03910                 {
03911                         geErrorLog_AddString(-1,"WriteToFile : Update_DriverToSystem", NULL);   
03912                         return GE_FALSE;
03913                 }
03914         }
03915 
03916         if ( ! geVFile_Write(F, &geBM_Tag, sizeof(geBM_Tag)) )
03917                 return GE_FALSE;
03918 
03919         if ( ! geVFile_Write(F, &geBM_Version, sizeof(geBM_Version)) )
03920                 return GE_FALSE;
03921 
03922         if ( ! geBitmap_WriteInfo(Bmp,F) )
03923                 return GE_FALSE;
03924 
03925         #ifdef COUNT_HEADER_SIZES
03926                 Header_Sizes += 15;
03927         #endif
03928 
03929         // the pointer Bmp->Info.Palette serves as boolean : HasPalette
03930         if ( Bmp->Info.Palette )
03931         {
03932                 if ( ! geBitmap_Palette_WriteToFile(Bmp->Info.Palette,F) )
03933                         return GE_FALSE;
03934         }
03935 
03936         if ( Bmp->Info.Format == GE_PIXELFORMAT_WAVELET )
03937         {
03938                 geErrorLog_AddString(-1,"Genesis3D 1.0 does not support Wavelet Images",NULL);
03939         }
03940         else
03941         {
03942                 for( mip = Bmp->Info.MinimumMip; mip <= Bmp->Info.MaximumMip; mip++ )
03943                 {
03944 
03945                         // write out all the interesting mips :
03946                         //      the first one, and then mips which are not just
03947                         //      sub-samples of the first (eg. that have been user-set)
03948 
03949                         if ( (mip == Bmp->Info.MinimumMip || Bmp->Modified[mip]) && Bmp->Data[mip] )
03950                         {
03951                         uint8 * MipData;
03952                         geBoolean MipDataAlloced;
03953                         uint32 MipDataLen;
03954 
03955                                 MipDataLen = SHIFT_R_ROUNDUP(Bmp->Info.Width,mip) * SHIFT_R_ROUNDUP(Bmp->Info.Height,mip) *
03956                                                                 gePixelFormat_BytesPerPel(Bmp->Info.Format);
03957 
03958                                 if ( Bmp->Info.Stride == Bmp->Info.Width )
03959                                 {
03960                                         MipData = Bmp->Data[mip];
03961                                         MipDataAlloced = GE_FALSE;
03962                                 }
03963                                 else
03964                                 {
03965                                 int w,h,s,y;
03966                                 uint8 * fptr,*tptr;
03967                                 
03968                                         if ( ! (MipData = geRam_Allocate(MipDataLen) ) )
03969                                         {
03970                                                 geErrorLog_AddString(-1,"Bitmap_WriteToFile : Ram_Alloc failed!",NULL);
03971                                                 return GE_FALSE;
03972                                         }
03973 
03974                                         MipDataAlloced = GE_TRUE;
03975 
03976                                         s = SHIFT_R_ROUNDUP(Bmp->Info.Stride,mip)* gePixelFormat_BytesPerPel(Bmp->Info.Format);
03977                                         w = SHIFT_R_ROUNDUP(Bmp->Info.Width,mip) * gePixelFormat_BytesPerPel(Bmp->Info.Format);
03978                                         h = SHIFT_R_ROUNDUP(Bmp->Info.Height,mip);
03979 
03980                                         fptr = Bmp->Data[mip];
03981                                         tptr = MipData;
03982                                         for(y=h;y--;)
03983                                         {
03984                                                 memcpy(tptr,fptr,w);
03985                                                 fptr += s;
03986                                                 tptr += w;
03987                                         }
03988                                 }
03989 
03990                                 assert( mip <= MIP_MASK );
03991                                 flags = mip;
03992                         #ifdef DO_LZ
03993                                 flags |= MIP_FLAG_COMPRESSED;
03994                         #endif
03995 
03996                                 if ( ! geVFile_Write(F, &flags, sizeof(flags)) )
03997                                         return GE_FALSE;
03998 
03999                         #ifdef DO_LZ
04000                         {
04001                         geVFile * LzF;
04002                                 LzF = geVFile_OpenNewSystem(F,GE_VFILE_TYPE_LZ,NULL,NULL,GE_VFILE_OPEN_CREATE);
04003                                 if ( ! LzF )
04004                                 {
04005                                         if ( MipDataAlloced )
04006                                                 geRam_Free(MipData);
04007                                         geErrorLog_AddString(-1,"Bitmap_WriteToFile : LZ File Open failed",NULL);
04008                                         return GE_FALSE;
04009                                 }
04010 
04011                                 if ( ! geVFile_Write(LzF, MipData, MipDataLen ) )
04012                                         return GE_FALSE;
04013 
04014                                 if ( ! geVFile_Close(LzF) )
04015                                 {
04016                                         if ( MipDataAlloced )
04017                                                 geRam_Free(MipData);
04018                                         geErrorLog_AddString(-1,"Bitmap_WriteToFile : LZ File Close failed",NULL);
04019                                         return GE_FALSE;
04020                                 }
04021                         }
04022                         #else
04023                                 if ( ! geVFile_Write(F, MipData, MipDataLen ) )
04024                                         return GE_FALSE;
04025                         #endif
04026 
04027                                 if ( MipDataAlloced )
04028                                         geRam_Free(MipData);
04029                         }
04030                 }
04031                 
04032                 // mip > MaximumMip signals End-Of-Mips
04033 
04034                 flags = MIP_MASK;
04035                 if ( ! geVFile_Write(F, &flags, sizeof(flags)) )
04036                         return GE_FALSE;
04037         }
04038 
04039         // the pointer Bmp->Alpha serves as boolean : HasAlpha
04040 
04041         if( Bmp->Alpha )
04042         {
04043                 if ( ! geBitmap_WriteToFile(Bmp->Alpha,F) )
04044                         return GE_FALSE;
04045         }
04046 
04047 return GE_TRUE;
04048 }
04049 
04050 /*}{********** Windows BMP Types *******/
04051 
04052 #pragma pack(1)
04053 
04054 typedef struct TGAHEADER
04055 {
04056         char    IDLength;
04057         char    ColorMapType;
04058         char    ImageType;
04059         uint16  CMFirstEntry;
04060         uint16  CMLength;
04061         char    CMEntrySize;
04062         uint16  Xorigin;
04063         uint16  Yorigin;
04064         uint16  Width;
04065         uint16  Height;
04066         char    PixelDepth;
04067         char    ImageDescriptor;
04068 } TGAHEADER;
04069 
04070 typedef struct 
04071 {
04072         uint32      biSize;
04073         long            biWidth;
04074         long            biHeight;
04075         uint16      biPlanes;
04076         uint16      biBitCount;
04077         uint32      biCompression;
04078         uint32      biSizeImage;
04079         long            biXPelsPerMeter;
04080         long            biYPelsPerMeter;
04081         uint32      biClrUsed;
04082         uint32      biClrImportant;
04083 } BITMAPINFOHEADER;
04084 
04085 typedef struct 
04086 {
04087         uint16   bfType;
04088         uint32   bfSize;
04089         uint16   bfReserved1;
04090         uint16   bfReserved2;
04091         uint32   bfOffBits;
04092 } BITMAPFILEHEADER;
04093 
04094 typedef struct 
04095 {
04096     uint8    B;
04097     uint8    G;
04098     uint8    R;
04099     uint8    rgbReserved;
04100 } RGBQUAD;
04101 #pragma pack()
04102 
04103 
04104 
04105 static geBoolean geBitmap_ReadFromBMP(geBitmap * Bmp,geVFile * F)
04106 {
04107 BITMAPFILEHEADER        bmfh;
04108 BITMAPINFOHEADER        bmih;
04109 int bPad,myRowWidth,bmpRowWidth,pelBytes;
04110 
04111         // Windows Bitmap
04112 
04113         if ( ! geVFile_Read(F, &bmfh, sizeof(bmfh)) )
04114                 return GE_FALSE;
04115 
04116         assert(bmfh.bfType == 0x4D42);
04117 
04118         bPad = bmfh.bfOffBits;
04119 
04120         if ( ! geVFile_Read(F, &bmih, sizeof(bmih)) )
04121                 return GE_FALSE;
04122 
04123         if ( bmih.biSize > sizeof(bmih) )
04124         {
04125                 geVFile_Seek(F, bmih.biSize - sizeof(bmih), GE_VFILE_SEEKCUR);
04126         }
04127         else if ( bmih.biSize < sizeof(bmih) )
04128         {
04129                 geErrorLog_AddString(-1,"CreateFromFile : bmih size bad", NULL);        
04130                 return GE_FALSE;
04131         }
04132 
04133         if ( bmih.biCompression )
04134         {
04135                 geErrorLog_AddString(-1,"CreateFromFile : only BI_RGB BMP compression supported", NULL);
04136                 return GE_FALSE;
04137         }
04138 
04139         bPad -= sizeof(bmih) + sizeof(bmfh);
04140 
04141         switch (bmih.biBitCount) 
04142         {
04143                 case 8:                 /* colormapped image */
04144                         if ( bmih.biClrUsed == 0 ) bmih.biClrUsed = 256;
04145 
04146                         if ( ! (Bmp->Info.Palette = geBitmap_Palette_Create(GE_PIXELFORMAT_32BIT_XRGB,bmih.biClrUsed)) )
04147                                 return GE_FALSE;
04148 
04149                         if ( ! geVFile_Read(F, Bmp->Info.Palette->Data, bmih.biClrUsed * 4) )
04150                                 return GE_FALSE;
04151 
04152                         bPad -= bmih.biClrUsed * 4;
04153 
04154                         Bmp->Info.Format = GE_PIXELFORMAT_8BIT_PAL;
04155                         pelBytes = 1;
04156                         break;
04157                 case 16:                        
04158                         Bmp->Info.Format = GE_PIXELFORMAT_16BIT_555_RGB;
04159                         // tried 555,565_BGR & RGB, seems to have too much green
04160                         pelBytes = 2;
04161                         break;
04162                 case 24:                        
04163                         Bmp->Info.Format = GE_PIXELFORMAT_24BIT_BGR;
04164                         pelBytes = 3;
04165                         break;
04166                 case 32:                        
04167                         Bmp->Info.Format = GE_PIXELFORMAT_32BIT_XRGB; // surprisingly sane !?
04168                         pelBytes = 4;
04169                         break;
04170                 default:
04171                         return GE_FALSE;
04172         }
04173 
04174         if ( bPad < 0 )
04175         {
04176                 geErrorLog_AddString(-1,"CreateFromFile : bPad bad", NULL);
04177                 return GE_FALSE;
04178         }
04179 
04180         geVFile_Seek(F, bPad, GE_VFILE_SEEKCUR);
04181         
04182         Bmp->Info.Width = bmih.biWidth;
04183         Bmp->Info.Height = abs(bmih.biHeight);
04184         Bmp->Info.Stride = ((bmih.biWidth+3)&(~3));
04185 
04186         Bmp->Info.HasColorKey = GE_FALSE;
04187 
04188         myRowWidth      = Bmp->Info.Stride * pelBytes;
04189         bmpRowWidth = (((bmih.biWidth * pelBytes) + 3)&(~3));
04190 
04191         assert( bmpRowWidth <= myRowWidth );
04192 
04193         if ( ! geBitmap_AllocSystemMip(Bmp,0) )
04194                 return GE_FALSE;
04195 
04196         if ( bmih.biHeight > 0 )
04197         {
04198         int y;
04199         char * row;
04200                 row = Bmp->Data[0];
04201                 row += (Bmp->Info.Height - 1) * myRowWidth;
04202                 for(y= Bmp->Info.Height;y--;)
04203                 {
04204                         if ( ! geVFile_Read(F, row, bmpRowWidth) )
04205                                 return GE_FALSE;                                
04206                         row -= myRowWidth;
04207                 }
04208         }
04209         else
04210         {
04211         int y;
04212         char * row;
04213                 row = Bmp->Data[0];
04214                 for(y= Bmp->Info.Height;y--;)
04215                 {
04216                         if ( ! geVFile_Read(F, row, bmpRowWidth) )
04217                                 return GE_FALSE;                                
04218                         row += myRowWidth;
04219                 }
04220         }
04221 
04222 return GE_TRUE;
04223 }       // end BMP reader
04224 
04225 
04226 /*******************************************************************************/
04227 static geBoolean  geBitmap_IsTGA(geVFile * F)
04228 {
04229         char targa[18];
04230         TGAHEADER tgah;
04231         
04232         if (!geVFile_Seek(F, - 18, GE_VFILE_SEEKEND))
04233                 return GE_FALSE;
04234         
04235         if(!geVFile_Read(F, &targa, 18))
04236                 return GE_FALSE;
04237         geVFile_Seek(F, 0, GE_VFILE_SEEKSET);
04238 
04239         //if we find the TRUEVISION-XFILE. signature this should be a tga file
04240         if(!strcmp(targa, "TRUEVISION-XFILE."))
04241                 return GE_TRUE;
04242         
04243         // older versions don't have a signature so do further checks
04244         if(!geVFile_Read(F, &tgah, 18))
04245                 return GE_FALSE;
04246         geVFile_Seek(F, 0, GE_VFILE_SEEKSET);
04247 
04248         if(tgah.ColorMapType != 0 && tgah.ColorMapType != 1)
04249                 return GE_FALSE;
04250         else if(tgah.ImageType != 1 && tgah.ImageType != 2 && tgah.ImageType != 9 && tgah.ImageType != 10)
04251                 return GE_FALSE;
04252         else if(tgah.PixelDepth != 8 && tgah.PixelDepth != 16 && tgah.PixelDepth != 24 && tgah.PixelDepth != 32)
04253                 return GE_FALSE;
04254         else 
04255                 return GE_TRUE;
04256 
04257                                 
04258         return GE_FALSE;
04259 }
04260  
04261 /*****************************************************************************/
04262 
04263 static geBoolean  geBitmap_ReadFromTGA(geBitmap * Bmp, geVFile * File)
04264 {
04265         TGAHEADER tgah;
04266         int alphabits;
04267         int fliphoriz;
04268         int flipvert;
04269     int myRowWidth,bmpRowWidth,pelBytes;
04270         long ImageOffset = 0;
04271         geBitmap *AlphaBmp = NULL;
04272 
04273 
04274         //read the header fields 
04275         if(!geVFile_Read(File, &tgah, 18))
04276                 return GE_FALSE;
04277         
04278         Bmp->Info.Width = tgah.Width;
04279         Bmp->Info.Height = tgah.Height;
04280         Bmp->Info.Stride = ((tgah.Width+3)&(~3));
04281         Bmp->Info.HasColorKey = GE_FALSE;
04282 
04283         alphabits = tgah.ImageDescriptor & 0x0f;
04284         fliphoriz = (tgah.ImageDescriptor & 0x10) ? 0 : 1;
04285         flipvert = (tgah.ImageDescriptor & 0x20) ? 1 : 0;  
04286         //flipvert is ignored at the moment, because it appears rather rarely
04287         //+ you can flip textures in editors
04288 
04289         switch (tgah.PixelDepth) 
04290         {
04291                 case 8 :
04292                         pelBytes=1;
04293                         Bmp->Info.Format = GE_PIXELFORMAT_8BIT_PAL;
04294                         ImageOffset = 0;
04295 
04296                         //      if ( tgah.CMLength == 0 ) tgah.CMLength = 256;
04297                         if(tgah.CMEntrySize == 16)
04298                         {
04299                                 if ( ! (Bmp->Info.Palette = geBitmap_Palette_Create(GE_PIXELFORMAT_16BIT_555_RGB, tgah.CMLength)) )
04300                                         return GE_FALSE;
04301                         }
04302                         else if(tgah.CMEntrySize == 24)
04303                         {
04304                                 if ( ! (Bmp->Info.Palette = geBitmap_Palette_Create(GE_PIXELFORMAT_24BIT_BGR, tgah.CMLength)) )
04305                                         return GE_FALSE;
04306                         }
04307                         else if(tgah.CMEntrySize == 32)
04308                         {
04309                                 if ( ! (Bmp->Info.Palette = geBitmap_Palette_Create(GE_PIXELFORMAT_32BIT_XRGB, tgah.CMLength)) )
04310                                         return GE_FALSE;
04311                         }
04312                         else
04313                                 return GE_FALSE;
04314 
04315                         // move to the palette data
04316                         geVFile_Seek(File, tgah.IDLength, GE_VFILE_SEEKCUR);
04317 
04318                         if ( ! geVFile_Read(File, Bmp->Info.Palette->Data, tgah.CMLength*(tgah.CMEntrySize/8)) )
04319                                 return GE_FALSE;
04320                         
04321                         break;
04322 
04323                 case 16 :
04324                         pelBytes = 2;
04325                         Bmp->Info.Format = GE_PIXELFORMAT_16BIT_555_RGB;
04326                         ImageOffset = tgah.IDLength+((tgah.CMEntrySize/8) * tgah.CMLength);
04327                         break;
04328 
04329                 case 24 :
04330                         pelBytes = 3;
04331                         Bmp->Info.Format = GE_PIXELFORMAT_24BIT_BGR;
04332                         ImageOffset = tgah.IDLength+((tgah.CMEntrySize/8) * tgah.CMLength);                     
04333                         break;
04334 
04335                 case 32 :
04336                         // Alpha map base creation ***************************
04337                         AlphaBmp = geBitmap_Create_Base();
04338         
04339                         if (!AlphaBmp)
04340                                 return GE_FALSE;
04341                                 
04342                         AlphaBmp->Info.Width = tgah.Width;
04343                         AlphaBmp->Info.Height = tgah.Height;
04344                         AlphaBmp->Info.Stride = ((tgah.Width+3)&(~3));
04345                         AlphaBmp->Info.HasColorKey = GE_FALSE;
04346                         AlphaBmp->Info.Format = GE_PIXELFORMAT_8BIT_GRAY;
04347         
04348                         if ( ! geBitmap_AllocSystemMip(AlphaBmp,0) )
04349                                 goto fail;              
04350                         // Alpha map base creation done **********************
04351                         
04352                         pelBytes = 3;
04353                         Bmp->Info.Format = GE_PIXELFORMAT_24BIT_BGR;
04354                         //      Bmp->Info.Format = GE_PIXELFORMAT_32BIT_ARGB;
04355                         ImageOffset = tgah.IDLength+((tgah.CMEntrySize/8) * tgah.CMLength);
04356 
04357                         break;
04358                 
04359                 default :
04360                         return GE_FALSE;
04361         }
04362         
04363 
04364 
04365         if ( ! geBitmap_AllocSystemMip(Bmp,0) )
04366                 goto fail;
04367         
04368         // move to the image data
04369         geVFile_Seek(File, ImageOffset, GE_VFILE_SEEKCUR);
04370                                 
04371         myRowWidth      = Bmp->Info.Stride * pelBytes;
04372         bmpRowWidth = (((tgah.Width * pelBytes) + 3)&(~3));
04373         assert( bmpRowWidth <= myRowWidth );
04374         
04375         // NOTE: to avoid the  if(tgah.PixelDepth == 32) statements in the following code
04376         // you can write a separate reading code for 32bit in the switch statement above
04377         // this may be longer but faster ...
04378 
04379         //Uncompressed images
04380         if(tgah.ImageType == 1 || tgah.ImageType == 2)
04381         {
04382                 int count, y;
04383                 char *row;
04384                 char * alpharow;
04385                 row = Bmp->Data[0];
04386                 alpharow = NULL;
04387                 
04388                 if(tgah.PixelDepth == 32)
04389                         alpharow = AlphaBmp->Data[0];
04390 
04391                 if(fliphoriz)
04392                 {
04393                         row += (Bmp->Info.Height - 1) * myRowWidth;
04394                         if(tgah.PixelDepth == 32)
04395                                 alpharow += (AlphaBmp->Info.Height - 1) * (AlphaBmp->Info.Stride);                              
04396                 }
04397 
04398                 for(y= Bmp->Info.Height;y--;)
04399                 {
04400                         // uff... since this could be 32bit we have to read each pixel separately
04401                         for(count=0; count<Bmp->Info.Stride; count++ )
04402                         {                               
04403                                 geVFile_Read(File, row, pelBytes);                                      
04404                                 row += pelBytes;
04405                                 if(tgah.PixelDepth == 32)
04406                                 {
04407                                         geVFile_Read(File, alpharow, 1);
04408                                         alpharow++;
04409                                 }
04410                         }
04411                         if(fliphoriz)
04412                         {
04413                                 // go back this row and to the row above
04414                                 row -= 2*myRowWidth; 
04415                                 if(tgah.PixelDepth == 32)
04416                                         alpharow -= 2*(AlphaBmp->Info.Stride);
04417                         }                               
04418                 }       
04419         }
04420         //Run-Length Encoded images
04421         else if(tgah.ImageType == 9 || tgah.ImageType == 10)
04422         {
04423                 int i, j, k, y;
04424                 char buff[4];
04425                 char * row;
04426                 char * alpharow;
04427                 row = Bmp->Data[0];
04428                 alpharow = NULL;
04429                 y = 0;
04430                 k = 1;
04431 
04432                 if(tgah.PixelDepth == 32)
04433                         alpharow = AlphaBmp->Data[0];
04434         
04435                 if(fliphoriz)
04436                 {
04437                         row += (Bmp->Info.Height - 1) * myRowWidth;
04438                         if(tgah.PixelDepth == 32)
04439                                 alpharow += (AlphaBmp->Info.Height - 1) * (AlphaBmp->Info.Stride);
04440                 }                                       
04441                 while(y < Bmp->Info.Height)
04442                 {       
04443                         // read in the Repetition Count byte:
04444                         // 1bit = packet type (RLE/Raw packet), 7bits = pixel count
04445                         // The pixel count can range from 0 to 127. Since a packet never 
04446                         // encodes zero pixels, the value in pixel count is always 1 less
04447                         // than the actual number of pixels encoded in the packet
04448                         geVFile_Read(File, buff, 1);
04449                                 
04450                         j = buff[0] & 0x7f; // number of encoded pixels-1
04451                         
04452                         if(buff[0] & 0x80) // RLE packet
04453                         {       
04454                                 geVFile_Read(File, buff, pelBytes);
04455                                 if(tgah.PixelDepth == 32)
04456                                         geVFile_Read(File, &(buff[3]), 1);
04457                                 
04458                                 for(i = 0; i <= j; i++)
04459                                 {                                                               
04460                                         *row++ = buff[0];
04461                                         if(pelBytes>1) *row++ = buff[1];
04462                                         if(pelBytes>2) *row++ = buff[2];
04463                                         if(tgah.PixelDepth == 32) *alpharow++ = buff[3];
04464                                         k++;
04465                                         if(k > Bmp->Info.Stride)
04466                                         {
04467                                                 k=1;
04468                                                 y++;
04469                                                 if(fliphoriz)
04470                                                 {
04471                                                         // go back this row and to the row above
04472                                                         row -= 2*myRowWidth;
04473                                                         if(tgah.PixelDepth == 32)
04474                                                                 alpharow -= 2*(AlphaBmp->Info.Stride);
04475                                                 }
04476                                         }
04477                                 }       
04478                         }       
04479                         else //Raw packet
04480                         {                                               
04481                                 for(i = 0; i <= j; i++)
04482                                 {
04483                                         geVFile_Read(File, row, pelBytes);
04484                                         row += pelBytes;
04485                                         if(tgah.PixelDepth == 32)
04486                                         {
04487                                                 geVFile_Read(File, alpharow, 1);
04488                                                 alpharow++;
04489                                         }
04490                                         k++;
04491                                         if(k > Bmp->Info.Stride)
04492                                         {
04493                                                 k=1;
04494                                                 y++;
04495                                                 if(fliphoriz)
04496                                                 {
04497                                                         // go back this row and to the row above
04498                                                         row -= 2*myRowWidth;
04499                                                         if(tgah.PixelDepth == 32)
04500                                                                 alpharow -= 2*(AlphaBmp->Info.Stride);
04501                                                 }
04502                                         }
04503                                 }
04504                         }
04505                 }                               
04506         }
04507         else
04508                 goto fail;
04509 
04510         //set alphamap
04511         if(tgah.PixelDepth == 32)
04512         {
04513                 assert(AlphaBmp);
04514                 if(!geBitmap_SetAlpha( Bmp, AlphaBmp))
04515                         goto fail;
04516                 geBitmap_Destroy(&AlphaBmp);
04517                 geBitmap_SetPreferredFormat(Bmp,GE_PIXELFORMAT_32BIT_ARGB);
04518         }
04519 
04520         return GE_TRUE;
04521 
04522 fail:
04523         if(AlphaBmp);
04524                 geBitmap_Destroy(&AlphaBmp);
04525         return GE_FALSE;
04526 }
04527 
04528 
04529 /*}{ *** Packed Info IO ***/
04530 
04531 #define INFO_FLAG_WH_ARE_LOG2   (1<<0)
04532 #define INFO_FLAG_HAS_CK        (1<<1)
04533 #define INFO_FLAG_HAS_ALPHA     (1<<2)
04534 #define INFO_FLAG_HAS_PAL       (1<<3)
04535 
04536 #define INFO_FLAG_IF_NOT_LOG2_ARE_BYTE  (1<<5)
04537 
04538 geBoolean geBitmap_ReadInfo(geBitmap *Bmp,geVFile * F)
04539 {
04540 uint8 data[4];
04541 uint8 flags;
04542 uint8 b;
04543 uint16 w;
04544 geBitmap_Info * pi;
04545 
04546         pi = &(Bmp->Info);
04547 
04548         if ( ! geVFile_Read(F,data,3) )
04549                 return GE_FALSE;
04550 
04551         flags = data[0];
04552 
04553         pi->Format = data[1]; // could go in 5 bits
04554 
04555         b = data[2];
04556 
04557         pi->MaximumMip = (b>>4)&0xF;
04558         Bmp->SeekMipCount = (b)&0xF;
04559 
04560         if ( flags & INFO_FLAG_HAS_PAL )
04561                 pi->Palette  = (geBitmap_Palette *)1;
04562         if ( flags & INFO_FLAG_HAS_ALPHA )
04563                 Bmp->Alpha = (geBitmap *)1;
04564 
04565         if ( flags & INFO_FLAG_WH_ARE_LOG2 )
04566         {
04567         int logw,logh;
04568 
04569                 if ( ! geVFile_Read(F,&b,1) )
04570                         return GE_FALSE;
04571 
04572                 logw = (b>>4)&0xF;
04573                 logh = (b   )&0xF;
04574 
04575                 pi->Width = 1<<logw;
04576                 pi->Height= 1<<logh;
04577         }
04578         else if ( flags & INFO_FLAG_IF_NOT_LOG2_ARE_BYTE )
04579         {
04580                 if ( ! geVFile_Read(F,&b,1) )
04581                         return GE_FALSE;
04582                 pi->Width = b;
04583                 if ( ! geVFile_Read(F,&b,1) )
04584                         return GE_FALSE;
04585                 pi->Height = b;
04586         }
04587         else
04588         {
04589                 if ( ! geVFile_Read(F,&w,2) )
04590                         return GE_FALSE;
04591                 pi->Width = w;
04592                 if ( ! geVFile_Read(F,&w,2) )
04593                         return GE_FALSE;
04594                 pi->Height = w;
04595         }
04596 
04597         if ( (flags & INFO_FLAG_HAS_CK) && gePixelFormat_BytesPerPel(pi->Format) > 0 )
04598         {
04599         uint8 * ptr;
04600                 pi->HasColorKey = GE_TRUE;
04601 
04602                 if ( ! geVFile_Read(F,data,gePixelFormat_BytesPerPel(pi->Format)) )
04603                         return GE_FALSE;
04604                 
04605                 ptr = data;
04606                 pi->ColorKey = gePixelFormat_GetPixel(pi->Format,&ptr);
04607         }
04608 
04609         pi->Stride = pi->Width;
04610 
04611         return GE_TRUE;
04612 }
04613 
04614 geBoolean geBitmap_WriteInfo(const geBitmap *Bmp,geVFile * F)
04615 {
04616 uint8 data[64];
04617 uint8 * ptr;
04618 uint8 flags;
04619 uint8 b;
04620 int len,logw,logh;
04621 const geBitmap_Info * pi;
04622 
04623 /*
04624         bit flags :
04625                 W&H are log2
04626                 HasCK
04627                 HasAlpha
04628                 HasPal
04629 
04630                 W&H logs in 1 byte, or W & H each in 2 bytes
04631 
04632                 Format in 5 bits
04633                 MaxMip in 3 bits
04634                 Bmp->SeekMipCount in 3 bits
04635 
04636                 CK in bpp bytes
04637 */
04638 
04639         pi = &(Bmp->Info);
04640         flags = 0;
04641         ptr = data + 1; // flags will go there
04642 
04643         assert( pi->Width < 65536 && pi->Height < 65536 );
04644         assert( pi->MinimumMip == 0 );
04645         assert( gePixelFormat_IsValid(pi->Format) );
04646 
04647         *ptr++ = pi->Format; // could go in 5 bits
04648 
04649         b = (pi->MaximumMip << 4) + Bmp->SeekMipCount; // could go in 6 bits
04650         *ptr++ = b;
04651 
04652         if ( pi->Palette )
04653                 flags |= INFO_FLAG_HAS_PAL;
04654         if ( Bmp->Alpha )
04655                 flags |= INFO_FLAG_HAS_ALPHA;
04656 
04657         for(logw=0;(1<<logw) < pi->Width;logw++);
04658         for(logh=0;(1<<logh) < pi->Height;logh++);
04659 
04660         if ( (1<<logw) == pi->Width && (1<<logh) == pi->Height )
04661         {
04662                 flags |= INFO_FLAG_WH_ARE_LOG2;
04663                 assert( logw <= 0xF && logh <= 0xF );
04664                 b = (logw<<4) + logh;
04665                 *ptr++ = b;
04666         }
04667         else
04668         {
04669                 if ( pi->Width < 256 && pi->Height < 256 )
04670                 {
04671                         flags |= INFO_FLAG_IF_NOT_LOG2_ARE_BYTE;
04672                         *ptr++ = pi->Width;
04673                         *ptr++ = pi->Height;
04674                 }
04675                 else
04676                 {
04677                         *((uint16 *)ptr) = pi->Width;  ptr += 2;
04678                         *((uint16 *)ptr) = pi->Height; ptr += 2;
04679                 }
04680         }
04681 
04682         if ( pi->HasColorKey && gePixelFormat_BytesPerPel(pi->Format) > 0 )
04683         {
04684                 flags |= INFO_FLAG_HAS_CK;
04685 
04686                 gePixelFormat_PutPixel(pi->Format,&ptr,pi->ColorKey);
04687         }
04688 
04689         *data = flags;
04690         len = (int)(ptr - data);
04691 
04692         if ( ! geVFile_Write(F,data,len) )
04693                 return GE_FALSE;
04694 
04695         return GE_TRUE;
04696 }
04697 
04698 /*}{ ***************** Palette Functions *******************/
04699 
04700 geBoolean geBitmap_Palette_BlitData(gePixelFormat SrcFormat,const void *SrcData,const geBitmap_Palette * SrcPal,
04701                                                                         gePixelFormat DstFormat,          void *DstData,const geBitmap_Palette * DstPal,
04702                                                                         int Pixels)
04703 {
04704 char *SrcPtr,*DstPtr;
04705 geBoolean SrcHasCK,DstHasCK;
04706 uint32 SrcCK=0,DstCK=0;
04707 int SrcCKi=0,DstCKi=0;
04708 
04709         assert( SrcData && DstData );
04710 
04711         assert( gePixelFormat_IsRaw(SrcFormat) );
04712         assert( gePixelFormat_IsRaw(DstFormat) );
04713 
04714         SrcPtr = (char *)SrcData;
04715         DstPtr = (char *)DstData;
04716 
04717         if ( SrcPal && SrcPal->HasColorKey )
04718         {
04719                 SrcHasCK = GE_TRUE;
04720                 SrcCK = SrcPal->ColorKey;
04721                 SrcCKi = SrcPal->ColorKeyIndex;
04722         }
04723         else
04724         {
04725                 SrcHasCK = GE_FALSE;
04726         }
04727 
04728         if ( DstPal && DstPal->HasColorKey )
04729         {
04730                 DstHasCK = GE_TRUE;
04731                 DstCK = DstPal->ColorKey;
04732                 DstCKi = DstPal->ColorKeyIndex;
04733         }
04734         else
04735         {
04736                 DstHasCK = GE_FALSE;
04737         }
04738 
04739 #if 0 // {} ?
04740         if ( SrcHasCK && DstHasCK )
04741         {
04742                 if ( DstCKi == -1 )
04743                         DstCKi = SrcCKi;
04744         }
04745 #endif
04746 
04747         // no, can't do this, and if SrcCKi < 0 then it's just ignored, which is correct
04748         //assert( SrcCKi >= 0 );
04749         //assert( DstCKi >= 0 );
04750 
04751         // CK -> no CK : do nothing
04752         // no CK -> CK : avoid CK
04753         // CK -> CK    : assert the CKI's are the same; change color at CKI
04754 
04755         {
04756         uint32 Pixel;
04757         int p,R,G,B,A;
04758         const gePixelFormat_Operations *SrcOps,*DstOps;
04759         gePixelFormat_Composer          ComposePixel;
04760         gePixelFormat_Decomposer        DecomposePixel;
04761         gePixelFormat_PixelPutter       PutPixel;
04762         gePixelFormat_PixelGetter       GetPixel;
04763 
04764                 SrcOps = gePixelFormat_GetOperations(SrcFormat);
04765                 DstOps = gePixelFormat_GetOperations(DstFormat);
04766                 assert(SrcOps && DstOps);
04767 
04768                 GetPixel = SrcOps->GetPixel;
04769                 DecomposePixel = SrcOps->DecomposePixel;
04770                 ComposePixel = DstOps->ComposePixel;
04771                 PutPixel = DstOps->PutPixel;
04772 
04773                 if ( SrcOps->AMask && ! DstOps->AMask )
04774                 {
04775                         // alpha -> CK in the palette
04776                         for(p=0;p<Pixels;p++)
04777                         {
04778                                 Pixel = GetPixel(&SrcPtr);
04779                                 DecomposePixel(Pixel,&R,&G,&B,&A);
04780                                 if ( SrcHasCK && ( p == SrcCKi || Pixel == SrcCK ) ) 
04781                                         A = 0;
04782                                 Pixel = ComposePixel(R,G,B,A);
04783 
04784                                 if ( DstHasCK )
04785                                 {
04786                                         if ( p == DstCKi || A < 128 )
04787                                                 Pixel = DstCK;
04788                                         else if ( Pixel == DstCK )
04789                                                 Pixel ^= 1;
04790 
04791                                         // BTW this makes dark blue into dark purple on glide
04792                                 }
04793                                 PutPixel(&DstPtr,Pixel);
04794                         }
04795                 }
04796                 else if ( ! SrcOps->AMask && DstOps->AMask )
04797                 {
04798                         // CK -> alpha in the palette
04799                         for(p=0;p<Pixels;p++)
04800                         {
04801                                 Pixel = GetPixel(&SrcPtr);
04802                                 DecomposePixel(Pixel,&R,&G,&B,&A);
04803                                 if ( SrcHasCK && ( p == SrcCKi || Pixel == SrcCK ) ) 
04804                                         A = 0;
04805 
04806                                 Pixel = ComposePixel(R,G,B,A);
04807                                 if ( DstHasCK )
04808                                 {
04809                                         if ( p == DstCKi )
04810                                                 Pixel = DstCK;
04811                                         else if ( Pixel == DstCK )
04812                                                 Pixel ^= 1;
04813                                 }
04814                                 PutPixel(&DstPtr,Pixel);
04815                         }
04816                 }
04817                 else
04818                 {
04819                         // both have alpha or both don't
04820                         for(p=0;p<Pixels;p++)
04821                         {
04822                                 Pixel = GetPixel(&SrcPtr);
04823                                 DecomposePixel(Pixel,&R,&G,&B,&A);
04824                                 if ( (SrcHasCK && ( p == SrcCKi || Pixel == SrcCK )) ||
04825                                          DstHasCK && p == DstCKi ) 
04826                                 {
04827                                         Pixel = DstCK;
04828                                 }
04829                                 else
04830                                 {
04831                                         Pixel = ComposePixel(R,G,B,A);
04832                                         if ( DstHasCK && Pixel == DstCK )
04833                                                 Pixel ^= 1;
04834                                 }
04835                                 PutPixel(&DstPtr,Pixel);
04836                         }
04837                 }
04838         }
04839 
04840 return GE_TRUE;
04841 }
04842 
04843 GENESISAPI geBitmap_Palette * GENESISCC geBitmap_Palette_Create(gePixelFormat Format,int Size)
04844 {
04845 geBitmap_Palette * P;
04846 int DataBytes;
04847 const gePixelFormat_Operations * ops;
04848 
04849         ops = gePixelFormat_GetOperations(Format);
04850         if ( ! ops->RMask )
04851         {
04852                 geErrorLog_AddString(-1,"geBitmap_Palette_Create : Invalid format for a palette!", NULL);
04853                 return NULL;
04854         }
04855 
04856         DataBytes = gePixelFormat_BytesPerPel(Format) * Size;
04857         if ( DataBytes == 0 )
04858         {
04859                 geErrorLog_AddString(-1,"geBitmap_Palette_Create : Invalid format for a palette!", NULL);
04860                 return NULL;
04861         }
04862 
04863         allocate(P);
04864         if ( ! P ) return NULL;
04865         clear(P);
04866 
04867         P->Size = Size;
04868         P->Format = Format;
04869         if ( ! (P->Data = geRam_Allocate(DataBytes)) )
04870         {
04871                 geRam_Free(P);
04872                 return NULL;
04873         }
04874 
04875         P->RefCount = 1;
04876         P->LockCount = 0;
04877 
04878         P->HasColorKey = GE_FALSE;
04879 
04880 return P;
04881 }
04882 
04883 GENESISAPI geBoolean GENESISCC geBitmap_Palette_CreateRef(geBitmap_Palette *P)
04884 {
04885         if ( ! P || P->RefCount < 1 )
04886                 return GE_FALSE;
04887         P->RefCount ++;
04888 return GE_TRUE;
04889 }
04890 
04891 GENESISAPI geBitmap_Palette * GENESISCC geBitmap_Palette_CreateFromBitmap(geBitmap * Bmp,geBoolean Slow)
04892 {
04893 geBitmap_Palette * Pal;
04894         Pal = geBitmap_GetPalette(Bmp);
04895         if ( Pal )
04896         {
04897                 geBitmap_Palette_CreateRef(Pal);
04898                 return Pal;
04899         }
04900         else
04901         {
04902                 return createPaletteFromBitmap(Bmp, Slow);
04903         }
04904 }
04905 
04906 geBitmap_Palette * BITMAP_GENESIS_INTERNAL geBitmap_Palette_CreateFromDriver(DRV_Driver * Driver,gePixelFormat Format,int Size)
04907 {
04908 geBitmap_Palette * P;
04909 geRDriver_THandleInfo TInfo;
04910 
04911         assert(Driver);
04912 
04913         allocate(P);
04914         if ( ! P ) return NULL;
04915         clear(P);
04916 
04917         P->Size = Size;
04918         P->Driver = Driver;     
04919 
04920         // {} the pixelformat passed in here has non-trivial implications when the
04921         //              driver provides more than one possible palette type
04922 
04923         assert( gePixelFormat_IsRaw(Format) );
04924 
04925         P->DriverHandle = geBitmap_CreateTHandle(Driver,Size,1,1,
04926                         Format,0,0,gePixelFormat_HasAlpha(Format),0,RDRIVER_PF_PALETTE);
04927         if ( ! P->DriverHandle )
04928         {
04929                 geErrorLog_AddString(-1,"Palette_CreateFromDriver : CreateTHandle", NULL);      
04930                 geRam_Free(P);
04931                 return NULL;
04932         }
04933 
04934         Driver->THandle_GetInfo(P->DriverHandle,0,&TInfo);
04935         P->Format = TInfo.PixelFormat.PixelFormat;
04936 
04937         P->HasColorKey = (TInfo.Flags & RDRIVER_THANDLE_HAS_COLORKEY) ? GE_TRUE : GE_FALSE;
04938         P->ColorKey = TInfo.ColorKey;
04939         P->ColorKeyIndex = -1;
04940 
04941         P->RefCount = 1;
04942 
04943 return P;
04944 }
04945 
04946 GENESISAPI geBitmap_Palette * GENESISCC geBitmap_Palette_CreateCopy(const geBitmap_Palette *Palette)
04947 {
04948 geBitmap_Palette * P;
04949 
04950         if ( ! Palette )
04951                 return NULL;
04952 
04953         if ( Palette->Driver )
04954         {
04955                 P = geBitmap_Palette_CreateFromDriver(Palette->Driver,Palette->Format,Palette->Size);
04956         }
04957         else
04958         {
04959                 P = geBitmap_Palette_Create(Palette->Format,Palette->Size);
04960         }
04961 
04962         if ( ! P ) return NULL;
04963 
04964         if ( ! geBitmap_Palette_Copy(Palette,P) )
04965         {
04966                 geBitmap_Palette_Destroy(&P);
04967                 return NULL;
04968         }
04969 
04970 return P;
04971 }
04972 
04973 GENESISAPI geBoolean GENESISCC geBitmap_Palette_Destroy(geBitmap_Palette ** ppPalette)
04974 {
04975 geBitmap_Palette * Palette;
04976         assert(ppPalette);
04977         if ( Palette = *ppPalette )
04978         {
04979                 if ( Palette->LockCount )
04980                         return GE_FALSE;
04981                 Palette->RefCount --;
04982                 if ( Palette->RefCount <= 0 )
04983                 {
04984                         if ( Palette->Data )
04985                                 geRam_Free(Palette->Data);
04986                         if ( Palette->DriverHandle )
04987                         {
04988                                 Palette->Driver->THandle_Destroy(Palette->DriverHandle);
04989                                 Palette->DriverHandle = NULL;
04990                         }
04991                         geRam_Free(Palette);
04992                 }
04993         }
04994         *ppPalette = NULL;
04995 return GE_TRUE;
04996 }
04997 
04998 GENESISAPI geBoolean GENESISCC geBitmap_Palette_Lock(geBitmap_Palette *P, void **pBits, gePixelFormat *pFormat,int *pSize)
04999 {
05000         assert(P);
05001         assert(pBits);
05002 
05003         if ( P->LockCount )
05004                 return GE_FALSE;
05005         P->LockCount++;
05006 
05007         *pBits = NULL;
05008 
05009         if ( P->Data )
05010         {
05011                 *pBits          = P->Data;
05012                 if ( pFormat )
05013                         *pFormat= P->Format;
05014                 if ( pSize )
05015                         *pSize  = P->Size;
05016         }
05017         else if ( P->DriverHandle )
05018         {
05019         geRDriver_THandleInfo TInfo;
05020 
05021                 if ( ! P->Driver->THandle_GetInfo(P->DriverHandle,0,&TInfo) )
05022                         return GE_FALSE;
05023 
05024                 if ( TInfo.Height != 1 )
05025                         return GE_FALSE;
05026 
05027                 if ( ! (P->Driver->THandle_Lock(P->DriverHandle,0,pBits)) )
05028                         *pBits = NULL;
05029 
05030                 P->DriverBits = *pBits;
05031 
05032                 if ( pFormat )
05033                         *pFormat = TInfo.PixelFormat.PixelFormat;
05034                 if ( pSize )
05035                         *pSize = TInfo.Width;
05036         }
05037 
05038         return (*pBits) ? GE_TRUE : GE_FALSE;
05039 }
05040 
05041 GENESISAPI geBoolean GENESISCC geBitmap_Palette_UnLock(geBitmap_Palette *P)
05042 {
05043         assert(P);
05044         if ( P->LockCount <= 0 )
05045                 return GE_FALSE;
05046         P->LockCount--;
05047         if ( P->LockCount == 0 )
05048         {
05049                 if ( P->HasColorKey )
05050                 {
05051                         if ( P->ColorKeyIndex >= 0 && P->ColorKeyIndex < P->Size )
05052                         {
05053                         uint8 *Bits=NULL,*pBits=NULL;
05054                         uint32 Pixel;
05055                         int p;
05056                         const gePixelFormat_Operations *ops;
05057                         gePixelFormat_PixelPutter       PutPixel;
05058                         gePixelFormat_PixelGetter       GetPixel;
05059 
05060                                 if ( P->Data )
05061                                 {
05062                                         Bits = P->Data;
05063                                 }
05064                                 else if ( P->DriverBits )
05065                                 {
05066                                         Bits = P->DriverBits;
05067                                 }
05068 
05069                                 ops = gePixelFormat_GetOperations(P->Format);
05070                                 assert(ops);
05071 
05072                                 GetPixel = ops->GetPixel;
05073                                 PutPixel = ops->PutPixel;
05074 
05075                                 for(p=0;p<P->Size;p++)
05076                                 {
05077                                         pBits = Bits;
05078                                         Pixel = GetPixel(&Bits);
05079                                         if ( p == P->ColorKeyIndex )
05080                                         {
05081                                                 PutPixel(&pBits,P->ColorKey);
05082                                         }
05083                                         else if ( Pixel == P->ColorKey )
05084                                         {
05085                                                 Pixel ^= 1;
05086                                                 PutPixel(&pBits,Pixel);
05087                                         }
05088                                 }
05089                         }
05090                 }
05091                 if ( P->DriverHandle )
05092                 {
05093                         if ( ! P->Driver->THandle_UnLock(P->DriverHandle,0) )
05094                                 return GE_FALSE;
05095                         P->DriverBits = NULL;
05096                 }
05097         }
05098 return GE_TRUE;
05099 }
05100 
05101 GENESISAPI geBoolean GENESISCC geBitmap_Palette_SetFormat(geBitmap_Palette * P,gePixelFormat Format)
05102 {
05103 void * NewData;
05104         
05105         assert(P);
05106 
05107         if ( P->DriverHandle ) // can't change format on card!
05108                 return GE_FALSE;
05109 
05110         assert( ! P->HasColorKey ); // can't have colorkey accept on Glide
05111 
05112         if ( Format == P->Format )
05113                 return GE_TRUE;
05114 
05115         NewData = geRam_Allocate( gePixelFormat_BytesPerPel(Format) * P->Size );
05116         if ( ! NewData )
05117                 return GE_FALSE;
05118 
05119         if ( ! geBitmap_Palette_BlitData(P->Format,P->Data,NULL,Format,NewData,NULL,P->Size) )
05120         {
05121                 geRam_Free(NewData);
05122                 return GE_FALSE;
05123         }
05124 
05125         geRam_Free(P->Data);
05126         P->Data = NewData;
05127         P->Format = Format;
05128 
05129 return GE_TRUE;
05130 }
05131 
05132 GENESISAPI geBoolean GENESISCC geBitmap_Palette_GetData(const geBitmap_Palette *P,void *Into,gePixelFormat Format,int Size)
05133 {
05134 gePixelFormat FmFormat;
05135 const void *FmData;
05136 int FmSize;
05137 geBoolean Ret;
05138 
05139         assert(P);
05140         assert(Into);
05141 
05142         if ( ! geBitmap_Palette_Lock((geBitmap_Palette *)P,(void **)&FmData,&FmFormat,&FmSize) )
05143                 return GE_FALSE;
05144 
05145         if ( FmSize < Size )
05146                 Size = FmSize;
05147 
05148         Ret = geBitmap_Palette_BlitData(FmFormat,FmData,P,Format,Into,NULL,Size);
05149         
05150         geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05151 
05152 return Ret;
05153 }
05154 
05155 GENESISAPI geBoolean GENESISCC geBitmap_Palette_GetInfo(const geBitmap_Palette *P,geBitmap_Info *pInfo)
05156 {
05157         assert(P && pInfo);
05158 
05159         pInfo->Width = pInfo->Stride = P->Size;
05160         pInfo->Height = 1;
05161 
05162         pInfo->Format = P->Format;
05163         pInfo->HasColorKey = P->HasColorKey;
05164         pInfo->ColorKey = P->ColorKey;
05165         pInfo->MaximumMip = pInfo->MinimumMip = 0;
05166         pInfo->Palette = NULL;
05167 
05168 return GE_TRUE;
05169 }
05170 
05171 GENESISAPI geBoolean GENESISCC geBitmap_Palette_SetData(geBitmap_Palette *P,const void *From,gePixelFormat Format,int Colors)
05172 {
05173 gePixelFormat PalFormat;
05174 void *PalData;
05175 int PalSize;
05176 geBoolean Ret;
05177 
05178         assert(P);
05179         assert(From);
05180 
05181         if ( ! geBitmap_Palette_Lock(P,&PalData,&PalFormat,&PalSize) )
05182                 return GE_FALSE;
05183 
05184         if ( PalSize < Colors )
05185                 Colors = PalSize;
05186 
05187         Ret = geBitmap_Palette_BlitData(Format,From,NULL,PalFormat,PalData,P,Colors);
05188         
05189         if ( ! geBitmap_Palette_UnLock(P) )
05190                 return GE_FALSE;
05191 
05192 return Ret;
05193 }
05194 
05195 GENESISAPI geBoolean GENESISCC geBitmap_Palette_Copy(const geBitmap_Palette * Fm,geBitmap_Palette * To)
05196 {
05197 gePixelFormat FmFormat,ToFormat;
05198 void *FmData,*ToData;
05199 int FmSize,ToSize;
05200 geBoolean Ret;
05201 
05202         assert(Fm);
05203         assert(To);
05204         if ( Fm == To )
05205                 return GE_TRUE;
05206 
05207         if ( ! geBitmap_Palette_Lock((geBitmap_Palette *)Fm,&FmData,&FmFormat,&FmSize) )
05208                 return GE_FALSE;
05209 
05210         if ( ! geBitmap_Palette_Lock(To,&ToData,&ToFormat,&ToSize) )
05211         {
05212                 geBitmap_Palette_UnLock((geBitmap_Palette *)Fm);
05213                 return GE_FALSE;
05214         }
05215 
05216         if ( FmSize > ToSize )
05217         {
05218                 Ret = GE_FALSE;
05219         }
05220         else
05221         {
05222                 Ret = geBitmap_Palette_BlitData(FmFormat,FmData,Fm,ToFormat,ToData,To,FmSize);
05223         }
05224         
05225         geBitmap_Palette_UnLock((geBitmap_Palette *)Fm);
05226         geBitmap_Palette_UnLock(To);
05227 
05228 return Ret;
05229 }
05230 
05231 GENESISAPI geBoolean GENESISCC geBitmap_Palette_SetEntryColor(geBitmap_Palette *P,int Color,int R,int G,int B,int A)
05232 {
05233         assert(P);
05234         
05235         if ( A < 80 && ! gePixelFormat_HasAlpha(P->Format) && P->HasColorKey )
05236         {
05237                 return geBitmap_Palette_SetEntry(P,Color,P->ColorKey);
05238         }
05239         else if ( P->HasColorKey )
05240         {
05241         uint32 Pixel;
05242 
05243                 // might have alpha AND colorkey !
05244 
05245                 if ( Color == P->ColorKeyIndex ) // and A > 80 because of the above
05246                         return GE_FALSE;
05247 
05248                 Pixel = gePixelFormat_ComposePixel(P->Format,R,G,B,A);
05249                 if ( Pixel == P->ColorKey )
05250                         Pixel ^= 1;
05251                         
05252                 return geBitmap_Palette_SetEntry(P,Color,Pixel);
05253         }
05254         else
05255         {
05256                 return geBitmap_Palette_SetEntry(P,Color,gePixelFormat_ComposePixel(P->Format,R,G,B,A));
05257         }
05258 }
05259 
05260 GENESISAPI geBoolean GENESISCC geBitmap_Palette_GetEntryColor(const geBitmap_Palette *P,int Color,int *R,int *G,int *B,int *A)
05261 {
05262 uint32 Pixel;
05263         assert(P);
05264         if ( P->HasColorKey )
05265         {
05266                 if ( Color == P->ColorKeyIndex )
05267                 {
05268                         *R = *G = *B = *A = 0;
05269                         return GE_TRUE;
05270                 }
05271                 else
05272                 {
05273                         if ( ! geBitmap_Palette_GetEntry(P,Color,&Pixel) )
05274                                 return GE_FALSE;
05275                         if ( Pixel == P->ColorKey )
05276                         {
05277                                 *R = *G = *B = *A = 0;
05278                         }
05279                         else
05280                         {
05281                                 gePixelFormat_DecomposePixel(P->Format,Pixel,R,G,B,A);
05282                         }
05283                 }
05284         }
05285         else
05286         {
05287                 if ( ! geBitmap_Palette_GetEntry(P,Color,&Pixel) )
05288                         return GE_FALSE;
05289                 gePixelFormat_DecomposePixel(P->Format,Pixel,R,G,B,A);
05290         }
05291         return GE_TRUE;
05292 }
05293 
05294 GENESISAPI geBoolean GENESISCC geBitmap_Palette_SetEntry(geBitmap_Palette *P,int Color,uint32 Pixel)
05295 {
05296         assert(P);
05297 
05298         if ( P->HasColorKey )
05299         {
05300                 if ( Color == P->ColorKeyIndex )
05301                         return GE_TRUE;
05302         }
05303 
05304         if ( P->Data )
05305         {
05306         char *Data;
05307 
05308                 if ( Color >= P->Size )
05309                         return GE_FALSE;
05310 
05311                 Data = (char *)(P->Data) + Color * gePixelFormat_BytesPerPel(P->Format);
05312                 gePixelFormat_PutPixel(P->Format,&Data,Pixel);
05313         }
05314         else
05315         {
05316         char *Data;
05317         gePixelFormat Format;
05318         int Size;
05319 
05320                 if ( ! geBitmap_Palette_Lock(P,&Data,&Format,&Size) )
05321                         return GE_FALSE;
05322 
05323                 if ( Color >= Size )
05324                 {
05325                         geBitmap_Palette_UnLock(P);
05326                         return GE_FALSE;
05327                 }
05328 
05329                 Data += Color * gePixelFormat_BytesPerPel(Format);
05330                 gePixelFormat_PutPixel(Format,&Data,Pixel);
05331 
05332                 geBitmap_Palette_UnLock(P);
05333         }
05334 return GE_TRUE;
05335 }
05336 
05337 GENESISAPI geBoolean GENESISCC geBitmap_Palette_GetEntry(const geBitmap_Palette *P,int Color,uint32 *Pixel)
05338 {
05339 
05340         assert(P);
05341 
05342         if ( P->Data )
05343         {
05344         char *Data;
05345 
05346                 if ( Color >= P->Size )
05347                         return GE_FALSE;
05348 
05349                 Data = (char *)(P->Data) + Color * gePixelFormat_BytesPerPel(P->Format);
05350                 *Pixel = gePixelFormat_GetPixel(P->Format,&Data);
05351         }
05352         else
05353         {
05354         char *Data;
05355         gePixelFormat Format;
05356         int Size;
05357 
05358                 // must cast away const cuz we don't have a lockforread/write on palettes
05359 
05360                 if ( ! geBitmap_Palette_Lock((geBitmap_Palette *)P,&Data,&Format,&Size) )
05361                         return GE_FALSE;
05362 
05363                 if ( Color >= Size )
05364                 {
05365                         geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05366                         return GE_FALSE;
05367                 }
05368 
05369                 Data += Color * gePixelFormat_BytesPerPel(Format);
05370                 *Pixel = gePixelFormat_GetPixel(Format,&Data);
05371 
05372                 geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05373         }
05374 return GE_TRUE;
05375 }
05376 
05377 #define PALETTE_INFO_FORMAT_MASK        (0x1F)
05378 #define PALETTE_INFO_FLAG_SIZE256       (1<<5)  // 5 is the low
05379 #define PALETTE_INFO_FLAG_COMPRESS      (1<<6)
05380 
05381 GENESISAPI geBitmap_Palette * GENESISCC geBitmap_Palette_CreateFromFile(geVFile *F)
05382 {
05383 geBitmap_Palette * P;
05384 int Size;
05385 gePixelFormat Format;
05386 uint8 flags,b;
05387 
05388         if ( ! geVFile_Read(F, &flags, sizeof(flags)) )
05389                 return NULL;
05390 
05391         Format = flags & PALETTE_INFO_FORMAT_MASK;
05392 
05393         if ( flags & PALETTE_INFO_FLAG_SIZE256 )
05394         {
05395                 Size = 256;
05396         }
05397         else
05398         {
05399                 if ( ! geVFile_Read(F, &b, sizeof(b)) )
05400                         return NULL;
05401                 Size = b;
05402         }
05403 
05404         P = geBitmap_Palette_Create(Format,Size);
05405         if ( ! P )
05406                 return NULL;
05407 
05408         if ( flags & PALETTE_INFO_FLAG_COMPRESS )
05409         {
05410                 geErrorLog_AddString(-1,"Bitmap_Palette_CreateFromFile : codePal failed!",NULL);
05411                 return GE_FALSE;
05412         }
05413         else
05414         {
05415                 if ( ! geVFile_Read(F, P->Data, gePixelFormat_BytesPerPel(P->Format) * P->Size) )
05416                 {
05417                         geRam_Free(P);
05418                         return NULL;
05419                 }
05420         }
05421 
05422 return P;
05423 }
05424 
05425 GENESISAPI geBoolean GENESISCC geBitmap_Palette_WriteToFile(const geBitmap_Palette *P,geVFile *F)
05426 {
05427 int Size;
05428 gePixelFormat Format;
05429 void *Data;
05430 
05431         assert(P);
05432 
05433         assert( P->HasColorKey == GE_FALSE ); // system palettes can't have color key!
05434 
05435         // we usually write the palette's header in one byte :^)
05436 
05437         if ( ! geBitmap_Palette_Lock((geBitmap_Palette *)P,&Data,&Format,&Size) )
05438                 return GE_FALSE;
05439 
05440         {
05441         uint8 b;
05442 
05443                 b = Format;
05444                 assert( b < 32 );
05445                 if ( Size == 256 )
05446                         b |= PALETTE_INFO_FLAG_SIZE256;
05447 
05448                 if ( ! geVFile_Write(F, &b, sizeof(b)) )
05449                 {
05450                         geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05451                         return GE_FALSE;
05452                 }
05453 
05454                 if ( Size != 256 )
05455                 {
05456                         assert(Size < 256);
05457                         b = Size;
05458                         
05459                         if ( ! geVFile_Write(F, &b, sizeof(b)) )
05460                         {
05461                                 geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05462                                 return GE_FALSE;
05463                         }
05464                 }
05465         }
05466 
05467         if ( ! geVFile_Write(F, Data, gePixelFormat_BytesPerPel(Format) * Size) )
05468         {
05469                 geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05470                 return GE_FALSE;
05471         }
05472                 
05473         geBitmap_Palette_UnLock((geBitmap_Palette *)P);
05474 
05475 return GE_TRUE;
05476 }
05477 
05478 /*}{ ******************** IsValid funcs **************************/
05479 
05480 // {} put ErrorLogs indicating where we failed in _IsValid
05481 
05482 geBoolean geBitmap_IsValid(const geBitmap *Bmp)
05483 {
05484         if ( ! Bmp ) return GE_FALSE;
05485 
05486         assert( Bmp->RefCount >= 1 );
05487 
05488         assert( ! (Bmp->LockCount && Bmp->LockOwner) );
05489 
05490         assert( !( (Bmp->DriverDataChanged || Bmp->DriverBitsLocked) &&
05491                         ! Bmp->DriverHandle ) );
05492         assert( ! (Bmp->DriverHandle && ! Bmp->Driver) );
05493 
05494         if ( ! geBitmap_Info_IsValid(&(Bmp->Info)) )
05495                 return GE_FALSE;
05496 
05497         if ( Bmp->DriverHandle && ! geBitmap_Info_IsValid(&(Bmp->DriverInfo)) )
05498                 return GE_FALSE;
05499 
05500         if ( Bmp->LockOwner && Bmp->Alpha )
05501                 assert( Bmp->Alpha->LockOwner );
05502 
05503         if ( Bmp->LockOwner )
05504         {
05505                 assert(Bmp->LockOwner != Bmp);
05506                 assert( Bmp->LockOwner->LockCount );
05507         }
05508 
05509         if ( Bmp->DataOwner )
05510         {
05511                 assert(Bmp->DataOwner != Bmp);
05512                 assert( Bmp->DataOwner->RefCount >= 2 );
05513         }
05514 
05515         if ( Bmp->Alpha )
05516         {
05517                 assert(Bmp->Alpha != Bmp);
05518                 if ( ! geBitmap_IsValid(Bmp->Alpha) )
05519                         return GE_FALSE;
05520         }
05521 
05522 return GE_TRUE;
05523 }
05524 
05525 geBoolean geBitmap_Info_IsValid(const geBitmap_Info *Info)
05526 {
05527         if ( ! Info ) return GE_FALSE;
05528 
05529         assert( Info->Width > 0 && Info->Height > 0 && Info->Stride >= Info->Width );
05530 
05531         assert( Info->MinimumMip >= 0 && Info->MaximumMip < MAXMIPLEVELS && Info->MinimumMip <= Info->MaximumMip );
05532 
05533         assert( Info->Format > GE_PIXELFORMAT_NO_DATA && Info->Format < GE_PIXELFORMAT_COUNT );
05534 
05535 //      ok to have palette on non-palettized
05536 //      if ( ! gePixelFormat_HasPalette(Info->Format) && Info->Palette )
05537 //              return GE_FALSE;
05538 
05539         if ( Info->Palette )
05540                 if ( ! geBitmap_Palette_IsValid(Info->Palette) )
05541                         return GE_FALSE;
05542 
05543 return GE_TRUE;
05544 }
05545 
05546 geBoolean geBitmap_Palette_IsValid(const geBitmap_Palette *Pal)
05547 {
05548         if ( ! Pal ) return GE_FALSE;
05549 
05550         assert(  Pal->Data ||  Pal->DriverHandle );
05551         assert( !Pal->Data || !Pal->DriverHandle );
05552 
05553         assert( (Pal->Driver && Pal->DriverHandle) ||
05554                 (! Pal->Driver && ! Pal->DriverHandle) );
05555 
05556         assert( Pal->RefCount >= 1 && Pal->Size >= 1 );
05557         assert( Pal->Format > GE_PIXELFORMAT_NO_DATA && Pal->Format < GE_PIXELFORMAT_COUNT );
05558 
05559 return GE_TRUE;
05560 }
05561 
05562 #ifdef _DEBUG
05563 GENESISAPI uint32 GENESISCC geBitmap_Debug_GetCount(void)
05564 {
05565 
05566         return _Bitmap_Debug_ActiveCount;
05567 }
05568 GENESISAPI uint32 GENESISCC geBitmap_Debug_GetRefs(void)
05569 {
05570 
05571         return _Bitmap_Debug_ActiveRefs;
05572 }
05573 #endif
05574 
05575 /*}{ ******************** Average Color **************************/
05576 
05577 GENESISAPI geBoolean GENESISCC geBitmap_GetAverageColor(const geBitmap *Bmp,int *pR,int *pG,int *pB)
05578 {
05579         {
05580         int bpp,x,y,w,h,xtra,dock;
05581         gePixelFormat Format;
05582         uint8 * ptr;
05583         uint32 R,G,B,A,Rt,Gt,Bt,cnt,ck;
05584 
05585                 //{} Rt == Rtotal , probably won't overflow; we can handle a 4096x4095 solid-white image
05586 
05587                 if ( Bmp->DriverHandle && Bmp->DriverDataChanged )
05588                 {
05589                         // must use the driver bits
05590                         if ( ! geBitmap_Update_DriverToSystem((geBitmap *)Bmp) )
05591                         {
05592                                 geErrorLog_AddString(-1,"Bitmap_AverageColor : DriverToSystem failed!",NULL);
05593                                 return GE_FALSE;
05594                         }
05595                 }
05596 
05597                 Format = Bmp->Info.Format;
05598                 bpp = gePixelFormat_BytesPerPel(Format);
05599                 ptr = Bmp->Data[0];     
05600 
05601                 if ( ! ptr || bpp < 1 )
05602                 {
05603                         geErrorLog_AddString(-1,"Bitmap_AverageColor : no data!",NULL);
05604                         return GE_FALSE;
05605                 }
05606 
05607                 w = Bmp->Info.Width;
05608                 h = Bmp->Info.Height;
05609                 xtra = (Bmp->Info.Stride - w)*bpp;
05610                 ck = Bmp->Info.ColorKey;
05611                 dock = Bmp->Info.HasColorKey;
05612 
05613                 Rt = Gt = Bt = cnt = 0;
05614 
05615                 if ( gePixelFormat_HasPalette(Format) )
05616                 {
05617                         // <> Blech!
05618                         geErrorLog_AddString(-1,"Bitmap_AverageColor : doesn't support palettized yet!",NULL);
05619                         #pragma message("Bitmap_AverageColor : doesn't support palettized yet!")
05620                         return GE_FALSE;
05621                 }
05622                 else
05623                 {
05624                 const gePixelFormat_Operations * ops;
05625                 gePixelFormat_ColorGetter GetColor;
05626                 gePixelFormat_PixelGetter GetPixel;
05627                 gePixelFormat_Decomposer Decomposer;
05628 
05629                         assert( gePixelFormat_IsRaw(Format) );
05630 
05631                         ops = gePixelFormat_GetOperations(Format);
05632                         GetColor = ops->GetColor;
05633                         GetPixel = ops->GetPixel;
05634                         Decomposer = ops->DecomposePixel;
05635 
05636                         if ( dock )
05637                         {
05638                                 for(y=h;y--;)
05639                                 {
05640                                         for(x=w;x--;)
05641                                         {
05642                                         uint32 Pixel;
05643                                                 Pixel = GetPixel(&ptr);
05644                                                 if ( Pixel != ck )
05645                                                 {
05646                                                         Decomposer(Pixel,&R,&G,&B,&A);
05647                                                         Rt += R; Gt += G; Bt += B;
05648                                                         cnt ++;
05649                                                 }
05650                                         }
05651                                         ptr += xtra;
05652                                 }
05653                         }
05654                         else
05655                         {
05656                                 for(y=h;y--;)
05657                                 {
05658                                         for(x=w;x--;)
05659                                         {
05660                                                 GetColor(&ptr,&R,&G,&B,&A);
05661                                                 if ( A > 80 )
05662                                                 {
05663                                                         Rt += R; Gt += G; Bt += B;
05664                                                         cnt ++;
05665                                                 }
05666                                         }
05667                                         ptr += xtra;
05668                                 }
05669                         }
05670                 }
05671 
05672                 if ( pR ) *pR = (Rt + (cnt>>1)) / cnt;
05673                 if ( pG ) *pG = (Gt + (cnt>>1)) / cnt;
05674                 if ( pB ) *pB = (Bt + (cnt>>1)) / cnt;
05675         }
05676 
05677 return GE_TRUE;
05678 }
05679 
05680 /*}{ ******************** EOF **************************/
05681 

Generated on Tue Sep 30 12:35:17 2003 for GTestAndEngine by doxygen 1.3.2