Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

texture.cpp

Go to the documentation of this file.
00001 /*           Copyright (C) 2001 Sony Computer Entertainment America
00002                               All Rights Reserved
00003                                SCEA Confidential                                */
00004 
00005 #include "ps2s/gsmem.h"
00006 
00007 #include "GL/ps2gl.h"
00008 
00009 #include "ps2gl/debug.h"
00010 #include "ps2gl/texture.h"
00011 #include "ps2gl/glcontext.h"
00012 #include "ps2gl/dlist.h"
00013 #include "ps2gl/immgmanager.h"
00014 #include "ps2gl/dlgmanager.h"
00015 #include "ps2gl/metrics.h"
00016 
00017 /********************************************
00018  * CTexManager
00019  */
00020 
00021 CTexManager::CTexManager( CGLContext &context )
00022    : GLContext(context), IsTexEnabled(false), InsideDListDef(false),
00023      Cursor(0), LastTexSent(NULL),
00024      CurClut(NULL),
00025      TexMode(GS::TexMode::kModulate)
00026 {
00027    // clear the texture name entries
00028    for ( int i = 0; i < NumTexNames; i++ )
00029       TexNames[i] = NULL;
00030 
00031    // create the default texture
00032    DefaultTex = new CMMTexture( GS::kContext1 );
00033    CurTexture = DefaultTex;
00034 }
00035 
00036 CTexManager::~CTexManager()
00037 {
00038    delete DefaultTex;
00039    if ( CurClut ) delete CurClut;
00040 
00041    for ( int i = 0; i < NumTexNames; i++ ) {
00042       if (TexNames[i]) delete TexNames[i];
00043    }
00044 }
00045 
00046 class CSetTexEnabledCmd : public CDListCmd {
00047       bool      IsEnabled;
00048    public:
00049       CSetTexEnabledCmd( bool enabled ) : IsEnabled(enabled) {}
00050       CDListCmd* Play() {
00051          pGLContext->GetTexManager().SetTexEnabled(IsEnabled);
00052          return CDListCmd::GetNextCmd(this);
00053       }
00054 };
00055 
00056 void
00057 CTexManager::SetTexEnabled( bool yesNo )
00058 {
00059    if (! InsideDListDef) {
00060       if ( IsTexEnabled != yesNo ) {
00061          GLContext.TexEnabledChanged();
00062          GLContext.GetImmGeomManager().GetVsmManager().TexEnabledChanged(yesNo);
00063          IsTexEnabled = yesNo;
00064       }
00065    }
00066    else {
00067       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00068       dlist += CSetTexEnabledCmd( yesNo );
00069       GLContext.TexEnabledChanged();
00070    }
00071 }
00072 
00073 class CSetTexModeCmd : public CDListCmd {
00074       GS::tTexMode Mode;
00075    public:
00076       CSetTexModeCmd( GS::tTexMode mode ) : Mode(mode) {}
00077       CDListCmd* Play() {
00078          pGLContext->GetTexManager().SetTexMode(Mode);
00079          return CDListCmd::GetNextCmd(this);
00080       }
00081 };
00082 
00083 void
00084 CTexManager::SetTexMode( GS::tTexMode mode )
00085 {
00086    if ( ! InsideDListDef )
00087       TexMode = mode;
00088    else {
00089       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00090       dlist += CSetTexModeCmd( mode );
00091    }
00092 }
00093 
00094 void
00095 CTexManager::GenTextures( GLsizei numNewTexNames, GLuint *newTexNames )
00096 {
00097    for ( int curTexName = 0; curTexName < numNewTexNames; curTexName++ ) {
00098       // find the next free tex name and assign it
00099       int i;
00100       for ( i = 0; i < NumTexNames; i++ ) {
00101          // 0 is a reserved tex name in OGL -- don't alloc it
00102          if ( Cursor != 0 && TexNames[Cursor] == NULL ) break;
00103 
00104          IncCursor();
00105       }
00106       // did we go through all the names without finding any free ones?
00107       if ( i == NumTexNames ) {
00108             mError("No free texture names.  Time to write a less braindead tex manager.");
00109 
00110         // In release build, return sensible names on failure
00111         while(i < NumTexNames) {
00112             newTexNames[i] = 0;
00113             ++i;
00114         }
00115       } else {
00116             newTexNames[curTexName] = Cursor;
00117             IncCursor();
00118       }
00119    }
00120 }
00121 
00122 void
00123 CTexManager::UseCurTexture( CVifSCDmaPacket &renderPacket )
00124 {
00125    if ( IsTexEnabled ) {
00126       GS::tPSM psm = CurTexture->GetPSM();
00127       // do we need to send the clut?
00128       if ( psm == GS::kPsm8 || psm == GS::kPsm8h ) {
00129          mErrorIf( CurClut == NULL,
00130                    "Trying to use an indexed-color texture with no color table given!" );
00131          CurClut->Load( renderPacket );
00132       }
00133       // use the texture
00134       CurTexture->SetTexMode( TexMode );
00135       if ( CurTexture->GetPSM() == GS::kPsm8
00136            || CurTexture->GetPSM() == GS::kPsm8h )
00137          CurTexture->SetClut( *CurClut );
00138       CurTexture->Use( renderPacket );
00139    }
00140 }
00141 
00142 class CBindTextureCmd : public CDListCmd {
00143       unsigned int TexName;
00144    public:
00145       CBindTextureCmd( unsigned int name ) : TexName(name) {}
00146       CDListCmd* Play() {
00147          pGLContext->GetTexManager().BindTexture(TexName);
00148          return CDListCmd::GetNextCmd(this);
00149       }
00150 };
00151 
00152 void
00153 CTexManager::BindTexture( GLuint texNameToBind )
00154 {
00155    GLContext.TextureChanged();
00156 
00157    if ( ! InsideDListDef ) {
00158       if ( texNameToBind == 0 ) {
00159          // default texture
00160          CurTexture = DefaultTex;
00161       }
00162       else {
00163          if ( TexNames[texNameToBind] == NULL )
00164             TexNames[texNameToBind] = new CMMTexture( GS::kContext1 );
00165          CurTexture = TexNames[texNameToBind];
00166       }
00167 
00168       pglAddToMetric(kMetricsBindTexture);
00169    }
00170    else {
00171       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00172       dlist += CBindTextureCmd( texNameToBind );
00173    }
00174 }
00175 
00176 void
00177 CTexManager::DeleteTextures( GLsizei numToDelete, const GLuint *texNames )
00178 {
00179    for ( int i = 0; i < numToDelete; i++ ) {
00180       mErrorIf( TexNames[texNames[i]] == NULL,
00181                 "Trying to delete a texture that doesn't exist!" );
00182       GLuint texName = texNames[i];
00183       if ( CurTexture == TexNames[texName] )
00184          CurTexture = DefaultTex;
00185       delete TexNames[texName];
00186       TexNames[texName] = NULL;
00187    }
00188 }
00189 
00190 class CSetCurTexParamCmd : public CDListCmd {
00191       GLenum    PName;
00192       int       Param;
00193    public:
00194       CSetCurTexParamCmd( GLenum pname, int param ) : PName(pname), Param(param) {}
00195       CDListCmd* Play() {
00196          pGLContext->GetTexManager().SetCurTexParam(PName, Param);
00197          return CDListCmd::GetNextCmd(this);
00198       }
00199 };
00200 
00201 void
00202 CTexManager::SetCurTexParam( GLenum pname, GLint param )
00203 {
00204    if ( ! InsideDListDef ) {
00205       CMMTexture &tex = *CurTexture;
00206 
00207       switch( pname ) {
00208          case GL_TEXTURE_MIN_FILTER:
00209             tex.SetMinMode( (GS::tMinMode)(param & 0xf) );
00210             break;
00211          case GL_TEXTURE_MAG_FILTER:
00212             tex.SetMagMode( (GS::tMagMode)(param & 0xf) );
00213             break;
00214          case GL_TEXTURE_MIN_LOD:
00215          case GL_TEXTURE_MAX_LOD:
00216          case GL_TEXTURE_BASE_LEVEL:
00217          case GL_TEXTURE_MAX_LEVEL:
00218          case GL_TEXTURE_PRIORITY:
00219          case GL_TEXTURE_BORDER_COLOR:
00220             mNotImplemented( );
00221             break;
00222          case GL_TEXTURE_WRAP_S:
00223             tex.SetWrapModeS( (GS::tTexWrapMode)(param & 0xf) );
00224             break;
00225          case GL_TEXTURE_WRAP_T:
00226             tex.SetWrapModeT( (GS::tTexWrapMode)(param & 0xf) );
00227             break;
00228          case GL_TEXTURE_WRAP_R:
00229             mNotImplemented( "Sorry, only 2d textures." );
00230             break;
00231       }
00232    }
00233    else {
00234       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00235       dlist += CSetCurTexParamCmd(pname, param);
00236    }
00237 }
00238 
00239 class CSetCurTexImageCmd : public CDListCmd {
00240       tU128             *Image;
00241       unsigned int      Width, Height;
00242       GS::tPSM          Psm;
00243    public:
00244       CSetCurTexImageCmd( tU128 *image, unsigned int w, unsigned int h,
00245                           GS::tPSM psm )
00246          : Image(image), Width(w), Height(h), Psm(psm) {}
00247       CDListCmd* Play() {
00248          pGLContext->GetTexManager().SetCurTexImage( Image, Width, Height, Psm );
00249          return CDListCmd::GetNextCmd(this);
00250       }
00251 };
00252 
00253 void
00254 CTexManager::SetCurTexImage( tU128* imagePtr, tU32 w, tU32 h,
00255                              GS::tPSM psm )
00256 {
00257    GLContext.TextureChanged();
00258 
00259    if ( ! InsideDListDef ) {
00260       CurTexture->SetImage( imagePtr, w, h, psm );
00261    }
00262    else {
00263       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00264       dlist += CSetCurTexImageCmd( imagePtr, w, h, psm );
00265    }
00266 }
00267 
00268 class CSetCurClutCmd : public CDListCmd {
00269       const void        *Clut;
00270       int               NumEntries;
00271    public:
00272       CSetCurClutCmd( const void *clut, int numEntries )
00273          : Clut(clut), NumEntries(numEntries) {}
00274       CDListCmd* Play() {
00275          pGLContext->GetTexManager().SetCurClut(Clut, NumEntries);
00276          return CDListCmd::GetNextCmd(this);
00277       }
00278 };
00279 
00280 void
00281 CTexManager::SetCurClut( const void *clut, int numEntries )
00282 {
00283    GLContext.TextureChanged();
00284 
00285    if ( ! InsideDListDef ) {
00286       if ( CurClut ) delete CurClut;
00287       CurClut = new CMMClut( clut );
00288    }
00289    else {
00290       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00291       dlist += CSetCurClutCmd( clut, numEntries );
00292    }
00293 }
00294 
00295 class CSetGsTextureCmd : public CDListCmd {
00296       GS::CMemArea      &Texture;
00297    public:
00298       CSetGsTextureCmd(GS::CMemArea &tex) : Texture(tex) {}
00299       CDListCmd* Play() {
00300          pGLContext->GetTexManager().SetGsTexture(Texture);
00301          return CDListCmd::GetNextCmd(this);
00302       }
00303 };
00304 
00305 void
00306 CTexManager::SetGsTexture( GS::CMemArea &area )
00307 {
00308    GLContext.TextureChanged();
00309 
00310    if ( ! InsideDListDef ) 
00311       CurTexture->SetImage( area );
00312    else {
00313       CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00314       dlist += CSetGsTextureCmd(area);
00315    }
00316 }
00317 
00318 /********************************************
00319  * CMMTexture methods
00320  */
00321 
00322 CMMTexture::CMMTexture( GS::tContext context )
00323    : CTexture( context ), pImageMem(NULL), XferImage(false)
00324 {
00325 }
00326 
00327 CMMTexture::~CMMTexture()
00328 {
00329    delete pImageMem;
00330 }
00331 
00335 void
00336 CMMTexture::SetImage( tU128* imagePtr, tU32 w, tU32 h, GS::tPSM psm )
00337 {
00338    if ( pImageMem ) {
00339       // we are being re-initialized
00340       delete pImageMem;
00341       CTexture::Reset();
00342    }
00343 
00344    CTexture::SetImage( imagePtr, w, h, psm, NULL );
00345 
00346    // create a memarea for the image
00347    tU32 bufWidth = gsrTex0.TBW * 64;
00348    pImageMem = new GS::CMemArea( bufWidth, h, psm, GS::kAlignBlock );
00349         
00350    XferImage = true;
00351 }
00352 
00357 void
00358 CMMTexture::SetImage( const GS::CMemArea &area )
00359 {
00360    CTexEnv::SetPSM( area.GetPixFormat() );
00361    CTexEnv::SetDimensions( area.GetWidth(), area.GetHeight() );
00362    SetImageGsAddr( area.GetWordAddr() );
00363 
00364    XferImage = false;
00365 }
00366 
00367 void
00368 CMMTexture::Load( bool waitForEnd = true )
00369 {
00370    mErrorIf( pImageMem == NULL,
00371              "Trying to load a texture that hasn't been defined!" );
00372    // first set the gs address and flush the cache
00373    if ( ! pImageMem->IsAllocated() ) {
00374       pImageMem->Alloc();
00375       SetImageGsAddr( pImageMem->GetWordAddr() );
00376       FlushCache(0);
00377 
00378       // send the image
00379       SendImage( waitForEnd, Packet::kDontFlushCache );
00380 
00381       pglAddToMetric(kMetricsTextureUploadCount);
00382    }
00383 }
00384 
00385 // these two should be templates or something..
00386 
00387 void
00388 CMMTexture::Load( CSCDmaPacket& packet )
00389 {
00390    mErrorIf( pImageMem == NULL,
00391              "Trying to load a texture that hasn't been defined!" );
00392    if ( ! pImageMem->IsAllocated() ) {
00393       pImageMem->Alloc();
00394       SetImageGsAddr( pImageMem->GetWordAddr() );
00395       SendImage( packet );
00396 
00397       pglAddToMetric(kMetricsTextureUploadCount);
00398    }
00399 }
00400 void
00401 CMMTexture::Load( CVifSCDmaPacket& packet )
00402 {
00403    mErrorIf( pImageMem == NULL,
00404              "Trying to load a texture that hasn't been defined!" );
00405    if ( ! pImageMem->IsAllocated() ) {
00406       pImageMem->Alloc();
00407       SetImageGsAddr( pImageMem->GetWordAddr() );
00408       SendImage( packet );
00409 
00410       pglAddToMetric(kMetricsTextureUploadCount);      
00411    }
00412 }
00413 
00414 // again, should be templates..
00415 
00416 void
00417 CMMTexture::Use( bool waitForEnd = false )
00418 {
00419    if ( XferImage ) Load();
00420    SendSettings( waitForEnd, Packet::kDontFlushCache );
00421 }
00422 void
00423 CMMTexture::Use( CSCDmaPacket& packet )
00424 {
00425    if ( XferImage ) Load( packet );
00426    SendSettings( packet );
00427 }
00428 void
00429 CMMTexture::Use( CVifSCDmaPacket& packet )
00430 {
00431    if ( XferImage ) Load( packet );
00432    SendSettings( packet );
00433 }
00434 
00435 void
00436 CMMTexture::Free( void )
00437 {
00438    pImageMem->Free(); 
00439 }
00440 
00441 /********************************************
00442  * CMMClut
00443  */
00444 
00445 void
00446 CMMClut::Load( CVifSCDmaPacket &packet )
00447 {
00448    if ( ! GsMem.IsAllocated() ) {
00449       GsMem.Alloc();
00450       SetGsAddr( GsMem.GetWordAddr() );
00451       Send(packet);
00452 
00453       pglAddToMetric(kMetricsClutUploadCount);
00454    }
00455 }
00456 
00457 /********************************************
00458  * gl api
00459  */
00460 
00461 void glGenTextures( GLsizei numNewTexNames, GLuint *newTexNames )
00462 {
00463    CTexManager &texManager = pGLContext->GetTexManager();
00464    texManager.GenTextures( numNewTexNames, newTexNames );
00465 }
00466 
00467 void glBindTexture( GLenum target, GLuint texName )
00468 {
00469    mErrorIf( target != GL_TEXTURE_2D, "There are only 2D textures in ps2gl" );
00470 
00471    CTexManager &texManager = pGLContext->GetTexManager();
00472    texManager.BindTexture( texName );
00473 }
00474 
00475 void glDeleteTextures( GLsizei numToDelete, const GLuint *texNames )
00476 {
00477    CTexManager &texManager = pGLContext->GetTexManager();
00478    texManager.DeleteTextures( numToDelete, texNames );
00479 }
00480 
00481 void glTexImage2D( GLenum target,
00482                    GLint level,
00483                    GLint internalFormat,
00484                    GLsizei width,
00485                    GLsizei height,
00486                    GLint border,
00487                    GLenum format,
00488                    GLenum type,
00489                    const GLvoid *pixels )
00490 {
00491    if ( target == GL_PROXY_TEXTURE_2D ) {
00492       mNotImplemented( );
00493       return;
00494    }
00495    if ( level > 0 ) {
00496       mNotImplemented("mipmapping");
00497       return;
00498    }
00499    if ( border > 0 ) {
00500       mNotImplemented("texture borders");
00501       return;
00502    }
00503    if ( (unsigned int)pixels & 0xf ) {
00504       mNotImplemented( "texture data needs to be aligned to at least 16 bytes, "
00505                        "preferably 9 quads" );
00506    }
00507 
00508    GS::tPSM psm = GS::kInvalidPsm;
00509    switch (format) {
00510       case GL_RGBA:
00511          if ( type == GL_UNSIGNED_BYTE ||
00512               type == GL_UNSIGNED_INT_8_8_8_8 )
00513             psm = GS::kPsm32;
00514          else if ( type == GL_UNSIGNED_SHORT_5_5_5_1 )
00515             psm = GS::kPsm16;
00516          else {
00517             mNotImplemented( "RGBA textures should have a type of GL_UNSIGNED_BYTE, "
00518                              "GL_UNSIGNED_INT_8_8_8_8, or GL_UNSIGNED_SHORT_5_5_5_1" );
00519          }
00520          break;
00521       case GL_RGB:
00522          if ( type == GL_UNSIGNED_BYTE )
00523             psm = GS::kPsm24;
00524          else {
00525             mNotImplemented( "RGB textures should have a type of GL_UNSIGNED_BYTE" );
00526          }
00527          break;
00528       case GL_COLOR_INDEX:
00529          if ( type == GL_UNSIGNED_BYTE )
00530             psm = GS::kPsm8;
00531          else {
00532             mNotImplemented( "indexed textures should have a type of GL_UNSIGNED_BYTE" );
00533          }
00534          break;
00535    }
00536 
00537    if ( psm != GS::kInvalidPsm ) {
00538       CTexManager& tm = pGLContext->GetTexManager();
00539       tm.SetCurTexImage( (tU128*)pixels, width, height, psm );
00540    }
00541 }
00542 
00543 void glColorTable( GLenum target, GLenum internalFormat,
00544                    GLsizei width, GLenum format, GLenum type,
00545                    const GLvoid *table )
00546 {
00547    mWarnIf( target != GL_COLOR_TABLE,
00548             "glColorTable only supports GL_COLOR_TABLE" );
00549    // ignore internalFormat
00550    mErrorIf( width != 16 && width != 256,
00551              "A color table must contain either 16 or 256 entries" );
00552    mErrorIf( format != GL_RGB && format != GL_RGBA,
00553              "The pixel format of color tables must be either GL_RGB or GL_RGBA" );
00554    mWarnIf( type != GL_UNSIGNED_INT && type != GL_UNSIGNED_INT_8_8_8_8,
00555             "The type of color table data must be either GL_UNSIGNED_INT or"
00556             "GL_UNSIGNED_INT_8_8_8_8" );
00557    mErrorIf( (unsigned int)table & (16-1),
00558              "Color tables in ps2gl need to be 16-byte aligned in memory.." );
00559 
00560    CTexManager& tm = pGLContext->GetTexManager();
00561    tm.SetCurClut( table, width );
00562 }
00563 
00564 void glTexParameteri( GLenum target, GLenum pname, GLint param )
00565 {
00566    if ( target != GL_TEXTURE_2D ) {
00567       mNotImplemented( "Sorry, only 2d textures." );
00568       return;
00569    }
00570 
00571    pGLContext->GetTexManager().SetCurTexParam( pname, param );
00572 }
00573 
00574 void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
00575 {
00576    glTexParameteri( target, pname, (GLint)param );
00577 }
00578 
00579 void glTexParameteriv( GLenum target, GLenum pname, GLint *param )
00580 {
00581    glTexParameteri( target, pname, *param );
00582 }
00583 
00584 void glTexParameterfv( GLenum target, GLenum pname, GLfloat *param )
00585 {
00586    glTexParameteri( target, pname, (GLint)*param );
00587 }
00588 
00589 void glTexEnvi( GLenum target, GLenum pname, GLint param )
00590 {
00591    CTexManager &tm = pGLContext->GetTexManager();
00592 
00593    switch( param ) {
00594       case GL_MODULATE:
00595          tm.SetTexMode( (GS::tTexMode)(param & 0xf) );
00596          break;
00597       case GL_DECAL:
00598          mWarn( "GL_DECAL functions exactly as GL_REPLACE right now." );
00599       case GL_REPLACE:
00600          tm.SetTexMode( (GS::tTexMode)(param & 0xf) );
00601          break;
00602       case GL_BLEND:
00603          mNotImplemented( );
00604          break;
00605    }
00606 }
00607 
00608 void glTexEnvf( GLenum target, GLenum pname, GLfloat param )
00609 {
00610    glTexEnvi( target, pname, (GLint)param );
00611 }
00612 
00613 void glTexEnvfv( GLenum target, GLenum pname, GLfloat *param )
00614 {
00615    glTexEnvi( target, pname, (GLint)*param );
00616 }
00617 
00618 void glTexEnviv( GLenum target, GLenum pname, GLint *param )
00619 {
00620    glTexEnvi( target, pname, *param );
00621 }
00622 
00623 /********************************************
00624  * ps2gl C interface
00625  */
00626 
00637 void pglTextureFromGsMemArea( pgl_area_handle_t tex_area_handle )
00638 {
00639    CTexManager &texManager = pGLContext->GetTexManager();
00640    GS::CMemArea *texArea = reinterpret_cast<GS::CMemArea*>(tex_area_handle);
00641    texManager.SetGsTexture( *texArea );
00642 }
00643 

ps2gl version 0.2