- Main Page
- Classes
- Files

- File List
- File Members

# flGraphics.c

Go to the documentation of this file.

    00001 #include "flGlobal.h"
    00002 #if FL_GRAPHICS != 0
    00003 #include <pspdisplay.h>
    00004 #include <pspdebug.h>
    00005 #include <pspgu.h>
    00006 #include <pspgum.h>
    00007
    00008 #if FL_FONT != 0
    00009 #include <stdio.h>
    00010 #endif
    00011
    00012 #if FL_INCLUDE_ALL_C == 0
    00013 #include "flGraphics.h"
    00014 #include "flMemory.h"
    00015 #include "flDebug.h"
    00016 #include "flTimer.h"
    00017 #include "flFont.h"
    00018 #include "flNotify.h"
    00019 #include "flTexture.h"
    00020 #endif
    00021
    00022 bool  graphicsVSync = FL_GRAPHICS_VSYNC_DEFAULT;
    00023 #if FL_GRAPHICS_DISPLAYLIST_STATIC != 0
    00024 static u32 __attribute__((aligned(16))) graphicsDisplayList[((FL_GRAPHICS_DISPLAYLIST_SIZE + 15) & ~15) >> 1];
    00025 static u32 __attribute__((aligned(16))) graphicsDisplayListCache[4096];
    00026 #else
    00027 void* graphicsDisplayList = NULL;
    00028 void* graphicsDisplayListCache = NULL;
    00029 #endif
    00030 u8    graphicsDisplayListCurrent = 0;
    00031
    00032 void* graphicsDrawBuffer = NULL;
    00033 void* graphicsDispBuffer = NULL;
    00034 void* graphicsDepthBuffer = NULL;
    00035
    00036 bool graphicsLinesAntiAlias = FL_GRAPHICS_LINES_ANTIALIAS_DEFAULT;
    00037 bool graphicsWireframe = false;
    00038
    00039 #if FL_TIMER != 0
    00040 Timer* graphicsFPSTimer;
    00041 float  graphicsFPS = 0;
    00042 bool   graphicsFPSShow = FL_GRAPHICS_FPS_SHOW_DEFAULT;
    00043 #endif
    00044
    00045 bool  graphicsFrame = false;
    00046 bool  graphicsOrtho = false;
    00047 void* graphicsRenderTarget = NULL;
    00048 int   graphicsRenderTargetStride = 0;
    00049 u8    graphicsRenderTargetPixelFormat = 0;
    00050
    00051 void* graphicsDispListCur() {
    00052      if(!(graphicsDisplayListCurrent & 1))
    00053           return graphicsDisplayList;
    00054      u32 tempOut = ((FL_GRAPHICS_DISPLAYLIST_SIZE + 15) & ~15);
    00055      tempOut += (u32)graphicsDisplayList;
    00056      return (void*)tempOut;
    00057 }
    00058
    00059 void* graphicsDispListLast() {
    00060      if(graphicsDisplayListCurrent & 1)
    00061           return graphicsDisplayList;
    00062      u32 tempOut = ((FL_GRAPHICS_DISPLAYLIST_SIZE + 15) & ~15);
    00063      tempOut += (u32)graphicsDisplayList;
    00064      return (void*)tempOut;
    00065 }
    00066
    00067 void graphicsInit() {
    00068      u32 tempDListSize = (((FL_GRAPHICS_DISPLAYLIST_SIZE + 15) & ~15) << 1);
    00069      #if FL_GRAPHICS_DISPLAYLIST_STATIC == 0
    00070      graphicsDisplayList = memAlign(16, tempDListSize);
    00071      graphicsDisplayListCache = memAlign(16, 4096);
    00072      if(!graphicsDisplayList) {
    00073           #if FL_DEBUG_ERROR != 0
    00074           debugError("Couldn't allocate display list, graphics initialization error.\n");
    00075           #endif
    00076           return;
    00077      }
    00078      #endif
    00079
    00080      #if FL_VSHMODE == 0
    00081      #if FL_MEMORY_VMEM != 0
    00082
    00083      graphicsDrawBuffer = vmemAllocBuffer(SCREEN_PITCH, SCREEN_HEIGHT, graphicsPixelFormatBPP(FL_GRAPHICS_DRAW_BUFFER_FORMAT), (SCREEN_STRIDE - SCREEN_WIDTH));
    00084      graphicsDispBuffer = vmemAllocBuffer(SCREEN_PITCH, SCREEN_HEIGHT, graphicsPixelFormatBPP(FL_GRAPHICS_DISP_BUFFER_FORMAT), (SCREEN_STRIDE - SCREEN_WIDTH));
    00085      graphicsDepthBuffer = vmemAllocBuffer(SCREEN_PITCH, SCREEN_HEIGHT, 16, (SCREEN_STRIDE - SCREEN_WIDTH));
    00086      vmemInit();
    00087      #else
    00088      graphicsDrawBuffer  = (void*)0x0;
    00089      graphicsDispBuffer  = (void*)graphicsPixelFormatBPP(FL_GRAPHICS_DRAW_BUFFER_FORMAT);
    00090      graphicsDepthBuffer = (void*)(graphicsPixelFormatBPP(FL_GRAPHICS_DRAW_BUFFER_FORMAT) + graphicsPixelFormatBPP(FL_GRAPHICS_DISP_BUFFER_FORMAT));
    00091      #endif
    00092      graphicsRenderTarget = graphicsDrawBuffer;
    00093      graphicsRenderTargetStride = SCREEN_STRIDE;
    00094      graphicsRenderTargetPixelFormat = FL_GRAPHICS_DRAW_BUFFER_FORMAT;
    00095      #else
    00096      int tempBuffWidth, tempFormat, tempSync = 0;
    00097      sceDisplayGetFrameBuf(&graphicsDrawBuffer, &tempBuffWidth, &tempFormat, tempSync);
    00098      // TODO - Fix these values for VSHMODE.
    00099      graphicsDispBuffer  = (void*)((u32)graphicsDrawBuffer + 0x88000);
    00100      graphicsDepthBuffer = (void*)((u32)graphicsDrawBuffer + 0x110000);
    00101      graphicsRenderTarget = graphicsDrawBuffer;
    00102      graphicsRenderTargetStride = tempBuffWidth;
    00103      graphicsRenderTargetPixelFormat = tempFormat;
    00104      #endif
    00105
    00106      #if FL_MEMORY != 0
    00107      memClear(graphicsDisplayList, tempDListSize);
    00108      memClear(graphicsDisplayListCache, 4096);
    00109      #else
    00110      u32* i = (u32*)graphicsDisplayList;
    00111      while((u32)i < ((u32)graphicsDisplayList + tempDListSize))
    00112           *(i++) = 0x00;
    00113      i = (u32*)graphicsDisplayListCache;
    00114      while((u32)i < ((u32)graphicsDisplayListCache + 4096))
    00115           *(i++) = 0x00;
    00116      #endif
    00117
    00118      #if FL_VSHMODE == 0
    00119      sceGuInit();
    00120      sceGuStart(GU_DIRECT, graphicsDisplayList);
    00121
    00122      sceGuDrawBuffer(FL_GRAPHICS_DRAW_BUFFER_FORMAT, graphicsDrawBuffer, SCREEN_STRIDE);
    00123      sceGuDispBuffer(SCREEN_WIDTH, SCREEN_HEIGHT, graphicsDispBuffer, SCREEN_STRIDE);
    00124      sceGuDepthBuffer(graphicsDepthBuffer, SCREEN_STRIDE);
    00125
    00126      sceGuOffset(2048 - (SCREEN_WIDTH >> 1), 2048 - (SCREEN_HEIGHT >> 1));
    00127      sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT);
    00128      sceGuDepthRange(65535, 0);
    00129
    00130      sceGuAmbientColor(0xFFFFFFFF);
    00131
    00132      sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    00133      sceGuEnable(GU_SCISSOR_TEST);
    00134
    00135      sceGuDepthFunc(GU_GEQUAL);
    00136      sceGuEnable(GU_DEPTH_TEST);
    00137
    00138      sceGuFrontFace(GU_CW);
    00139      sceGuEnable(GU_CULL_FACE);
    00140
    00141      sceGuShadeModel(GU_SMOOTH);
    00142
    00143      sceGuEnable(GU_CLIP_PLANES);
    00144
    00145      sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
    00146      sceGuEnable(GU_BLEND);
    00147
    00148      sceGuTexEnvColor(0xFFFFFFFF);
    00149
    00150      if(graphicsLinesAntiAlias)
    00151           sceGuEnable(GU_LINE_SMOOTH);
    00152
    00153      //sceGuAlphaFunc();
    00154      //sceGuEnable(GU_ALPHA_TEST);
    00155
    00156      sceGuEnable(GU_TEXTURE_2D);
    00157
    00158      sceGuColor(0xFFFFFFFF);
    00159
    00160      sceGuFinish();
    00161      sceGuSync(GU_SYNC_WAIT, GU_SYNC_FINISH);
    00162
    00163      sceDisplayWaitVblankStart();
    00164      sceGuDisplay(GU_TRUE);
    00165      #endif
    00166
    00167      #if FL_TIMER != 0
    00168      graphicsFPSTimer = timerCreate();
    00169      #endif
    00170
    00171      // Begin the call list for next frame.
    00172      sceGuStart(GU_CALL, graphicsDispListCur());
    00173      sceGuFinish();
    00174      sceGuStart(GU_DIRECT, graphicsDisplayListCache);
    00175      sceGuCallList(graphicsDispListCur());
    00176      sceGuFinish();
    00177      graphicsDisplayListCurrent ^= 1;
    00178
    00179      sceGuStart(GU_CALL, graphicsDispListCur());
    00180      sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_FAST_CLEAR_BIT);
    00181      sceGumMatrixMode(GU_MODEL);
    00182      sceGumLoadIdentity();
    00183      #if FL_GRAPHICS_DRAW_BUFFER_FORMAT != FL_GRAPHICS_DISP_BUFFER_FORMAT
    00184      sceGuDrawBufferList(FL_GRAPHICS_DRAW_BUFFER_FORMAT, (void*)graphicsDrawBuffer, SCREEN_STRIDE);
    00185      #endif
    00186
    00187      graphicsFrame = true;
    00188 }
    00189
    00190 void graphicsSetProjection() {
    00191      sceGumMatrixMode(GU_PROJECTION);
    00192      sceGumLoadIdentity();
    00193      sceGumPerspective(45.0f, ((float)SCREEN_WIDTH / (float)SCREEN_HEIGHT), 0.5f, 1000.0f);
    00194
    00195      sceGumMatrixMode(GU_VIEW);
    00196      sceGumLoadIdentity();
    00197
    00198      sceGumMatrixMode(GU_MODEL);
    00199      sceGumLoadIdentity();
    00200
    00201      sceGuClearColor(0xFF000000);
    00202      sceGuClearDepth(0x00);
    00203 }
    00204
    00205 void graphicsTerm() {
    00206      sceGuFinish();
    00207      sceGuSync(GU_SYNC_WAIT, GU_SYNC_FINISH);
    00208
    00209      if(graphicsDisplayList)
    00210           memFree(graphicsDisplayList);
    00211      #if FL_MEMORY_VMEM
    00212      vmemTerm();
    00213      #endif
    00214      sceDisplayWaitVblankStart();
    00215      sceGuDisplay(GU_FALSE);
    00216      sceGuTerm();
    00217 }
    00218
    00219 void graphicsSwapBuffers() {
    00220      pspDebugScreenSetXY(0, 0);
    00221
    00222      #if FL_TIMER
    00223      #if FL_GRAPHICS_FPS_DAMP
    00224      graphicsFPS = (FL_GRAPHICS_FPS_DAMPRATIO * (1 / timerGetDeltaTime(graphicsFPSTimer))) + ((1 - FL_GRAPHICS_FPS_DAMPRATIO) * graphicsFPS);
    00225      #else
    00226      graphicsFPS = (1 / timerGetDeltaTime(graphicsFPSTimer));
    00227      #endif
    00228
    00229      #if FL_NOTIFY
    00230      ntfyTick();
    00231      #endif
    00232
    00233      if(graphicsFPSShow) {
    00234           #if FL_FONT != 0
    00235           char tempFPSString[16];
    00236           sprintf(tempFPSString, "FPS: %4.2f", graphicsFPS);
    00237           fontDraw2dString(0, 0, fontDefault, tempFPSString);
    00238           #else
    00239           pspDebugScreenSetTextColor(FL_GRAPHICS_FPS_SHOW_COLOR);
    00240           pspDebugScreenSetBackColor(~FL_GRAPHICS_FPS_SHOW_COLOR);
    00241           pspDebugScreenPrintf("FPS: %4.2f", graphicsFPS);
    00242           #if FL_GRAPHICS_FPS_SHOW_COLOR != 0xFFFFFFFF
    00243           pspDebugScreenSetTextColor(0xFFFFFFFF);
    00244           pspDebugScreenSetBackColor(0x00000000);
    00245           #endif
    00246           #endif
    00247      }
    00248      #endif
    00249
    00250      #if FL_GRAPHICS_VSYNC_AUTO != 0
    00251      bool tempVSync = (graphicsVSync && !(graphicsFPS < FL_GRAPHICS_VSYNC_AUTO_CUTOFF));
    00252      #else
    00253      bool tempVSync = (graphicsVSync != 0);
    00254      #endif
    00255
    00256
    00257      #if FL_VSHMODE == 0
    00258      sceGuSync(GU_SYNC_WAIT, GU_SYNC_FINISH);
    00259      sceGuFinish();
    00260      #if FL_GRAPHICS_DRAW_BUFFER_FORMAT == FL_GRAPHICS_DISP_BUFFER_FORMAT
    00261      graphicsDispBuffer = graphicsDrawBuffer;
    00262      if(tempVSync)
    00263           sceDisplayWaitVblankStart();
    00264      graphicsDrawBuffer = sceGuSwapBuffers();
    00265      pspDebugScreenSetOffset((int)graphicsDrawBuffer);
    00266      sceGuStart(GU_DIRECT, graphicsDisplayListCache);
    00267      sceGuCallList(graphicsDispListCur());
    00268      sceGuFinish();
    00269      #else
    00270      u32 i, j;
    00271      u32 tempSlice = 64;
    00272      u32 tempVertCount = (((SCREEN_WIDTH + (tempSlice - 1)) / tempSlice) << 1);
    00273      vertTsVs* tempVerts;
    00274
    00275      sceGuStart(GU_DIRECT, graphicsDisplayListCache);
    00276      sceGuDisable(GU_DEPTH_TEST);
    00277      sceGuTexMode(FL_GRAPHICS_DRAW_BUFFER_FORMAT, 0, 0, GU_FALSE);
    00278      sceGuTexImage(0, SCREEN_STRIDE, SCREEN_HEIGHT, SCREEN_STRIDE, (void*)graphicsDrawBuffer);
    00279      sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
    00280      sceGuTexFilter(GU_NEAREST, GU_NEAREST);
    00281
    00282      tempVerts = sceGuGetMemory(sizeof(vertTsVs) * tempVertCount);
    00283      for(i = 0, j = 0; i < SCREEN_WIDTH; i += tempSlice, j++) {
    00284           if((i + tempSlice) > SCREEN_WIDTH)
    00285                tempSlice = (SCREEN_WIDTH - (i + tempSlice));
    00286
    00287           tempVerts[j].vertX = i;
    00288           tempVerts[j].vertY = 0;
    00289           tempVerts[j].vertZ = 0;
    00290           tempVerts[j].vertU = tempVerts[j].vertU;
    00291           tempVerts[j].vertV = tempVerts[j].vertY;
    00292
    00293           j++;
    00294           tempVerts[j].vertX = i + tempSlice;
    00295           tempVerts[j].vertY = SCREEN_HEIGHT;
    00296           tempVerts[j].vertZ = 0;
    00297           tempVerts[j].vertU = tempVerts[j].vertU;
    00298           tempVerts[j].vertV = tempVerts[j].vertY;
    00299      }
    00300
    00301      sceGuDrawBufferList(FL_GRAPHICS_DISP_BUFFER_FORMAT, (void*)graphicsDispBuffer, SCREEN_STRIDE);
    00302      if(tempVSync)
    00303           sceDisplayWaitVblankStart();
    00304      sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, tempVertCount, 0, tempVerts);
    00305      sceGuDrawBufferList(FL_GRAPHICS_DRAW_BUFFER_FORMAT, (void*)graphicsDrawBuffer, SCREEN_STRIDE);
    00306      sceGuEnable(GU_DEPTH_TEST);
    00307
    00308      sceGuCallList(graphicsDispListCur());
    00309      sceGuFinish();
    00310      #if FL_TEXTURE
    00311      texBound = NULL;
    00312      #endif
    00313      #endif
    00314
    00315      graphicsDisplayListCurrent ^= 1;
    00316      sceGuStart(GU_CALL, graphicsDispListCur());
    00317
    00318      sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_FAST_CLEAR_BIT);
    00319      sceGumMatrixMode(GU_MODEL);
    00320      sceGumLoadIdentity();
    00321      #endif
    00322 }
    00323
    00324 void graphicsBeginOrtho() {
    00325      if(graphicsOrtho)
    00326           return;
    00327      sceGumMatrixMode(GU_PROJECTION);
    00328      sceGumPushMatrix();
    00329      sceGumLoadIdentity();
    00330      sceGumOrtho(0, 480, 272, 0, -1, 1);
    00331      sceGumMatrixMode(GU_VIEW);
    00332      sceGumPushMatrix();
    00333      sceGumLoadIdentity();
    00334      sceGumMatrixMode(GU_MODEL);
    00335      sceGumLoadIdentity();
    00336      graphicsOrtho = true;
    00337 }
    00338
    00339 void graphicsEndOrtho() {
    00340      if(!graphicsOrtho)
    00341           return;
    00342      sceGumMatrixMode(GU_VIEW);
    00343      sceGumPopMatrix();
    00344      sceGumMatrixMode(GU_PROJECTION);
    00345      sceGumPopMatrix();
    00346      sceGumMatrixMode(GU_MODEL);
    00347      sceGumLoadIdentity();
    00348      graphicsOrtho = false;
    00349 }
    00350
    00351 void graphicsSetLinesAntiAlias(bool inValue) {
    00352      if(graphicsLinesAntiAlias == inValue)
    00353           return;
    00354      if(inValue)
    00355           sceGuEnable(GU_LINE_SMOOTH);
    00356      else
    00357           sceGuDisable(GU_LINE_SMOOTH);
    00358      graphicsLinesAntiAlias = inValue;
    00359 }
    00360
    00361 void graphicsRenderToFramebuffer() {
    00362      sceGuDrawBufferList(FL_GRAPHICS_DRAW_BUFFER_FORMAT, (void*)graphicsDrawBuffer, SCREEN_STRIDE);
    00363      graphicsRenderTarget = (void*)graphicsDrawBuffer;
    00364      graphicsRenderTargetStride = SCREEN_STRIDE;
    00365      graphicsRenderTargetPixelFormat = FL_GRAPHICS_DRAW_BUFFER_FORMAT;
    00366 }
    00367
    00368 bool graphicsRenderToVmem(void* inPtr, int inStride, u8 inPixelFormat) {
    00369      if(!((unsigned int)inPtr & 0x04000000)) {
    00370           #if DEBUG_ERROR != 0
    00371           debugError("Render target invalid, must be in VRam.");
    00372           #endif
    00373           return false;
    00374      }
    00375      graphicsRenderTarget = (void*)((unsigned int)inPtr & 0xBBFFFFFF);
    00376      sceGuDrawBufferList(inPixelFormat, graphicsRenderTarget, inStride);
    00377      graphicsRenderTargetStride = inStride;
    00378      graphicsRenderTargetPixelFormat = inPixelFormat;
    00379      return true;
    00380 }
    00381
    00382 u8 graphicsPixelFormatBPP(u8 inPixelFormat) {
    00383      switch(inPixelFormat) {
    00384           case GU_PSM_8888:
    00385           case GU_PSM_T32:
    00386                return 32;
    00387           case GU_PSM_4444:
    00388           case GU_PSM_5650:
    00389           case GU_PSM_5551:
    00390           case GU_PSM_T16:
    00391                return 16;
    00392           case GU_PSM_DXT3:
    00393           case GU_PSM_DXT5:
    00394           case GU_PSM_T8:
    00395                return 8;
    00396           case GU_PSM_DXT1:
    00397           case GU_PSM_T4:
    00398                return 4;
    00399      }
    00400      return 0;
    00401 }
    00402
    00403 u8* graphicsSwizzleData(u8* inData, u32 inWidth, u32 inHeight, u8 inPixelFormat) {
    00404      if(!inData) {
    00405           #if FL_DEBUG_WARNING != 0
    00406           debugWarning("Can't swizzle data from a NULL pointer.");
    00407           #endif
    00408           return NULL;
    00409      }
    00410      if(!inWidth || !inHeight) {
    00411           #if FL_DEBUG_WARNING != 0
    00412           debugWarning("Can't swizzle data with a dimension of 0.");
    00413           #endif
    00414           return NULL;
    00415      }
    00416      u32 tempWidth = ((inWidth * graphicsPixelFormatBPP(inPixelFormat)) >> 3);
    00417      if((tempWidth & 15) || (inHeight & 7)) {
    00418           #if FL_DEBUG_WARNING != 0
    00419           debugWarning("Data must have a width in which is a multiple of 16 bytes (%u), and a height which is a multiple of 8  (%u).", (unsigned int)tempWidth, (unsigned int)inHeight);
    00420           #endif
    00421           return inData;
    00422      }
    00423      u32 tempSize = tempWidth * inHeight;
    00424
    00425      u8* tempDest = (u8*)memQalloc(tempSize);
    00426      if(!tempDest) {
    00427           #if FL_DEBUG_ERROR != 0
    00428           debugError("Not enough memory to perform swizzle.");
    00429           #endif
    00430           return NULL;
    00431      }
    00432
    00433      u32  tempBlockX, tempBlockY;
    00434      u32  j;
    00435
    00436      u32  tempWidthBlocks  = (tempWidth >> 4);
    00437      u32  tempHeightBlocks = (inHeight >> 3);
    00438
    00439      u32  tempSrcPitch     = ((tempWidth - 16) >> 2);
    00440      u32  tempSrcRow       = (tempWidth << 3);
    00441
    00442      u8*   tempYSrc        = inData;
    00443      u32*  tempDestPtr     = (u32*)tempDest;
    00444
    00445      u8*  tempXSrc;
    00446      u32* tempSrc;
    00447
    00448      for(tempBlockY = 0; tempBlockY < tempHeightBlocks; ++tempBlockY) {
    00449           tempXSrc = tempYSrc;
    00450           for(tempBlockX = 0; tempBlockX < tempWidthBlocks; ++tempBlockX) {
    00451                tempSrc = (u32*)tempXSrc;
    00452                for(j = 0; j < 8; ++j) {
    00453                     *(tempDestPtr++) = *(tempSrc++);
    00454                     *(tempDestPtr++) = *(tempSrc++);
    00455                     *(tempDestPtr++) = *(tempSrc++);
    00456                     *(tempDestPtr++) = *(tempSrc++);
    00457                     tempSrc += tempSrcPitch;
    00458                }
    00459                tempXSrc += 16;
    00460           }
    00461           tempYSrc += tempSrcRow;
    00462      }
    00463
    00464      memCopy(inData, tempDest, tempSize);
    00465      memFree(tempDest);
    00466
    00467      if(memIsCachedPointer(inData)) {
    00468           if(tempSize >= 16384)
    00469                sceKernelDcacheWritebackAll();
    00470           else
    00471                sceKernelDcacheWritebackRange(inData, tempSize);
    00472      }
    00473      return inData;
    00474 }
    00475
    00476 u8* graphicsUnswizzleData(u8* inData, u32 inWidth, u32 inHeight, u8 inPixelFormat) {
    00477      if(!inData) {
    00478           #if FL_DEBUG_WARNING != 0
    00479           debugWarning("Can't unswizzle data from a NULL pointer.");
    00480           #endif
    00481           return NULL;
    00482      }
    00483      if(!inWidth || !inHeight) {
    00484           #if FL_DEBUG_WARNING != 0
    00485           debugWarning("Can't unswizzle data with a dimension of 0.");
    00486           #endif
    00487           return NULL;
    00488      }
    00489      u32 tempWidth = ((inWidth * graphicsPixelFormatBPP(inPixelFormat)) >> 3);
    00490      if((tempWidth & 15) || (inHeight & 7)) {
    00491           #if FL_DEBUG_WARNING != 0
    00492           debugWarning("Data must have a width in which is a multiple of 16 bytes (%u), and a height which is a multiple of 8  (%u).", (unsigned int)tempWidth, (unsigned int)inHeight);
    00493           #endif
    00494           return inData;
    00495      }
    00496      u32 tempSize = (tempWidth * inHeight);
    00497
    00498      u8* tempDest = (u8*)memQalloc(tempSize);
    00499      if(!tempDest) {
    00500           #if FL_DEBUG_ERROR != 0
    00501           debugError("Not enough memory to perform unswizzle.");
    00502           #endif
    00503           return NULL;
    00504      }
    00505
    00506      u32  tempBlockX, tempBlockY;
    00507      u32  j;
    00508
    00509      u32  tempWidthBlocks  = (tempWidth >> 4);
    00510      u32  tempHeightBlocks = (inHeight >> 3);
    00511
    00512      u32  tempDestPitch    = ((tempWidth - 16) >> 2);
    00513      u32  tempDestRow      = (tempWidth << 3);
    00514
    00515      u32* tempSrc          = (u32*)inData;
    00516      u8*  tempYDest        = (u8*)tempDest;
    00517
    00518      u8*  tempXDest;
    00519      u32* tempDestPtr;
    00520
    00521      for(tempBlockY = 0; tempBlockY < tempHeightBlocks; ++tempBlockY) {
    00522           tempXDest = tempYDest;
    00523           for(tempBlockX = 0; tempBlockX < tempWidthBlocks; ++tempBlockX) {
    00524                tempDestPtr = (u32*)tempXDest;
    00525                for(j = 0; j < 8; ++j) {
    00526                     *(tempDestPtr++) = *(tempSrc++);
    00527                     *(tempDestPtr++) = *(tempSrc++);
    00528                     *(tempDestPtr++) = *(tempSrc++);
    00529                     *(tempDestPtr++) = *(tempSrc++);
    00530                     tempDestPtr += tempDestPitch;
    00531                }
    00532                tempXDest += 16;
    00533           }
    00534           tempYDest += tempDestRow;
    00535      }
    00536
    00537      memCopy(inData, tempDest, tempSize);
    00538      memFree(tempDest);
    00539
    00540      if(memIsCachedPointer(inData)) {
    00541           if(tempSize >= 16384)
    00542                sceKernelDcacheWritebackAll();
    00543           else
    00544                sceKernelDcacheWritebackRange(inData, tempSize);
    00545      }
    00546
    00547      return inData;
    00548 }
    00549
    00550 #endif