From 2acce6771f5ec7e47148f0d2ca30b63bc34abd57 Mon Sep 17 00:00:00 2001 From: Sergey Date: Mon, 17 Mar 2014 22:28:24 +0400 Subject: [PATCH 1/8] software per decompression support --- build/cocos2d_libs.xcodeproj/project.pbxproj | 12 + cocos/2d/cocos2d.vcxproj | 2 + cocos/2d/cocos2d.vcxproj.filters | 6 + cocos/Android.mk | 1 + cocos/base/CMakeLists.txt | 1 + cocos/base/pvr.cpp | 712 +++++++++++++++++++ cocos/base/pvr.h | 16 + cocos/platform/CCImage.cpp | 152 +++- cocos/platform/CCImage.h | 2 + cocos/platform/win32/CCGL.h | 6 - 10 files changed, 879 insertions(+), 31 deletions(-) create mode 100644 cocos/base/pvr.cpp create mode 100644 cocos/base/pvr.h diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index 05cf2b5dc2..cea663757f 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -1242,6 +1242,10 @@ B24AA98B195A675C007B4522 /* CCFastTMXTiledMap.h in Headers */ = {isa = PBXBuildFile; fileRef = B24AA984195A675C007B4522 /* CCFastTMXTiledMap.h */; }; B24AA98C195A675C007B4522 /* CCFastTMXTiledMap.h in Headers */ = {isa = PBXBuildFile; fileRef = B24AA984195A675C007B4522 /* CCFastTMXTiledMap.h */; }; B27AEE0219768934008BD575 /* libwebsockets.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AAF5384180E35A3000584C8 /* libwebsockets.a */; }; + A5BC6BA819430ABA00AD87B3 /* pvr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5BC6BA619430ABA00AD87B3 /* pvr.cpp */; }; + A5BC6BA919430ABA00AD87B3 /* pvr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5BC6BA619430ABA00AD87B3 /* pvr.cpp */; }; + A5BC6BAA19430ABA00AD87B3 /* pvr.h in Headers */ = {isa = PBXBuildFile; fileRef = A5BC6BA719430ABA00AD87B3 /* pvr.h */; }; + A5BC6BAB19430ABA00AD87B3 /* pvr.h in Headers */ = {isa = PBXBuildFile; fileRef = A5BC6BA719430ABA00AD87B3 /* pvr.h */; }; B29594B41926D5EC003EEF37 /* CCMeshCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B29594B21926D5EC003EEF37 /* CCMeshCommand.cpp */; }; B29594B51926D5EC003EEF37 /* CCMeshCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B29594B21926D5EC003EEF37 /* CCMeshCommand.cpp */; }; B29594B61926D5EC003EEF37 /* CCMeshCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = B29594B31926D5EC003EEF37 /* CCMeshCommand.h */; }; @@ -2891,6 +2895,8 @@ B24EEA7619775ECE004493CC /* libcocosBuilder iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libcocosBuilder iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B24EEA7E19775EE1004493CC /* libcocosSpine iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libcocosSpine iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B24EEA8619775EF3004493CC /* libcocosNetwork iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libcocosNetwork iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + A5BC6BA619430ABA00AD87B3 /* pvr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pvr.cpp; path = ../base/pvr.cpp; sourceTree = ""; }; + A5BC6BA719430ABA00AD87B3 /* pvr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pvr.h; path = ../base/pvr.h; sourceTree = ""; }; B29594AF1926D5D9003EEF37 /* ccShader_3D_Color.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Color.frag; sourceTree = ""; }; B29594B01926D5D9003EEF37 /* ccShader_3D_ColorTex.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorTex.frag; sourceTree = ""; }; B29594B11926D5D9003EEF37 /* ccShader_3D_PositionTex.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_PositionTex.vert; sourceTree = ""; }; @@ -3377,6 +3383,8 @@ 50ABBE141925AB6F00A911A9 /* etc1.cpp */, 50ABBE151925AB6F00A911A9 /* etc1.h */, 50ABBE161925AB6F00A911A9 /* firePngData.h */, + A5BC6BA619430ABA00AD87B3 /* pvr.cpp */, + A5BC6BA719430ABA00AD87B3 /* pvr.h */, 50ABBE171925AB6F00A911A9 /* s3tc.cpp */, 50ABBE181925AB6F00A911A9 /* s3tc.h */, 50ABBE191925AB6F00A911A9 /* TGAlib.cpp */, @@ -5159,6 +5167,7 @@ 1A57011D180BC90D0088DEC7 /* CCGrabber.h in Headers */, 1A570121180BC90D0088DEC7 /* CCGrid.h in Headers */, 5034CA2D191D591100CE6051 /* ccShader_PositionTextureA8Color.frag in Headers */, + A5BC6BAA19430ABA00AD87B3 /* pvr.h in Headers */,, 1AC0269C1914068200FA920D /* ConvertUTF.h in Headers */, 50ABBED11925AB6F00A911A9 /* TGAlib.h in Headers */, 1A57019F180BCB590088DEC7 /* CCFont.h in Headers */, @@ -5613,6 +5622,7 @@ 1A57034E180BD09B0088DEC7 /* tinyxml2.h in Headers */, 1A570357180BD0B00088DEC7 /* ioapi.h in Headers */, 50ABBD4B1925AB0000A911A9 /* Mat4.h in Headers */, + A5BC6BAB19430ABA00AD87B3 /* pvr.h in Headers */, 1A01C69B18F57BE800EFE3A6 /* CCSet.h in Headers */, 50ABBED61925AB6F00A911A9 /* utlist.h in Headers */, 1A57035B180BD0B00088DEC7 /* unzip.h in Headers */, @@ -6656,6 +6666,7 @@ 1A12775C18DFCC590005F345 /* CCTweenFunction.cpp in Sources */, 1A5701E6180BCB8C0088DEC7 /* CCTransition.cpp in Sources */, B24AA985195A675C007B4522 /* CCFastTMXLayer.cpp in Sources */, + A5BC6BA819430ABA00AD87B3 /* pvr.cpp in Sources */, 1A5701EA180BCB8C0088DEC7 /* CCTransitionPageTurn.cpp in Sources */, 50ABBDAD1925AB4100A911A9 /* CCRenderer.cpp in Sources */, 1A5701EE180BCB8C0088DEC7 /* CCTransitionProgress.cpp in Sources */, @@ -6987,6 +6998,7 @@ 1A5701E3180BCB8C0088DEC7 /* CCScene.cpp in Sources */, 50ABBD611925AB0000A911A9 /* Vec4.cpp in Sources */, 50ABBD9C1925AB4100A911A9 /* ccGLStateCache.cpp in Sources */, + A5BC6BA919430ABA00AD87B3 /* pvr.cpp in Sources */, 1A5701E7180BCB8C0088DEC7 /* CCTransition.cpp in Sources */, 50ABC01E1926664800A911A9 /* CCThread.cpp in Sources */, 1A5701EB180BCB8C0088DEC7 /* CCTransitionPageTurn.cpp in Sources */, diff --git a/cocos/2d/cocos2d.vcxproj b/cocos/2d/cocos2d.vcxproj index 0ff4dd0daf..7e8469382a 100644 --- a/cocos/2d/cocos2d.vcxproj +++ b/cocos/2d/cocos2d.vcxproj @@ -229,6 +229,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + @@ -422,6 +423,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + diff --git a/cocos/2d/cocos2d.vcxproj.filters b/cocos/2d/cocos2d.vcxproj.filters index b264b0caa8..af5fa51213 100644 --- a/cocos/2d/cocos2d.vcxproj.filters +++ b/cocos/2d/cocos2d.vcxproj.filters @@ -418,6 +418,9 @@ base + + platform + base @@ -991,6 +994,9 @@ base + + platform + base diff --git a/cocos/Android.mk b/cocos/Android.mk index 990ee16aaa..740d7952ca 100644 --- a/cocos/Android.mk +++ b/cocos/Android.mk @@ -140,6 +140,7 @@ base/ccTypes.cpp \ base/ccUTF8.cpp \ base/ccUtils.cpp \ base/etc1.cpp \ +base/pvr.cpp \ base/s3tc.cpp \ base/CCController.cpp \ base/CCController-android.cpp \ diff --git a/cocos/base/CMakeLists.txt b/cocos/base/CMakeLists.txt index 701c8ba5a6..e57058fd5a 100644 --- a/cocos/base/CMakeLists.txt +++ b/cocos/base/CMakeLists.txt @@ -40,6 +40,7 @@ set(COCOS_BASE_SRC base/ccUTF8.cpp base/ccUtils.cpp base/etc1.cpp + base/pvr.cpp base/s3tc.cpp base/ObjectFactory.cpp ) diff --git a/cocos/base/pvr.cpp b/cocos/base/pvr.cpp new file mode 100644 index 0000000000..d3fbb7e854 --- /dev/null +++ b/cocos/base/pvr.cpp @@ -0,0 +1,712 @@ +/****************************************************************************** + + @File pvr.cpp + + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "pvr.h" + +#define PVRT_MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define PVRT_MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define PVRT_CLAMP(x, l, h) (PVRT_MIN((h), PVRT_MAX((x), (l)))) + +/***************************************************************************** + * defines and consts + *****************************************************************************/ +#define PT_INDEX (2) // The Punch-through index + +#define BLK_Y_SIZE (4) // always 4 for all 2D block types + +#define BLK_X_MAX (8) // Max X dimension for blocks + +#define BLK_X_2BPP (8) // dimensions for the two formats +#define BLK_X_4BPP (4) + +#define WRAP_COORD(Val, Size) ((Val) & ((Size)-1)) + +#define POWER_OF_2(X) util_number_is_power_2(X) + +/* + Define an expression to either wrap or clamp large or small vals to the + legal coordinate range + */ +#define LIMIT_COORD(Val, Size, AssumeImageTiles) \ +((AssumeImageTiles)? WRAP_COORD((Val), (Size)): PVRT_CLAMP((Val), 0, (Size)-1)) + +/***************************************************************************** + * Useful typedefs + *****************************************************************************/ +typedef unsigned long U32; +typedef unsigned char U8; + +/*********************************************************** + DECOMPRESSION ROUTINES + ************************************************************/ + +/*!*********************************************************************** + @Struct AMTC_BLOCK_STRUCT + @Brief + *************************************************************************/ +typedef struct +{ + // Uses 64 bits pre block + U32 PackedData[2]; +}AMTC_BLOCK_STRUCT; + + +static void PVRDecompress(AMTC_BLOCK_STRUCT *pCompressedData, + const bool Do2bitMode, + const int XDim, + const int YDim, + const int AssumeImageTiles, + unsigned char* pResultImage); + +/*!*********************************************************************** + @Function PVRTDecompressPVRTC + @Input pCompressedData The PVRTC texture data to decompress + @Input Do2bitMode Signifies whether the data is PVRTC2 or PVRTC4 + @Input XDim X dimension of the texture + @Input YDim Y dimension of the texture + @Modified pResultImage The decompressed texture data + @Description Decompresses PVRTC to RGBA 8888 + *************************************************************************/ +int PVRTDecompressPVRTC(const void * const pCompressedData,const int XDim,const int YDim, void *pDestData,const bool Do2bitMode) +{ + PVRDecompress((AMTC_BLOCK_STRUCT*)pCompressedData,Do2bitMode,XDim,YDim,1,(unsigned char*)pDestData); + unsigned char* pSwap = (unsigned char*)pDestData, swap; + + for(int i=0;iPackedData[1] & (0xFFFE); // 15 bits (shifted up by one) + RawBits[1] = pBlock->PackedData[1] >> 16; // 16 bits + + // step through both colours + for(i = 0; i < 2; i++) + { + // If completely opaque + if(RawBits[i] & (1<<15)) + { + // Extract R and G (both 5 bit) + ABColours[i][0] = (RawBits[i] >> 10) & 0x1F; + ABColours[i][1] = (RawBits[i] >> 5) & 0x1F; + + /* + The precision of Blue depends on A or B. If A then we need to + replicate the top bit to get 5 bits in total + */ + ABColours[i][2] = RawBits[i] & 0x1F; + if(i==0) + { + ABColours[0][2] |= ABColours[0][2] >> 4; + } + + // set 4bit alpha fully on... + ABColours[i][3] = 0xF; + } + else // Else if colour has variable translucency + { + /* + Extract R and G (both 4 bit). + (Leave a space on the end for the replication of bits + */ + ABColours[i][0] = (RawBits[i] >> (8-1)) & 0x1E; + ABColours[i][1] = (RawBits[i] >> (4-1)) & 0x1E; + + // replicate bits to truly expand to 5 bits + ABColours[i][0] |= ABColours[i][0] >> 4; + ABColours[i][1] |= ABColours[i][1] >> 4; + + // grab the 3(+padding) or 4 bits of blue and add an extra padding bit + ABColours[i][2] = (RawBits[i] & 0xF) << 1; + + /* + expand from 3 to 5 bits if this is from colour A, or 4 to 5 bits if from + colour B + */ + if(i==0) + { + ABColours[0][2] |= ABColours[0][2] >> 3; + } + else + { + ABColours[0][2] |= ABColours[0][2] >> 4; + } + + // Set the alpha bits to be 3 + a zero on the end + ABColours[i][3] = (RawBits[i] >> 11) & 0xE; + } + } +} + +/*!*********************************************************************** + @Function UnpackModulations + @Input pBlock + @Input Do2bitMode + @Input ModulationVals + @Input ModulationModes + @Input StartX + @Input StartY + @Description Given the block and the texture type and it's relative + position in the 2x2 group of blocks, extract the bit + patterns for the fully defined pixels. + *************************************************************************/ +static void UnpackModulations(const AMTC_BLOCK_STRUCT *pBlock, + const int Do2bitMode, + int ModulationVals[8][16], + int ModulationModes[8][16], + int StartX, + int StartY) +{ + int BlockModMode; + U32 ModulationBits; + + int x, y; + + BlockModMode= pBlock->PackedData[1] & 1; + ModulationBits = pBlock->PackedData[0]; + + // if it's in an interpolated mode + if(Do2bitMode && BlockModMode) + { + /* + run through all the pixels in the block. Note we can now treat all the + "stored" values as if they have 2bits (even when they didn't!) + */ + for(y = 0; y < BLK_Y_SIZE; y++) + { + for(x = 0; x < BLK_X_2BPP; x++) + { + ModulationModes[y+StartY][x+StartX] = BlockModMode; + + // if this is a stored value... + if(((x^y)&1) == 0) + { + ModulationVals[y+StartY][x+StartX] = ModulationBits & 3; + ModulationBits >>= 2; + } + } + } + } + else if(Do2bitMode) // else if direct encoded 2bit mode - i.e. 1 mode bit per pixel + { + for(y = 0; y < BLK_Y_SIZE; y++) + { + for(x = 0; x < BLK_X_2BPP; x++) + { + ModulationModes[y+StartY][x+StartX] = BlockModMode; + + // double the bits so 0=> 00, and 1=>11 + if(ModulationBits & 1) + { + ModulationVals[y+StartY][x+StartX] = 0x3; + } + else + { + ModulationVals[y+StartY][x+StartX] = 0x0; + } + ModulationBits >>= 1; + } + } + } + else // else its the 4bpp mode so each value has 2 bits + { + for(y = 0; y < BLK_Y_SIZE; y++) + { + for(x = 0; x < BLK_X_4BPP; x++) + { + ModulationModes[y+StartY][x+StartX] = BlockModMode; + + ModulationVals[y+StartY][x+StartX] = ModulationBits & 3; + ModulationBits >>= 2; + } + } + } + + // make sure nothing is left over + assert(ModulationBits==0); +} + +/*!*********************************************************************** + @Function InterpolateColours + @Input ColourP + @Input ColourQ + @Input ColourR + @Input ColourS + @Input Do2bitMode + @Input x + @Input y + @Modified Result + @Description This performs a HW bit accurate interpolation of either the + A or B colours for a particular pixel. + + NOTE: It is assumed that the source colours are in ARGB 5554 + format - This means that some "preparation" of the values will + be necessary. + *************************************************************************/ +static void InterpolateColours(const int ColourP[4], + const int ColourQ[4], + const int ColourR[4], + const int ColourS[4], + const int Do2bitMode, + const int x, + const int y, + int Result[4]) +{ + int u, v, uscale; + int k; + + int tmp1, tmp2; + + int P[4], Q[4], R[4], S[4]; + + // Copy the colours + for(k = 0; k < 4; k++) + { + P[k] = ColourP[k]; + Q[k] = ColourQ[k]; + R[k] = ColourR[k]; + S[k] = ColourS[k]; + } + + // put the x and y values into the right range + v = (y & 0x3) | ((~y & 0x2) << 1); + + if(Do2bitMode) + u = (x & 0x7) | ((~x & 0x4) << 1); + else + u = (x & 0x3) | ((~x & 0x2) << 1); + + // get the u and v scale amounts + v = v - BLK_Y_SIZE/2; + + if(Do2bitMode) + { + u = u - BLK_X_2BPP/2; + uscale = 8; + } + else + { + u = u - BLK_X_4BPP/2; + uscale = 4; + } + + for(k = 0; k < 4; k++) + { + tmp1 = P[k] * uscale + u * (Q[k] - P[k]); + tmp2 = R[k] * uscale + u * (S[k] - R[k]); + + tmp1 = tmp1 * 4 + v * (tmp2 - tmp1); + + Result[k] = tmp1; + } + + // Lop off the appropriate number of bits to get us to 8 bit precision + if(Do2bitMode) + { + // do RGB + for(k = 0; k < 3; k++) + { + Result[k] >>= 2; + } + + Result[3] >>= 1; + } + else + { + // do RGB (A is ok) + for(k = 0; k < 3; k++) + { + Result[k] >>= 1; + } + } + + // sanity check + for(k = 0; k < 4; k++) + { + assert(Result[k] < 256); + } + + + /* + Convert from 5554 to 8888 + + do RGB 5.3 => 8 + */ + for(k = 0; k < 3; k++) + { + Result[k] += Result[k] >> 5; + } + + Result[3] += Result[3] >> 4; + + // 2nd sanity check + for(k = 0; k < 4; k++) + { + assert(Result[k] < 256); + } + +} + +/*!*********************************************************************** + @Function GetModulationValue + @Input x + @Input y + @Input Do2bitMode + @Input ModulationVals + @Input ModulationModes + @Input Mod + @Input DoPT + @Description Get the modulation value as a numerator of a fraction of 8ths + *************************************************************************/ +static void GetModulationValue(int x, + int y, + const int Do2bitMode, + const int ModulationVals[8][16], + const int ModulationModes[8][16], + int *Mod, + int *DoPT) +{ + static const int RepVals0[4] = {0, 3, 5, 8}; + static const int RepVals1[4] = {0, 4, 4, 8}; + + int ModVal; + + // Map X and Y into the local 2x2 block + y = (y & 0x3) | ((~y & 0x2) << 1); + + if(Do2bitMode) + x = (x & 0x7) | ((~x & 0x4) << 1); + else + x = (x & 0x3) | ((~x & 0x2) << 1); + + // assume no PT for now + *DoPT = 0; + + // extract the modulation value. If a simple encoding + if(ModulationModes[y][x]==0) + { + ModVal = RepVals0[ModulationVals[y][x]]; + } + else if(Do2bitMode) + { + // if this is a stored value + if(((x^y)&1)==0) + ModVal = RepVals0[ModulationVals[y][x]]; + else if(ModulationModes[y][x] == 1) // else average from the neighbours if H&V interpolation.. + { + ModVal = (RepVals0[ModulationVals[y-1][x]] + + RepVals0[ModulationVals[y+1][x]] + + RepVals0[ModulationVals[y][x-1]] + + RepVals0[ModulationVals[y][x+1]] + 2) / 4; + } + else if(ModulationModes[y][x] == 2) // else if H-Only + { + ModVal = (RepVals0[ModulationVals[y][x-1]] + + RepVals0[ModulationVals[y][x+1]] + 1) / 2; + } + else // else it's V-Only + { + ModVal = (RepVals0[ModulationVals[y-1][x]] + + RepVals0[ModulationVals[y+1][x]] + 1) / 2; + } + } + else // else it's 4BPP and PT encoding + { + ModVal = RepVals1[ModulationVals[y][x]]; + + *DoPT = ModulationVals[y][x] == PT_INDEX; + } + + *Mod =ModVal; +} + +/*!*********************************************************************** + @Function TwiddleUV + @Input YSize Y dimension of the texture in pixels + @Input XSize X dimension of the texture in pixels + @Input YPos Pixel Y position + @Input XPos Pixel X position + @Returns The twiddled offset of the pixel + @Description Given the Block (or pixel) coordinates and the dimension of + the texture in blocks (or pixels) this returns the twiddled + offset of the block (or pixel) from the start of the map. + + NOTE the dimensions of the texture must be a power of 2 + *************************************************************************/ +static int DisableTwiddlingRoutine = 0; + +static U32 TwiddleUV(U32 YSize, U32 XSize, U32 YPos, U32 XPos) +{ + U32 Twiddled; + + U32 MinDimension; + U32 MaxValue; + + U32 SrcBitPos; + U32 DstBitPos; + + int ShiftCount; + + assert(YPos < YSize); + assert(XPos < XSize); + + assert(POWER_OF_2(YSize)); + assert(POWER_OF_2(XSize)); + + if(YSize < XSize) + { + MinDimension = YSize; + MaxValue = XPos; + } + else + { + MinDimension = XSize; + MaxValue = YPos; + } + + // Nasty hack to disable twiddling + if(DisableTwiddlingRoutine) + return (YPos* XSize + XPos); + + // Step through all the bits in the "minimum" dimension + SrcBitPos = 1; + DstBitPos = 1; + Twiddled = 0; + ShiftCount = 0; + + while(SrcBitPos < MinDimension) + { + if(YPos & SrcBitPos) + { + Twiddled |= DstBitPos; + } + + if(XPos & SrcBitPos) + { + Twiddled |= (DstBitPos << 1); + } + + + SrcBitPos <<= 1; + DstBitPos <<= 2; + ShiftCount += 1; + + } + + // prepend any unused bits + MaxValue >>= ShiftCount; + + Twiddled |= (MaxValue << (2*ShiftCount)); + + return Twiddled; +} + +/*!*********************************************************************** + @Function Decompress + @Input pCompressedData The PVRTC texture data to decompress + @Input Do2BitMode Signifies whether the data is PVRTC2 or PVRTC4 + @Input XDim X dimension of the texture + @Input YDim Y dimension of the texture + @Input AssumeImageTiles Assume the texture data tiles + @Modified pResultImage The decompressed texture data + @Description Decompresses PVRTC to RGBA 8888 + *************************************************************************/ +static void PVRDecompress(AMTC_BLOCK_STRUCT *pCompressedData, + const bool Do2bitMode, + const int XDim, + const int YDim, + const int AssumeImageTiles, + unsigned char* pResultImage) +{ + int x, y; + int i, j; + + int BlkX, BlkY; + int BlkXp1, BlkYp1; + int XBlockSize; + int BlkXDim, BlkYDim; + + int StartX, StartY; + + int ModulationVals[8][16]; + int ModulationModes[8][16]; + + int Mod, DoPT; + + unsigned int uPosition; + + // local neighbourhood of blocks + AMTC_BLOCK_STRUCT *pBlocks[2][2]; + + AMTC_BLOCK_STRUCT *pPrevious[2][2] = {{NULL, NULL}, {NULL, NULL}}; + + // Low precision colours extracted from the blocks + struct + { + int Reps[2][4]; + }Colours5554[2][2]; + + // Interpolated A and B colours for the pixel + int ASig[4], BSig[4]; + + int Result[4]; + + if(Do2bitMode) + XBlockSize = BLK_X_2BPP; + else + XBlockSize = BLK_X_4BPP; + + // For MBX don't allow the sizes to get too small + BlkXDim = PVRT_MAX(2, XDim / XBlockSize); + BlkYDim = PVRT_MAX(2, YDim / BLK_Y_SIZE); + + /* + Step through the pixels of the image decompressing each one in turn + + Note that this is a hideously inefficient way to do this! + */ + for(y = 0; y < YDim; y++) + { + for(x = 0; x < XDim; x++) + { + // map this pixel to the top left neighbourhood of blocks + BlkX = (x - XBlockSize/2); + BlkY = (y - BLK_Y_SIZE/2); + + BlkX = LIMIT_COORD(BlkX, XDim, AssumeImageTiles); + BlkY = LIMIT_COORD(BlkY, YDim, AssumeImageTiles); + + + BlkX /= XBlockSize; + BlkY /= BLK_Y_SIZE; + + // compute the positions of the other 3 blocks + BlkXp1 = LIMIT_COORD(BlkX+1, BlkXDim, AssumeImageTiles); + BlkYp1 = LIMIT_COORD(BlkY+1, BlkYDim, AssumeImageTiles); + + // Map to block memory locations + pBlocks[0][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkX); + pBlocks[0][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkXp1); + pBlocks[1][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkX); + pBlocks[1][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkXp1); + + + /* + extract the colours and the modulation information IF the previous values + have changed. + */ + if(memcmp(pPrevious, pBlocks, 4*sizeof(void*)) != 0) + { + StartY = 0; + for(i = 0; i < 2; i++) + { + StartX = 0; + for(j = 0; j < 2; j++) + { + Unpack5554Colour(pBlocks[i][j], Colours5554[i][j].Reps); + + UnpackModulations(pBlocks[i][j], + Do2bitMode, + ModulationVals, + ModulationModes, + StartX, StartY); + + StartX += XBlockSize; + } + + StartY += BLK_Y_SIZE; + } + + // make a copy of the new pointers + memcpy(pPrevious, pBlocks, 4*sizeof(void*)); + } + + // decompress the pixel. First compute the interpolated A and B signals + InterpolateColours(Colours5554[0][0].Reps[0], + Colours5554[0][1].Reps[0], + Colours5554[1][0].Reps[0], + Colours5554[1][1].Reps[0], + Do2bitMode, x, y, + ASig); + + InterpolateColours(Colours5554[0][0].Reps[1], + Colours5554[0][1].Reps[1], + Colours5554[1][0].Reps[1], + Colours5554[1][1].Reps[1], + Do2bitMode, x, y, + BSig); + + GetModulationValue(x,y, Do2bitMode, (const int (*)[16])ModulationVals, (const int (*)[16])ModulationModes, + &Mod, &DoPT); + + // compute the modulated colour + for(i = 0; i < 4; i++) + { + Result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]); + Result[i] >>= 3; + } + + if(DoPT) + Result[3] = 0; + + // Store the result in the output image + uPosition = (x+y*XDim)<<2; + pResultImage[uPosition+0] = (U8)Result[0]; + pResultImage[uPosition+1] = (U8)Result[1]; + pResultImage[uPosition+2] = (U8)Result[2]; + pResultImage[uPosition+3] = (U8)Result[3]; + } + } +} + +/***************************************************************************** + End of file (pvr.cpp) + *****************************************************************************/ \ No newline at end of file diff --git a/cocos/base/pvr.h b/cocos/base/pvr.h new file mode 100644 index 0000000000..0e29590836 --- /dev/null +++ b/cocos/base/pvr.h @@ -0,0 +1,16 @@ +// +// PVRDecompressor.h +// inferno +// +// Created by user-i121 on 09.07.13. +// +// + +#ifndef __PVR_H__ +#define __PVR_H__ + + +int PVRTDecompressPVRTC(const void * const pCompressedData,const int XDim,const int YDim,void *pDestData,const bool Do2bitMode); + + +#endif //__PVR_H__ diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 323a1aaa7e..138148bb26 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -66,6 +66,7 @@ extern "C" } #include "base/s3tc.h" #include "base/atitc.h" +#include "base/pvr.h" #include "base/TGAlib.h" #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) @@ -141,6 +142,34 @@ namespace PVRTC2BPP_RGBA = 1ULL, PVRTC4BPP_RGB = 2ULL, PVRTC4BPP_RGBA = 3ULL, + PVRTC2_2BPP_RGBA = 4ULL, + PVRTC2_4BPP_RGBA = 5ULL, + ETC1 = 6ULL, + DXT1 = 7ULL, + DXT2 = 8ULL, + DXT3 = 9ULL, + DXT4 = 10ULL, + DXT5 = 11ULL, + BC1 = 7ULL, + BC2 = 9ULL, + BC3 = 11ULL, + BC4 = 12ULL, + BC5 = 13ULL, + BC6 = 14ULL, + BC7 = 15ULL, + UYVY = 16ULL, + YUY2 = 17ULL, + BW1bpp = 18ULL, + R9G9B9E5 = 19ULL, + RGBG8888 = 20ULL, + GRGB8888 = 21ULL, + ETC2_RGB = 22ULL, + ETC2_RGBA = 23ULL, + ETC2_RGBA1 = 24ULL, + EAC_R11_Unsigned = 25ULL, + EAC_R11_Signed = 26ULL, + EAC_RG11_Unsigned = 27ULL, + EAC_RG11_Signed = 28ULL, BGRA8888 = 0x0808080861726762ULL, RGBA8888 = 0x0808080861626772ULL, @@ -169,10 +198,8 @@ namespace _pixel2_formathash::value_type(PVR2TexturePixelFormat::I8, Texture2D::PixelFormat::I8), _pixel2_formathash::value_type(PVR2TexturePixelFormat::AI88, Texture2D::PixelFormat::AI88), -#ifdef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC2BPP_RGBA, Texture2D::PixelFormat::PVRTC2A), _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC4BPP_RGBA, Texture2D::PixelFormat::PVRTC4A), -#endif }; static const int PVR2_MAX_TABLE_ELEMENTS = sizeof(v2_pixel_formathash_value) / sizeof(v2_pixel_formathash_value[0]); @@ -192,12 +219,12 @@ namespace _pixel3_formathash::value_type(PVR3TexturePixelFormat::L8, Texture2D::PixelFormat::I8), _pixel3_formathash::value_type(PVR3TexturePixelFormat::LA88, Texture2D::PixelFormat::AI88), -#ifdef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGB, Texture2D::PixelFormat::PVRTC2), _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGBA, Texture2D::PixelFormat::PVRTC2A), _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGB, Texture2D::PixelFormat::PVRTC4), _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGBA, Texture2D::PixelFormat::PVRTC4A), -#endif + + _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC1, Texture2D::PixelFormat::ETC), }; static const int PVR3_MAX_TABLE_ELEMENTS = sizeof(v3_pixel_formathash_value) / sizeof(v3_pixel_formathash_value[0]); @@ -415,6 +442,11 @@ Image::Image() Image::~Image() { + for (unsigned int i = 0; i < _numberOfMipmaps; ++i) + { + if(_mipmaps[i].unpack) + CC_SAFE_DELETE_ARRAY(_mipmaps[i].address); + } CC_SAFE_FREE(_data); } @@ -1181,29 +1213,36 @@ namespace { bool testFormatForPvr2TCSupport(PVR2TexturePixelFormat format) { - if (!Configuration::getInstance()->supportsPVRTC()) - { - if (format == PVR2TexturePixelFormat::PVRTC2BPP_RGBA || - format == PVR2TexturePixelFormat::PVRTC4BPP_RGBA) - { - return false; - } - } - return true; } bool testFormatForPvr3TCSupport(PVR3TexturePixelFormat format) { - if (!Configuration::getInstance()->supportsPVRTC()) + if (format == PVR3TexturePixelFormat::PVRTC2_2BPP_RGBA || + format == PVR3TexturePixelFormat::PVRTC2_4BPP_RGBA || + format == PVR3TexturePixelFormat::DXT1 || + format == PVR3TexturePixelFormat::DXT2 || + format == PVR3TexturePixelFormat::DXT3 || + format == PVR3TexturePixelFormat::DXT4 || + format == PVR3TexturePixelFormat::DXT5 || + format == PVR3TexturePixelFormat::BC4 || + format == PVR3TexturePixelFormat::BC5 || + format == PVR3TexturePixelFormat::BC6 || + format == PVR3TexturePixelFormat::BC7 || + format == PVR3TexturePixelFormat::UYVY || + format == PVR3TexturePixelFormat::YUY2 || + format == PVR3TexturePixelFormat::BW1bpp || + format == PVR3TexturePixelFormat::R9G9B9E5 || + format == PVR3TexturePixelFormat::RGBG8888 || + format == PVR3TexturePixelFormat::ETC2_RGB || + format == PVR3TexturePixelFormat::ETC2_RGBA || + format == PVR3TexturePixelFormat::ETC2_RGBA1 || + format == PVR3TexturePixelFormat::EAC_R11_Unsigned || + format == PVR3TexturePixelFormat::EAC_R11_Signed || + format == PVR3TexturePixelFormat::EAC_RG11_Unsigned || + format == PVR3TexturePixelFormat::EAC_RG11_Signed) { - if (format == PVR3TexturePixelFormat::PVRTC2BPP_RGB || - format == PVR3TexturePixelFormat::PVRTC2BPP_RGBA || - format == PVR3TexturePixelFormat::PVRTC4BPP_RGB || - format == PVR3TexturePixelFormat::PVRTC4BPP_RGBA) - { - return false; - } + return false; } return true; @@ -1284,13 +1323,32 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) // Calculate the data size for each texture level and respect the minimum number of blocks while (dataOffset < dataLength) { + _mipmaps[_numberOfMipmaps].unpack = false; switch (formatFlags) { case PVR2TexturePixelFormat::PVRTC2BPP_RGBA: + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); + _mipmaps[_numberOfMipmaps].unpack = true; + _mipmaps[_numberOfMipmaps].len = width*height*4; + _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); + _renderFormat = Texture2D::PixelFormat::RGBA8888; + } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; heightBlocks = height / 4; break; case PVR2TexturePixelFormat::PVRTC4BPP_RGBA: + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); + _mipmaps[_numberOfMipmaps].unpack = true; + _mipmaps[_numberOfMipmaps].len = width*height*4; + _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); + _renderFormat = Texture2D::PixelFormat::RGBA8888; + } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; heightBlocks = height / 4; @@ -1323,8 +1381,11 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) packetLength = packetLength > dataSize ? dataSize : packetLength; //Make record to the mipmaps array and increment counter - _mipmaps[_numberOfMipmaps].address = _data + dataOffset; - _mipmaps[_numberOfMipmaps].len = packetLength; + if(!_mipmaps[_numberOfMipmaps].unpack) + { + _mipmaps[_numberOfMipmaps].address = _data + dataOffset; + _mipmaps[_numberOfMipmaps].len = packetLength; + } _numberOfMipmaps++; dataOffset += packetLength; @@ -1408,16 +1469,54 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) for (int i = 0; i < _numberOfMipmaps; i++) { + _mipmaps[i].unpack = false; switch ((PVR3TexturePixelFormat)pixelFormat) { case PVR3TexturePixelFormat::PVRTC2BPP_RGB : case PVR3TexturePixelFormat::PVRTC2BPP_RGBA : + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _mipmaps[i].unpack = true; + _mipmaps[i].len = width*height*4; + _mipmaps[i].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); + _renderFormat = Texture2D::PixelFormat::RGBA8888; + } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; heightBlocks = height / 4; break; case PVR3TexturePixelFormat::PVRTC4BPP_RGB : case PVR3TexturePixelFormat::PVRTC4BPP_RGBA : + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _mipmaps[i].unpack = true; + _mipmaps[i].len = width*height*4; + _mipmaps[i].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); + _renderFormat = Texture2D::PixelFormat::RGBA8888; + } + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case PVR3TexturePixelFormat::ETC1: + if(!Configuration::getInstance()->supportsETC()) + { + CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder"); + int bytePerPixel = 3; + unsigned int stride = width * bytePerPixel; + _mipmaps[i].unpack = true; + _mipmaps[i].len = width*height*bytePerPixel; + _mipmaps[i].address = new unsigned char[width*height*bytePerPixel]; + if (etc1_decode_image(static_cast(_data+dataOffset), static_cast(_mipmaps[i].address), width, height, bytePerPixel, stride) != 0) + { + return false; + } + _renderFormat = Texture2D::PixelFormat::RGB888; + } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; heightBlocks = height / 4; @@ -1449,8 +1548,11 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) auto packetLength = _dataLen - dataOffset; packetLength = packetLength > dataSize ? dataSize : packetLength; - _mipmaps[i].address = _data + dataOffset; - _mipmaps[i].len = static_cast(packetLength); + if(!_mipmaps[i].unpack) + { + _mipmaps[i].address = _data + dataOffset; + _mipmaps[i].len = static_cast(packetLength); + } dataOffset += packetLength; CCAssert(dataOffset <= _dataLen, "CCTexurePVR: Invalid lenght"); diff --git a/cocos/platform/CCImage.h b/cocos/platform/CCImage.h index 5c37da9436..815ec31bb6 100644 --- a/cocos/platform/CCImage.h +++ b/cocos/platform/CCImage.h @@ -51,6 +51,8 @@ typedef struct _MipmapInfo { unsigned char* address; int len; + bool unpack; + _MipmapInfo():address(NULL),len(0),unpack(false){} }MipmapInfo; class CC_DLL Image : public Ref diff --git a/cocos/platform/win32/CCGL.h b/cocos/platform/win32/CCGL.h index 4ec822b630..2ed38288bc 100644 --- a/cocos/platform/win32/CCGL.h +++ b/cocos/platform/win32/CCGL.h @@ -33,12 +33,6 @@ THE SOFTWARE. #define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8 -// These macros are only for making TexturePVR.cpp complied without errors since they are not included in GLEW. -#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 - #endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 #endif // __CCGL_H__ From 1a617ad804d07391a8d3ac37f39aba879506d4ac Mon Sep 17 00:00:00 2001 From: Sergey Date: Thu, 20 Mar 2014 13:07:28 +0400 Subject: [PATCH 2/8] pvr display fix pvr decompression on 64 bit platforms fix --- cocos/base/pvr.cpp | 13 ++------ cocos/platform/CCImage.cpp | 64 ++++++++++++++++++++++++++++---------- cocos/platform/CCImage.h | 4 +-- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/cocos/base/pvr.cpp b/cocos/base/pvr.cpp index d3fbb7e854..bb33452248 100644 --- a/cocos/base/pvr.cpp +++ b/cocos/base/pvr.cpp @@ -41,8 +41,9 @@ /***************************************************************************** * Useful typedefs *****************************************************************************/ -typedef unsigned long U32; -typedef unsigned char U8; + +typedef uint32_t U32; +typedef uint8_t U8; /*********************************************************** DECOMPRESSION ROUTINES @@ -80,14 +81,6 @@ int PVRTDecompressPVRTC(const void * const pCompressedData,const int XDim,const PVRDecompress((AMTC_BLOCK_STRUCT*)pCompressedData,Do2bitMode,XDim,YDim,1,(unsigned char*)pDestData); unsigned char* pSwap = (unsigned char*)pDestData, swap; - for(int i=0;isupportsPVRTC()) + return format; + else + return Texture2D::PixelFormat::RGBA8888; + case Texture2D::PixelFormat::ETC: + if(Configuration::getInstance()->supportsETC()) + return format; + else + return Texture2D::PixelFormat::RGB888; + default: + return format; + } +} + ////////////////////////////////////////////////////////////////////////// // Implement Image ////////////////////////////////////////////////////////////////////////// @@ -431,6 +452,7 @@ Image::Image() , _dataLen(0) , _width(0) , _height(0) +, _unpack(false) , _fileType(Format::UNKOWN) , _renderFormat(Texture2D::PixelFormat::NONE) , _preMulti(false) @@ -442,12 +464,13 @@ Image::Image() Image::~Image() { - for (unsigned int i = 0; i < _numberOfMipmaps; ++i) + if(_unpack) { - if(_mipmaps[i].unpack) + for (unsigned int i = 0; i < _numberOfMipmaps; ++i) CC_SAFE_DELETE_ARRAY(_mipmaps[i].address); } - CC_SAFE_FREE(_data); + else + CC_SAFE_FREE(_data); } bool Image::initWithImageFile(const std::string& path) @@ -1295,7 +1318,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) return false; } - auto it = Texture2D::getPixelFormatInfoMap().find(v2_pixel_formathash.at(formatFlags)); + auto it = Texture2D::getPixelFormatInfoMap().find(getDevicePixelFormat(v2_pixel_formathash.at(formatFlags))); if (it == Texture2D::getPixelFormatInfoMap().end()) { @@ -1323,13 +1346,12 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) // Calculate the data size for each texture level and respect the minimum number of blocks while (dataOffset < dataLength) { - _mipmaps[_numberOfMipmaps].unpack = false; switch (formatFlags) { case PVR2TexturePixelFormat::PVRTC2BPP_RGBA: if(!Configuration::getInstance()->supportsPVRTC()) { CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); - _mipmaps[_numberOfMipmaps].unpack = true; + _unpack = true; _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); @@ -1343,7 +1365,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) if(!Configuration::getInstance()->supportsPVRTC()) { CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); - _mipmaps[_numberOfMipmaps].unpack = true; + _unpack = true; _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); @@ -1381,7 +1403,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) packetLength = packetLength > dataSize ? dataSize : packetLength; //Make record to the mipmaps array and increment counter - if(!_mipmaps[_numberOfMipmaps].unpack) + if(!_unpack) { _mipmaps[_numberOfMipmaps].address = _data + dataOffset; _mipmaps[_numberOfMipmaps].len = packetLength; @@ -1394,6 +1416,12 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); } + + if(_unpack) + { + _data = _mipmaps[0].address; + _dataLen = _mipmaps[0].len; + } return true; } @@ -1432,7 +1460,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) return false; } - auto it = Texture2D::getPixelFormatInfoMap().find(v3_pixel_formathash.at(pixelFormat)); + auto it = Texture2D::getPixelFormatInfoMap().find(getDevicePixelFormat(v3_pixel_formathash.at(pixelFormat))); if (it == Texture2D::getPixelFormatInfoMap().end()) { @@ -1469,7 +1497,6 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) for (int i = 0; i < _numberOfMipmaps; i++) { - _mipmaps[i].unpack = false; switch ((PVR3TexturePixelFormat)pixelFormat) { case PVR3TexturePixelFormat::PVRTC2BPP_RGB : @@ -1477,11 +1504,10 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) if(!Configuration::getInstance()->supportsPVRTC()) { CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _mipmaps[i].unpack = true; + _unpack = true; _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); - _renderFormat = Texture2D::PixelFormat::RGBA8888; } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; @@ -1492,11 +1518,10 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) if(!Configuration::getInstance()->supportsPVRTC()) { CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _mipmaps[i].unpack = true; + _unpack = true; _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); - _renderFormat = Texture2D::PixelFormat::RGBA8888; } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; @@ -1508,14 +1533,13 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder"); int bytePerPixel = 3; unsigned int stride = width * bytePerPixel; - _mipmaps[i].unpack = true; + _unpack = true; _mipmaps[i].len = width*height*bytePerPixel; _mipmaps[i].address = new unsigned char[width*height*bytePerPixel]; if (etc1_decode_image(static_cast(_data+dataOffset), static_cast(_mipmaps[i].address), width, height, bytePerPixel, stride) != 0) { return false; } - _renderFormat = Texture2D::PixelFormat::RGB888; } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; @@ -1548,7 +1572,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) auto packetLength = _dataLen - dataOffset; packetLength = packetLength > dataSize ? dataSize : packetLength; - if(!_mipmaps[i].unpack) + if(!_unpack) { _mipmaps[i].address = _data + dataOffset; _mipmaps[i].len = static_cast(packetLength); @@ -1561,6 +1585,12 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); } + + if(_unpack) + { + _data = _mipmaps[0].address; + _dataLen = _mipmaps[0].len; + } return true; } diff --git a/cocos/platform/CCImage.h b/cocos/platform/CCImage.h index 815ec31bb6..9cb49f63d1 100644 --- a/cocos/platform/CCImage.h +++ b/cocos/platform/CCImage.h @@ -51,8 +51,7 @@ typedef struct _MipmapInfo { unsigned char* address; int len; - bool unpack; - _MipmapInfo():address(NULL),len(0),unpack(false){} + _MipmapInfo():address(NULL),len(0){} }MipmapInfo; class CC_DLL Image : public Ref @@ -169,6 +168,7 @@ protected: ssize_t _dataLen; int _width; int _height; + bool _unpack; Format _fileType; Texture2D::PixelFormat _renderFormat; bool _preMulti; From 624b6a5af4029973a91c61b5928ef402da359fc4 Mon Sep 17 00:00:00 2001 From: Sergey Date: Thu, 20 Mar 2014 13:08:18 +0400 Subject: [PATCH 3/8] unused variable removed --- cocos/base/pvr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos/base/pvr.cpp b/cocos/base/pvr.cpp index bb33452248..1b73c81fbc 100644 --- a/cocos/base/pvr.cpp +++ b/cocos/base/pvr.cpp @@ -79,7 +79,6 @@ static void PVRDecompress(AMTC_BLOCK_STRUCT *pCompressedData, int PVRTDecompressPVRTC(const void * const pCompressedData,const int XDim,const int YDim, void *pDestData,const bool Do2bitMode) { PVRDecompress((AMTC_BLOCK_STRUCT*)pCompressedData,Do2bitMode,XDim,YDim,1,(unsigned char*)pDestData); - unsigned char* pSwap = (unsigned char*)pDestData, swap; return XDim*YDim/2; } From 600dbebfb0c48697bc8bb2ef48a075767be1eb5d Mon Sep 17 00:00:00 2001 From: Sergey Date: Tue, 25 Mar 2014 11:47:14 +0400 Subject: [PATCH 4/8] pvr 2bpp decompression fixed --- cocos/platform/CCImage.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 9cc0fa8b9f..34b6ddac8e 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1350,11 +1350,11 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) case PVR2TexturePixelFormat::PVRTC2BPP_RGBA: if(!Configuration::getInstance()->supportsPVRTC()) { - CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); _unpack = true; _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, true); _renderFormat = Texture2D::PixelFormat::RGBA8888; } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp @@ -1364,11 +1364,11 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) case PVR2TexturePixelFormat::PVRTC4BPP_RGBA: if(!Configuration::getInstance()->supportsPVRTC()) { - CCLOG("cocos2d: TexturePVR. PVRTC not supported on this device unpacking"); + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); _unpack = true; _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address,false); + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, false); _renderFormat = Texture2D::PixelFormat::RGBA8888; } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp @@ -1507,7 +1507,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) _unpack = true; _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true); } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; @@ -1521,7 +1521,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) _unpack = true; _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address,false); + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, false); } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; From 9c0493d40bcfa785fdc5eaa4256a5a4f2880221f Mon Sep 17 00:00:00 2001 From: Sergey Date: Tue, 25 Mar 2014 12:16:56 +0400 Subject: [PATCH 5/8] mipmaps loading fix --- cocos/platform/CCImage.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 34b6ddac8e..2dbc86268c 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1327,6 +1327,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) } _renderFormat = it->first; + int bpp = it->second.bpp; //Reset num of mipmaps _numberOfMipmaps = 0; @@ -1355,7 +1356,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, true); - _renderFormat = Texture2D::PixelFormat::RGBA8888; + bpp = 2; } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; @@ -1369,7 +1370,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) _mipmaps[_numberOfMipmaps].len = width*height*4; _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, false); - _renderFormat = Texture2D::PixelFormat::RGBA8888; + bpp = 4; } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; @@ -1398,7 +1399,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) heightBlocks = 2; } - dataSize = widthBlocks * heightBlocks * ((blockSize * it->second.bpp) / 8); + dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); int packetLength = (dataLength - dataOffset); packetLength = packetLength > dataSize ? dataSize : packetLength; @@ -1470,6 +1471,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) } _renderFormat = it->first; + int bpp = it->second.bpp; // flags int flags = CC_SWAP_INT32_LITTLE_TO_HOST(header->flags); @@ -1507,7 +1509,8 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) _unpack = true; _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true); + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true); + bpp = 2; } blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; @@ -1522,6 +1525,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) _mipmaps[i].len = width*height*4; _mipmaps[i].address = new unsigned char[width*height*4]; PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, false); + bpp = 4; } blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; @@ -1568,7 +1572,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) heightBlocks = 2; } - dataSize = widthBlocks * heightBlocks * ((blockSize * it->second.bpp) / 8); + dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); auto packetLength = _dataLen - dataOffset; packetLength = packetLength > dataSize ? dataSize : packetLength; From 5c62a2fea72779c49f57755289d47508d18c343f Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 7 Jun 2014 14:04:47 +0400 Subject: [PATCH 6/8] template fix --- templates/cocos2dx_files.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/cocos2dx_files.json b/templates/cocos2dx_files.json index 60676e1716..637fb5bf6b 100644 --- a/templates/cocos2dx_files.json +++ b/templates/cocos2dx_files.json @@ -378,6 +378,8 @@ "cocos/base/etc1.cpp", "cocos/base/etc1.h", "cocos/base/firePngData.h", + "cocos/base/pvr.cpp", + "cocos/base/pvr.h", "cocos/base/s3tc.cpp", "cocos/base/s3tc.h", "cocos/base/uthash.h", From 59cbc153d45f212b98c66b5e047d621ac5ebcf06 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 25 Jun 2014 22:44:20 +0400 Subject: [PATCH 7/8] Copyright & small fixes --- cocos/base/pvr.cpp | 10 +- cocos/base/pvr.h | 20 ++- cocos/platform/CCImage.cpp | 257 ++++++++++++++++----------------- cocos/renderer/CCTexture2D.cpp | 2 +- 4 files changed, 151 insertions(+), 138 deletions(-) diff --git a/cocos/base/pvr.cpp b/cocos/base/pvr.cpp index 1b73c81fbc..b2ce270618 100644 --- a/cocos/base/pvr.cpp +++ b/cocos/base/pvr.cpp @@ -1,6 +1,14 @@ /****************************************************************************** - @File pvr.cpp + @File PVRTDecompress.cpp + + @Title + + @Copyright Copyright (C) 2000 - 2008 by Imagination Technologies Limited. + + @Platform ANSI compatible + + @Description PVRTC Texture Decompression. ******************************************************************************/ #include diff --git a/cocos/base/pvr.h b/cocos/base/pvr.h index 0e29590836..33c14a4e06 100644 --- a/cocos/base/pvr.h +++ b/cocos/base/pvr.h @@ -1,10 +1,16 @@ -// -// PVRDecompressor.h -// inferno -// -// Created by user-i121 on 09.07.13. -// -// +/****************************************************************************** + + @File PVRTDecompress.h + + @Title + + @Copyright Copyright (C) 2000 - 2008 by Imagination Technologies Limited. + + @Platform ANSI compatible + + @Description PVRTC Texture Decompression. + + ******************************************************************************/ #ifndef __PVR_H__ #define __PVR_H__ diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 2dbc86268c..07335110cd 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1241,34 +1241,33 @@ namespace bool testFormatForPvr3TCSupport(PVR3TexturePixelFormat format) { - if (format == PVR3TexturePixelFormat::PVRTC2_2BPP_RGBA || - format == PVR3TexturePixelFormat::PVRTC2_4BPP_RGBA || - format == PVR3TexturePixelFormat::DXT1 || - format == PVR3TexturePixelFormat::DXT2 || - format == PVR3TexturePixelFormat::DXT3 || - format == PVR3TexturePixelFormat::DXT4 || - format == PVR3TexturePixelFormat::DXT5 || - format == PVR3TexturePixelFormat::BC4 || - format == PVR3TexturePixelFormat::BC5 || - format == PVR3TexturePixelFormat::BC6 || - format == PVR3TexturePixelFormat::BC7 || - format == PVR3TexturePixelFormat::UYVY || - format == PVR3TexturePixelFormat::YUY2 || - format == PVR3TexturePixelFormat::BW1bpp || - format == PVR3TexturePixelFormat::R9G9B9E5 || - format == PVR3TexturePixelFormat::RGBG8888 || - format == PVR3TexturePixelFormat::ETC2_RGB || - format == PVR3TexturePixelFormat::ETC2_RGBA || - format == PVR3TexturePixelFormat::ETC2_RGBA1 || - format == PVR3TexturePixelFormat::EAC_R11_Unsigned || - format == PVR3TexturePixelFormat::EAC_R11_Signed || - format == PVR3TexturePixelFormat::EAC_RG11_Unsigned || - format == PVR3TexturePixelFormat::EAC_RG11_Signed) - { - return false; + switch (format) { + case PVR3TexturePixelFormat::DXT1: + case PVR3TexturePixelFormat::DXT3: + case PVR3TexturePixelFormat::DXT5: + return Configuration::getInstance()->supportsS3TC(); + + case PVR3TexturePixelFormat::BGRA8888: + return Configuration::getInstance()->supportsBGRA8888(); + + case PVR3TexturePixelFormat::PVRTC2BPP_RGB: + case PVR3TexturePixelFormat::PVRTC2BPP_RGBA: + case PVR3TexturePixelFormat::PVRTC4BPP_RGB: + case PVR3TexturePixelFormat::PVRTC4BPP_RGBA: + case PVR3TexturePixelFormat::ETC1: + case PVR3TexturePixelFormat::RGBA8888: + case PVR3TexturePixelFormat::RGBA4444: + case PVR3TexturePixelFormat::RGBA5551: + case PVR3TexturePixelFormat::RGB565: + case PVR3TexturePixelFormat::RGB888: + case PVR3TexturePixelFormat::A8: + case PVR3TexturePixelFormat::L8: + case PVR3TexturePixelFormat::LA88: + return true; + + default: + return false; } - - return true; } } @@ -1348,47 +1347,47 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) while (dataOffset < dataLength) { switch (formatFlags) { - case PVR2TexturePixelFormat::PVRTC2BPP_RGBA: - if(!Configuration::getInstance()->supportsPVRTC()) - { - CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _unpack = true; - _mipmaps[_numberOfMipmaps].len = width*height*4; - _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, true); - bpp = 2; - } - blockSize = 8 * 4; // Pixel by pixel block size for 2bpp - widthBlocks = width / 8; - heightBlocks = height / 4; - break; - case PVR2TexturePixelFormat::PVRTC4BPP_RGBA: - if(!Configuration::getInstance()->supportsPVRTC()) - { - CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _unpack = true; - _mipmaps[_numberOfMipmaps].len = width*height*4; - _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, false); - bpp = 4; - } - blockSize = 4 * 4; // Pixel by pixel block size for 4bpp - widthBlocks = width / 4; - heightBlocks = height / 4; - break; - case PVR2TexturePixelFormat::BGRA8888: - if (Configuration::getInstance()->supportsBGRA8888() == false) - { - CCLOG("cocos2d: Image. BGRA8888 not supported on this device"); - return false; - } - default: - blockSize = 1; - widthBlocks = width; - heightBlocks = height; - break; + case PVR2TexturePixelFormat::PVRTC2BPP_RGBA: + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _unpack = true; + _mipmaps[_numberOfMipmaps].len = width*height*4; + _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, true); + bpp = 2; + } + blockSize = 8 * 4; // Pixel by pixel block size for 2bpp + widthBlocks = width / 8; + heightBlocks = height / 4; + break; + case PVR2TexturePixelFormat::PVRTC4BPP_RGBA: + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _unpack = true; + _mipmaps[_numberOfMipmaps].len = width*height*4; + _mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, false); + bpp = 4; + } + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case PVR2TexturePixelFormat::BGRA8888: + if (Configuration::getInstance()->supportsBGRA8888() == false) + { + CCLOG("cocos2d: Image. BGRA8888 not supported on this device"); + return false; + } + default: + blockSize = 1; + widthBlocks = width; + heightBlocks = height; + break; } - + // Clamp to minimum number of blocks if (widthBlocks < 2) { @@ -1398,11 +1397,11 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) { heightBlocks = 2; } - + dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); int packetLength = (dataLength - dataOffset); packetLength = packetLength > dataSize ? dataSize : packetLength; - + //Make record to the mipmaps array and increment counter if(!_unpack) { @@ -1410,9 +1409,9 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen) _mipmaps[_numberOfMipmaps].len = packetLength; } _numberOfMipmaps++; - + dataOffset += packetLength; - + //Update width and height to the next lower power of two width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); @@ -1501,65 +1500,65 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen) { switch ((PVR3TexturePixelFormat)pixelFormat) { - case PVR3TexturePixelFormat::PVRTC2BPP_RGB : - case PVR3TexturePixelFormat::PVRTC2BPP_RGBA : - if(!Configuration::getInstance()->supportsPVRTC()) - { - CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _unpack = true; - _mipmaps[i].len = width*height*4; - _mipmaps[i].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true); - bpp = 2; - } - blockSize = 8 * 4; // Pixel by pixel block size for 2bpp - widthBlocks = width / 8; - heightBlocks = height / 4; - break; - case PVR3TexturePixelFormat::PVRTC4BPP_RGB : - case PVR3TexturePixelFormat::PVRTC4BPP_RGBA : - if(!Configuration::getInstance()->supportsPVRTC()) - { - CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); - _unpack = true; - _mipmaps[i].len = width*height*4; - _mipmaps[i].address = new unsigned char[width*height*4]; - PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, false); - bpp = 4; - } - blockSize = 4 * 4; // Pixel by pixel block size for 4bpp - widthBlocks = width / 4; - heightBlocks = height / 4; - break; - case PVR3TexturePixelFormat::ETC1: - if(!Configuration::getInstance()->supportsETC()) - { - CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder"); - int bytePerPixel = 3; - unsigned int stride = width * bytePerPixel; - _unpack = true; - _mipmaps[i].len = width*height*bytePerPixel; - _mipmaps[i].address = new unsigned char[width*height*bytePerPixel]; - if (etc1_decode_image(static_cast(_data+dataOffset), static_cast(_mipmaps[i].address), width, height, bytePerPixel, stride) != 0) - { - return false; - } - } - blockSize = 4 * 4; // Pixel by pixel block size for 4bpp - widthBlocks = width / 4; - heightBlocks = height / 4; - break; - case PVR3TexturePixelFormat::BGRA8888: - if( ! Configuration::getInstance()->supportsBGRA8888()) + case PVR3TexturePixelFormat::PVRTC2BPP_RGB : + case PVR3TexturePixelFormat::PVRTC2BPP_RGBA : + if(!Configuration::getInstance()->supportsPVRTC()) { - CCLOG("cocos2d: Image. BGRA8888 not supported on this device"); - return false; - } - default: - blockSize = 1; - widthBlocks = width; - heightBlocks = height; - break; + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _unpack = true; + _mipmaps[i].len = width*height*4; + _mipmaps[i].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true); + bpp = 2; + } + blockSize = 8 * 4; // Pixel by pixel block size for 2bpp + widthBlocks = width / 8; + heightBlocks = height / 4; + break; + case PVR3TexturePixelFormat::PVRTC4BPP_RGB : + case PVR3TexturePixelFormat::PVRTC4BPP_RGBA : + if(!Configuration::getInstance()->supportsPVRTC()) + { + CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder"); + _unpack = true; + _mipmaps[i].len = width*height*4; + _mipmaps[i].address = new unsigned char[width*height*4]; + PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, false); + bpp = 4; + } + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case PVR3TexturePixelFormat::ETC1: + if(!Configuration::getInstance()->supportsETC()) + { + CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder"); + int bytePerPixel = 3; + unsigned int stride = width * bytePerPixel; + _unpack = true; + _mipmaps[i].len = width*height*bytePerPixel; + _mipmaps[i].address = new unsigned char[width*height*bytePerPixel]; + if (etc1_decode_image(static_cast(_data+dataOffset), static_cast(_mipmaps[i].address), width, height, bytePerPixel, stride) != 0) + { + return false; + } + } + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case PVR3TexturePixelFormat::BGRA8888: + if( ! Configuration::getInstance()->supportsBGRA8888()) + { + CCLOG("cocos2d: Image. BGRA8888 not supported on this device"); + return false; + } + default: + blockSize = 1; + widthBlocks = width; + heightBlocks = height; + break; } // Clamp to minimum number of blocks diff --git a/cocos/renderer/CCTexture2D.cpp b/cocos/renderer/CCTexture2D.cpp index e41a610dd5..d120aa3112 100644 --- a/cocos/renderer/CCTexture2D.cpp +++ b/cocos/renderer/CCTexture2D.cpp @@ -79,7 +79,7 @@ namespace { #endif #ifdef GL_ETC1_RGB8_OES - PixelFormatInfoMapValue(Texture2D::PixelFormat::ETC, Texture2D::PixelFormatInfo(GL_ETC1_RGB8_OES, 0xFFFFFFFF, 0xFFFFFFFF, 24, true, false)), + PixelFormatInfoMapValue(Texture2D::PixelFormat::ETC, Texture2D::PixelFormatInfo(GL_ETC1_RGB8_OES, 0xFFFFFFFF, 0xFFFFFFFF, 4, true, false)), #endif #ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT From 9e692cd329514c00655c3904c6f213df6a79a2a8 Mon Sep 17 00:00:00 2001 From: Sergey Date: Thu, 26 Jun 2014 11:46:19 +0400 Subject: [PATCH 8/8] missing include --- cocos/base/pvr.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos/base/pvr.cpp b/cocos/base/pvr.cpp index b2ce270618..3a59860c6f 100644 --- a/cocos/base/pvr.cpp +++ b/cocos/base/pvr.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "pvr.h" #define PVRT_MIN(a,b) (((a) < (b)) ? (a) : (b))