00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "rSDL.h"
00029
00030 #include "aa_config.h"
00031
00032 #include "rTexture.h"
00033 #include "rDisplayList.h"
00034 #include "tString.h"
00035 #include "rScreen.h"
00036 #include "tDirectories.h"
00037 #include "tLocale.h"
00038 #include "tConsole.h"
00039 #include "tException.h"
00040 #include "tResourceManager.h"
00041
00042 #include <sstream>
00043
00044 #ifndef DEDICATED
00045 #include "rRender.h"
00046 #include "rGL.h"
00047
00048
00049
00050 #ifdef _MSC_VER
00051 #include <SDL_image.h>
00052 #else
00053 #ifdef __MINGW32__
00054 #include <SDL_image.h>
00055 #else
00056 #ifdef HAVE_SDL_IMG_H
00057 #include <SDL_image.h>
00058 #else
00059 #ifdef HAVE_SDL_SDL_IMAGE_H
00060 #include <SDL/SDL_image.h>
00061 #else
00062 #ifdef HAVE_IMG_H
00063 #include <IMG.h>
00064 #else
00065 #ifdef HAVE_SDL_IMG_H
00066 #include <SDL/IMG.h>
00067 #else
00068 #ifdef HAVE_LIBSDL
00069 #include <SDL_image.h>
00070 #else
00071 #ifdef HAVE_LIBIMG
00072 #include <IMG.h>
00073 #else
00074
00075 #include <SDL_image.h>
00076 #endif
00077 #endif
00078 #endif
00079 #endif
00080 #endif
00081 #endif
00082 #endif
00083 #endif
00084 #endif
00085
00086
00087 #ifndef GL_CLAMP_TO_EDGE
00088 #define GL_CLAMP_TO_EDGE GL_CLAMP
00089 #endif
00090
00091
00092
00093
00094
00095
00099
00100
00101 rSurface::rSurface( char const * fileName, tPath const * path )
00102 {
00103 Init();
00104 Create( fileName, path );
00105 }
00106
00107
00108
00109
00110
00111
00114
00115
00116 rSurface::~rSurface( void )
00117 {
00118 Clear();
00119 }
00120
00121
00122
00123
00124
00125
00128
00129
00130 rSurface::rSurface( void )
00131 {
00132 Init();
00133 }
00134
00135
00136
00137
00138
00139
00143
00144
00145 rSurface::rSurface( rSurface const & other )
00146 {
00147 Init();
00148 CopyFrom( other );
00149 }
00150
00151
00152
00153
00154
00155
00160
00161
00162 rSurface & rSurface::operator =( rSurface const & other )
00163 {
00164 if ( &other != this )
00165 {
00166 Clear();
00167 CopyFrom( other );
00168 }
00169
00170 return *this;
00171 }
00172
00173
00174
00175
00176
00177
00180
00181
00182 void rSurface::Init( void )
00183 {
00184 surface_ = 0;
00185 format_ = 0;
00186 }
00187
00188
00189
00190
00191
00192
00195
00196
00197 void rSurface::Clear( void )
00198 {
00199 #ifndef DEDICATED
00200
00201 if ( surface_ )
00202 SDL_FreeSurface( surface_ );
00203
00204 #endif
00205 surface_ = 0;
00206 }
00207
00208
00209
00210
00211
00212
00216
00217
00218 void rSurface::Create( char const * fileName, tPath const *path )
00219 {
00220 #ifndef DEDICATED
00221 sr_LockSDL();
00222
00223 IMG_InvertAlpha(true);
00224
00225
00226 SDL_Surface *surface;
00227 if(path) {
00228 tString s = path->GetReadPath( fileName );
00229 surface = IMG_Load(s);
00230 } else {
00231 surface = IMG_Load(fileName);
00232 }
00233 Create(surface);
00234
00235
00236
00237
00238 sr_UnlockSDL();
00239 #endif
00240 }
00241
00242
00243
00244
00245
00246
00250
00251
00252 void rSurface::Create( SDL_Surface * surface )
00253 {
00254 #ifndef DEDICATED
00255
00256 Clear();
00257
00258
00259 surface_ = surface;
00260
00261
00262 if ( surface_ )
00263 {
00264 switch (surface_->format->BytesPerPixel){
00265 case 1:
00266 format_ = GL_LUMINANCE;
00267 break;
00268
00269 case 2:
00270 format_ = GL_LUMINANCE8_ALPHA8;
00271 break;
00272
00273 case 3:
00274 format_ = GL_RGB;
00275 break;
00276
00277 case 4:
00278 format_ = GL_RGBA;
00279 break;
00280
00281 default:
00282 {
00283
00284
00285 SDL_Surface *dummy =
00286 SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1,
00287 32,
00288 0x0000FF, 0x00FF00,
00289 0xFF0000 ,0xFF000000);
00290
00291 SDL_Surface *convtex =
00292 SDL_ConvertSurface(surface_, dummy->format, SDL_SWSURFACE);
00293
00294 SDL_FreeSurface(surface_);
00295 surface_ = convtex;
00296 SDL_FreeSurface(dummy);
00297
00298 format_ = GL_RGBA;
00299 }
00300 break;
00301 }
00302 }
00303 #endif
00304 }
00305
00306
00307
00308
00309
00310
00314
00315
00316 void rSurface::CopyFrom( rSurface const & other )
00317 {
00318 #ifndef DEDICATED
00319 tASSERT( 0 == surface_ );
00320 tASSERT( other.surface_ );
00321
00322
00323 surface_ = SDL_ConvertSurface(other.surface_, other.surface_->format, SDL_SWSURFACE);
00324
00325
00326 format_ = other.format_;
00327 #endif
00328 }
00329
00330
00331
00332
00333
00334
00337
00338
00339 rITexture::~rITexture( void )
00340 {
00341 s_textures_.Remove(this,id_);
00342 }
00343
00344
00345
00346
00347
00348
00351
00352
00353 void rITexture::UnloadAll( void )
00354 {
00355 for(int i=s_textures_.Len()-1;i>=0;i--)
00356 {
00357 s_textures_(i)->Unload();
00358 }
00359 }
00360
00361
00362
00363
00364
00365
00368
00369
00370 void rITexture::LoadAll( void )
00371 {
00372
00373 for(int i=s_textures_.Len()-1;i>=0;i--)
00374 {
00375 s_textures_(i)->Select();
00376
00377
00378 }
00379
00380 }
00381
00382
00383
00384
00385
00386
00389
00390
00391 rITexture::rITexture( void )
00392 : id_( -1 )
00393 {
00394 }
00395
00396
00397
00398
00399
00400
00404
00405
00406 void rITexture::OnSelect( bool enforce )
00407 {
00408 if ( id_ < 0 )
00409 s_textures_.Add(this,id_);
00410 }
00411
00412
00413
00414
00415
00416
00419
00420
00421 void rITexture::OnUnload( void )
00422 {
00423 }
00424
00425
00426
00427
00428
00429
00436
00437
00438 rISurfaceTexture::rISurfaceTexture( int group, bool repx, bool repy, bool storeAlpha )
00439 : group_( group ), textureModeLast_( -1), repx_( repx ), repy_( repy ), storeAlpha_( storeAlpha )
00440 {
00441 }
00442
00443
00444
00445
00446
00447
00450
00451
00452 rISurfaceTexture::~rISurfaceTexture( void )
00453 {
00454 if (tint_.IsValid() )
00455 {
00456 rDisplayList::ClearAll();
00457 }
00458 }
00459
00460
00461
00462
00463
00464
00468
00469
00470 void rISurfaceTexture::ProcessImage( SDL_Surface * surface )
00471 {
00472 }
00473
00474
00475
00476
00477
00478
00482
00483
00484 void rISurfaceTexture::Upload( rSurface & surface )
00485 {
00486 #ifndef DEDICATED
00487 sr_LockSDL();
00488 GLenum texformat = surface.GetFormat();
00489 SDL_Surface * tex = surface.GetSurface();
00490 tASSERT( tex );
00491
00492 bool texalpha=tex->format->Amask;
00493
00494 ProcessImage(tex);
00495
00496 if(repx_)
00497 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
00498 else
00499 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
00500 if(repy_)
00501 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
00502 else
00503 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
00504
00505 int format;
00506 if (sr_texturesTruecolor)
00507 if (storageHack_ || ( storeAlpha_ && texalpha ) )
00508 format=GL_RGBA8;
00509 else
00510 format=GL_RGB8;
00511 else
00512 if (storageHack_ || ( storeAlpha_ && texalpha ) )
00513 format=GL_RGBA4;
00514 else
00515 format=GL_RGB5;
00516
00517 gluBuild2DMipmaps(GL_TEXTURE_2D,format,tex->w,tex->h,
00518 texformat,GL_UNSIGNED_BYTE,tex->pixels);
00519
00520 sr_UnlockSDL();
00521 #endif
00522 }
00523
00524
00525
00526
00527
00528
00532
00533
00534 void rISurfaceTexture::OnSelect( bool enforce )
00535 {
00536 #ifndef DEDICATED
00537 if(sr_glOut)
00538 {
00539 RenderEnd(true);
00540
00541 int texmod=rTextureGroups::TextureMode[group_];
00542 if (enforce && texmod<0) texmod=GL_NEAREST_MIPMAP_NEAREST;
00543
00544 if(textureModeLast_!=texmod)
00545 {
00546
00547 Unload();
00548
00549
00550 if (texmod>0){
00551
00552 rDisplayList::Cancel();
00553
00554 glBindTexture(GL_TEXTURE_2D,tint_);
00555
00556 if (textureModeLast_<0)
00557 {
00558
00559 OnSelect();
00560 }
00561
00562
00563 glEnable(GL_TEXTURE_2D);
00564
00565 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
00566 texmod);
00567
00568 switch(texmod)
00569 {
00570 case GL_NEAREST:
00571 case GL_NEAREST_MIPMAP_NEAREST:
00572 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
00573 GL_NEAREST);
00574 break;
00575 default:
00576 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
00577 GL_LINEAR);
00578 break;
00579 }
00580
00581 }
00582 else
00583 {
00584 glDisable(GL_TEXTURE_2D);
00585 }
00586 }
00587 else
00588 {
00589 glBindTexture(GL_TEXTURE_2D,tint_);
00590 if (texmod>0)
00591 {
00592 glEnable(GL_TEXTURE_2D);
00593 }
00594 else
00595 {
00596 glDisable(GL_TEXTURE_2D);
00597 }
00598 }
00599 textureModeLast_=texmod;
00600 }
00601 rITexture::OnSelect(enforce);
00602 #endif
00603 }
00604
00605
00606
00607
00608
00609
00614
00615
00616 void rISurfaceTexture::OnSelect()
00617 {
00618 }
00619
00620
00621
00622
00623
00624
00627
00628
00629 void rISurfaceTexture::OnUnload( void )
00630 {
00631 #ifndef DEDICATED
00632 if ( tint_.IsValid() )
00633 {
00634 rDisplayList::ClearAll();
00635 }
00636
00637 tint_.Delete();
00638 textureModeLast_=-100;
00639 rITexture::OnUnload();
00640 #endif
00641 }
00642
00643
00644
00645
00646
00647
00650
00651
00652 void rISurfaceTexture::StoreAlpha( void )
00653 {
00654 storeAlpha_ = true;
00655 }
00656
00657
00658
00659
00660
00661
00669
00670
00671 rFileTexture::rFileTexture( int group, char const * fileName, bool repx, bool repy, bool storeAlpha, tPath const *path )
00672 : rISurfaceTexture( group, repx, repy, storeAlpha )
00673 , fileName_( fileName )
00674 , path_(path)
00675 {
00676 }
00677
00678
00679
00680
00681
00682
00685
00686
00687 rFileTexture::~rFileTexture( void )
00688 {
00689 }
00690
00691
00692
00693
00694
00695
00698
00699
00700 void rFileTexture::OnSelect()
00701 {
00702 #ifndef DEDICATED
00703
00704 rSurface surface( fileName_, path_ );
00705 if ( surface.GetSurface() )
00706 {
00707 this->Upload( surface );
00708 }
00709 else if (s_reportErrors_)
00710 {
00711 throw tGenericException( tOutput( "$texture_error_filenotfound", fileName_ ), tOutput("$texture_error_filenotfound_title") );
00712 }
00713 rISurfaceTexture::OnSelect();
00714 #endif
00715 }
00716
00717
00718
00719
00720
00721
00729
00730
00731 rSurfaceTexture::rSurfaceTexture( int group, rSurface const & surface, bool repx, bool repy, bool storeAlpha )
00732 : rISurfaceTexture( group, repx, repy, storeAlpha )
00733 , surface_( surface )
00734 {
00735 }
00736
00737
00738
00739
00740
00741
00744
00745
00746 rSurfaceTexture::~rSurfaceTexture( void )
00747 {
00748 }
00749
00750
00751
00752
00753
00754
00757
00758
00759 void rSurfaceTexture::OnSelect()
00760 {
00761 #ifndef DEDICATED
00762
00763 if ( surface_.GetSurface() )
00764 {
00765 rSurface copy( surface_ );
00766 this->Upload( copy );
00767 rISurfaceTexture::OnSelect();
00768 }
00769 #endif
00770 }
00771
00772
00773 bool rISurfaceTexture::s_reportErrors_=false;
00774 tList<rITexture> rITexture::s_textures_;
00775
00776 int rTextureGroups::TextureMode[rTextureGroups::TEX_GROUPS];
00777
00778 char const * rTextureGroups::TextureGroupDescription[rTextureGroups::TEX_GROUPS]=
00779 {
00780 "$texture_mode_0_help",
00781 "$texture_mode_1_help",
00782 "$texture_mode_2_help",
00783 "$texture_mode_3_help",
00784 };
00785
00786 bool rISurfaceTexture::storageHack_ = false;
00787
00788
00789
00790
00791
00792 static rCallbackBeforeScreenModeChange unload(&rITexture::UnloadAll);
00793
00794
00795
00796 rResourceTexture::texlist_t rResourceTexture::textures;
00797
00798 rResourceTexture::rResourceTexture(tResourcePath const &path, bool repx, bool repy) : repx_(repx), repy_(repy) {
00799 if(!path.Valid()) {
00800 tex_ = 0;
00801 return;
00802 }
00803 for(texlist_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) {
00804 if((*iter)->path_ == path) {
00805 tex_ = *iter;
00806 tex_->Use();
00807 return;
00808 }
00809 }
00810 tex_ = new tex_t(path);
00811 }
00812
00813 rResourceTexture::InternalTex::InternalTex(tResourcePath const &path) : rFileTexture(rTextureGroups::TEX_OBJ, tResourceManager::locateResource(path.Path().c_str()).c_str(), true, true, true, 0), use_(1), path_(path) {
00814 textures.push_back(this);
00815 }
00816
00817 void rResourceTexture::InternalTex::Release() {
00818 if(--use_ < 1) {
00819 for(texlist_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) {
00820 if((*iter)->path_ == path_) {
00821 textures.erase(iter);
00822 break;
00823 }
00824 }
00825 Unload();
00826 delete this;
00827 }
00828 }
00829
00830 rResourceTexture &rResourceTexture::operator=(rResourceTexture const &other) {
00831 if(tex_ != other.tex_) {
00832 repx_ = other.repx_;
00833 repy_ = other.repy_;
00834 if(tex_) {
00835 tex_->Release();
00836 }
00837 tex_ = other.tex_;
00838 if(tex_) {
00839 tex_->Use();
00840 }
00841 }
00842 return *this;
00843 }
00844
00845 void rResourceTexture::Select() {
00846 #ifndef DEDICATED
00847 if(tex_) {
00848 tex_->Select();
00849
00850 if(repx_)
00851 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
00852 else
00853 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
00854 if(repy_)
00855 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
00856 else
00857 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
00858 } else {
00859 tERR_WARN("Trying to select a resource texture that's not loaded");
00860 }
00861 #endif
00862 }