Main Page | Namespace List | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

TextureManager.cpp

Go to the documentation of this file.
00001 
00003 #include <assert.h>
00004 #include <sps2lib.h>
00005 #include <sps2tags.h>
00006 #include <memory.h>
00007 
00008 #include "PS2Utils.h"
00009 #include "TextureManager.h"
00010  
00011 #define DEBUG
00012 
00025 NablaPS2Utils::TextureManager::TextureManager(const char *FileName, int SPS2Descriptor) {
00026 
00027     //Do not forget to initialize all Class internal members
00028     m_status            = false;
00029     m_imageData     = NULL;
00030     m_clutData      = NULL;
00031 
00032     //Open the file
00033     FILE * fp = NULL;
00034     fp = fopen(FileName, "rb");
00035     if (fp) {
00036         
00037         // Read all the header, check that reading went good.
00038         TextureFileHeader TFH;
00039         int Read = fread(&TFH, sizeof(TFH), 1, fp);
00040         assert(1 == Read);
00041         UpdateImageData(TFH);
00042 
00043         //Now read all data in a while, remember that TFH contains datasize of the 
00044         //binary data of image.
00045         m_SPS2Desc      = SPS2Descriptor;
00046         m_numMemBlocks = (TFH.DataSize + 4095) / 4096; 
00047         m_imageData     = sps2Allocate(4096 * m_numMemBlocks, 
00048                                     SPS2_MAP_BLOCK_4K | SPS2_MAP_UNCACHED,  m_SPS2Desc);
00049         fread(m_imageData->pvStart, 1, TFH.DataSize, fp);
00050 #ifdef DEBUG
00051         printf("Image size = %d Bytes, Num of 4096 block = %d\n", TFH.DataSize, m_numMemBlocks); 
00052 #endif
00053         //Now if a CLUT is present allocate memory for the clut, 
00054         if (PSM_PSMT8 == TFH.PixelFormat) {
00055         
00056             //256 CLUT entry are present, so 256 * 2 = 1024 bytes are needed
00057             m_clutData = sps2Allocate(4096, 
00058                                     SPS2_MAP_BLOCK_4K | SPS2_MAP_UNCACHED,  m_SPS2Desc);
00059             fread(m_clutData->pvStart, 1, 1024, fp);
00060         } 
00061         else if (PSM_PSMT4 == TFH.PixelFormat) {
00062         
00063             //16 CLUT entry are present, so 16 * 4 = 64 byte of memory should be 
00064             //allocated
00065             m_clutData = sps2Allocate(4096, 
00066                                     SPS2_MAP_BLOCK_4K | SPS2_MAP_UNCACHED,  m_SPS2Desc);
00067             fread(m_clutData, 1, 64, fp);
00068         }
00069 
00070         //All went good.
00071         m_status = true;
00072     }
00073 }
00074 
00078 NablaPS2Utils::TextureManager::~TextureManager() {
00079 
00080     SPS2_SAFE_FREE(m_imageData);
00081     SPS2_SAFE_FREE(m_clutData);
00082 }
00083 
00100 void NablaPS2Utils::TextureManager::SendTexture(
00101                                         sps2uint32 GSAddress, 
00102                                         sps2Memory_t *DMAMemory) {
00103 
00105     m_UploadAddress = GSAddress;
00106 
00107     //To upload a texture 4 register must be set, moreover GIFTag for begin 
00108     //IMAGE MODE transfer must also be set, this is a total of 
00109     //GifTag to specify 4 register + 4 * register specs + GifTag for IMAGEMODE
00110     //equal 6 qword of data.
00111     PS2_QWORD *DMAPacket = (PS2_QWORD *) DMAMemory->pvStart;
00112     DMAPacket++->ul128 = PS2_DMA_SET_HEADER(6, 0, DMA_ID_SOURCE_CNT, 0, 0, 0);
00113 
00114     //Now giftag, A+D mode and set other registers. Remember that EOP paramter 
00115     //Must be set to GS_GIF_EOP_WITHFOLLOWINGPRIM because we must send three
00116     //GS Primitives.
00117     sceGifTag *GifTag = (sceGifTag *) DMAPacket;
00118     memset(GifTag, 0, sizeof(sceGifTag));
00119     DMAPacket++->ul64[0] = PS2_GIF_SET_TAG(4, 
00120                                   GS_GIF_EOP_WITHFOLLOWINGPRIM, 
00121                                   GS_GIF_PRE_IGNOREPRIM, 
00122                                   0, 
00123                                   GIF_FLG_PACKED, 
00124                                   1);
00125     GifTag->REGS0 = GIF_REG_A_D;
00126 
00127     //(m_width + 63) / 64 gives smaller buffer width for transfer.
00128     int BufferWidth = (m_width + 63) / 64;
00129     DMAPacket->ul64[0] = PS2_GIF_SET_BITBLTBUF(0, 0, 0, GSAddress, BufferWidth, m_pixelFormat);
00130     DMAPacket++->ul64[1] = GIF_A_D_REG_BITBLTBUF;
00131     DMAPacket->ul64[0] = PS2_GIF_SET_TRXPOS(0, 0, 0, 0, 0);
00132     DMAPacket++->ul64[1] = GIF_A_D_REG_TRXPOS;
00133     DMAPacket->ul64[0] = PS2_GIF_SET_TRXREG(m_width, m_height);
00134     DMAPacket++->ul64[1] = GIF_A_D_REG_TRXREG;
00135     //Start image transfer.
00136     DMAPacket->ul64[0] = PS2_GIF_SET_TRXDIR(0);
00137     DMAPacket++->ul64[1] = GIF_A_D_REG_TRXDIR;
00138 
00139     //Now another GIFTag specifiyng IMAGE transfer is to be stored into first
00140     //cnt DMA tag packet, this GIFtag ends data transferred by the first chain
00141     //tag, all the data of this GIF packet are to be sent with a series of
00142     //ref chain tag.
00143     GifTag = (sceGifTag *) DMAPacket;
00144     memset(GifTag, 0, sizeof(sceGifTag));
00145     DMAPacket++->ul64[0] = PS2_GIF_SET_TAG(m_imageSize >> 4, 
00146                                         GS_GIF_EOP_WITHFOLLOWINGPRIM, 
00147                                         GS_GIF_PRE_IGNOREPRIM, 
00148                                         0, 
00149                                         GIF_FLG_IMAGE, 
00150                                         0);
00151     //This end the tranfers of first cnt DMA tag, now build ref packets
00152     sps2uint32 PhyAddress;
00153     for (int pageNum = 0; pageNum < m_numMemBlocks - 1; ++pageNum) {
00154     
00155         PhyAddress = sps2GetPhysicalAddress( 
00156                                 (char *) m_imageData->pvStart + 4096 * pageNum, m_imageData);
00157         DMAPacket++->ul128 = PS2_DMA_SET_HEADER( 
00158                                 256, 0, DMA_ID_SOURCE_REF, 0, PhyAddress, 0);
00159     } 
00160     //Remember that last block can be partially filled with data
00161     int lastPageSize = (m_imageSize & 0x0FFF) >> 4;
00162     if (0 == lastPageSize) lastPageSize = 256;
00163     printf("lastPageSize = %d\n", lastPageSize);
00164     PhyAddress = sps2GetPhysicalAddress( 
00165                                 (char *) m_imageData->pvStart + 4096 * (m_numMemBlocks - 1), m_imageData);
00166     DMAPacket++->ul128 = PS2_DMA_SET_HEADER( 
00167                             lastPageSize, 0, DMA_ID_SOURCE_REF, 0, PhyAddress, 0);
00168     //Now texture pixels are set, remember to set clut if necessary.
00169     //TODO, for now no CLUT is supported
00170     assert(m_pixelFormat == PSM_PSMCT32 || m_pixelFormat == PSM_PSMCT24);
00171 
00172     //Last GIF packet is used to access TEXFLUSH and stop data tranfer, this
00173     //also makes GS flushing data to be sure that next primitve that will be
00174     //rendered will correctly access the texture.
00175     DMAPacket++->ul128 = PS2_DMA_SET_HEADER(2, 0, DMA_ID_SOURCE_END, 0, 0, 0);
00176     GifTag = (sceGifTag *) DMAPacket;
00177     memset(GifTag, 0, sizeof(sceGifTag));
00178     //Remember to close GS packet, this is done setting EOP to 
00179     //GS_GIF_EOP_WITHOUTFOLLOWINGPRIM.
00180     DMAPacket++->ul64[0] = PS2_GIF_SET_TAG(1, 
00181                                 GS_GIF_EOP_WITHOUTFOLLOWINGPRIM, 
00182                                 GS_GIF_PRE_IGNOREPRIM, 
00183                                 0, 
00184                                 GIF_FLG_PACKED, 
00185                                 1);
00186     GifTag->REGS0 = GIF_REG_A_D;
00187     DMAPacket->ul64[0] = 0;
00188     DMAPacket++->ul64[1] = GIF_A_D_REG_TEXFLUSH;
00189 
00190     //Now the packet is to be send to GS, this transfer is different from 
00191     //the one used for past tutorial because we are doing source chain mode.
00192     //First of all we do not want any data to be transferred initially.
00193     //If 0 qword are to be transmitted MADR must not be set.
00194     *EE_D2_QWC  = 0;
00195     //This is the address of the first tag of the chain, this is memory
00196     //area passed by main program.
00197     *EE_D2_TADR = PS2_DMA_SET_TADR( 
00198         sps2GetPhysicalAddress(DMAMemory->pvStart, DMAMemory), 0);
00199     //Start the transfer.
00200     *EE_D2_CHCR = PS2_DMA_SET_CHCR(DMA_CHCR_DIR_TOMEMORY,
00201                                 DMA_CHCR_MOD_CHAIN,
00202                                 DMA_CHCR_ASP_NOADDRESS,
00203                                 DMA_CHCR_TTE_NOTRANSFER_DMATAG,
00204                                 DMA_CHCR_TIE_INTDISABLE,
00205                                 DMA_CHCR_STR_STARTTRANSFER,
00206                                 0);
00207     //wait for transfer to end.
00208     sps2WaitForDMA(2, m_SPS2Desc);
00209 }
00210 
00217 sps2uint64 NablaPS2Utils::TextureManager::BuildTEX0(int TextureFunction) const {
00218 
00219     sps2GIFRegTEX0_n_t TEX0;
00220     TEX0.s.TBP0     = m_UploadAddress;
00221     TEX0.s.TBW      = m_width / 64;
00222     TEX0.s.PSM      = m_pixelFormat;
00223     TEX0.s.TW       = IntLog2(m_width);
00224     TEX0.s.TH       = IntLog2(m_height);
00225     TEX0.s.TCC      = GS_TEX0_TCC_RGB;
00226     TEX0.s.TFX      = TextureFunction;
00227     TEX0.s.CBP      = 0;
00228     TEX0.s.CPSM     = 0;
00229     TEX0.s.CSM      = 0;
00230     TEX0.s.CSA      = 0;
00231     TEX0.s.CLD      = 0;
00232     return      (sps2uint64) TEX0.i64;
00233 }
00234 
00244 sps2uint64 NablaPS2Utils::TextureManager::BuildTEX1(int FilteringMode) const {
00245 
00246     sps2GIFRegTEX1_n_t TEX1;
00247     TEX1.s.LCM  = 0; //LODFORMULA but mipmapping is not used 
00248     TEX1.s.MXL  = 0;
00249     TEX1.s.MMAG = FilteringMode;
00250     TEX1.s.MMIN = FilteringMode;
00251     TEX1.s.MTBA = 0;
00252     TEX1.s.L        = 0;
00253     TEX1.s.K        = 0;
00254     return TEX1.i64;
00255 }
00259 void NablaPS2Utils::TextureManager::UpdateImageData(const TextureFileHeader &TFH) {
00260 
00261     m_height            = TFH.Height;
00262     m_width         = TFH.Width;
00263     m_pixelFormat   = TFH.PixelFormat;
00264     m_swizzled      = TFH.Swizzled;
00265     m_imageSize     = TFH.DataSize; 
00266 #ifdef DEBUG
00267     printf("Loaded Texture image");
00268     printf("Height\t\t = %d \n", m_height);
00269     printf("Width\t\t = %d \n", m_width);
00270     printf("PixelFormat\t = %d \n", m_pixelFormat);
00271     printf("Swizzled\t = %d \n", m_swizzled);
00272     printf("DataSize\t = %d \n", m_imageSize);
00273 #endif
00274 }
00275 
00280 int NablaPS2Utils::GetPixelSizeInBytes(PSM_t Format) {
00281 
00282     switch (Format) {
00283     
00284         case PSM_PSMCT32: 
00285         return 4;
00286 
00287         case PSM_PSMCT24:
00288         return 3;
00289 
00290         case PSM_PSMCT16: //Fall Through
00291         case PSM_PSMCT16S:
00292         return 2;
00293     
00294         case PSM_PSMT8: //Fall Through
00295         case PSM_PSMT8H:
00296         case PSM_PSMT4:
00297         return 1;
00298 
00299 
00300         default:
00301             return 0;
00302     }   
00303 }

Generated on Wed Jan 7 19:11:57 2004 for PS2 Tutorial by doxygen 1.3.4