mirror of https://github.com/axmolengine/axmol.git
Merge pull request #6997 from newnon/v3_software_pvr_decompression
V3 software pvr decompression
This commit is contained in:
commit
1af3236d09
|
@ -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 = "<group>"; };
|
||||
A5BC6BA719430ABA00AD87B3 /* pvr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pvr.h; path = ../base/pvr.h; sourceTree = "<group>"; };
|
||||
B29594AF1926D5D9003EEF37 /* ccShader_3D_Color.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Color.frag; sourceTree = "<group>"; };
|
||||
B29594B01926D5D9003EEF37 /* ccShader_3D_ColorTex.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorTex.frag; sourceTree = "<group>"; };
|
||||
B29594B11926D5D9003EEF37 /* ccShader_3D_PositionTex.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_PositionTex.vert; sourceTree = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -229,6 +229,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
|
|||
<ClCompile Include="..\base\ccUtils.cpp" />
|
||||
<ClCompile Include="..\base\CCValue.cpp" />
|
||||
<ClCompile Include="..\base\etc1.cpp" />
|
||||
<ClCompile Include="..\base\pvr.cpp" />
|
||||
<ClCompile Include="..\base\ObjectFactory.cpp" />
|
||||
<ClCompile Include="..\base\s3tc.cpp" />
|
||||
<ClCompile Include="..\base\TGAlib.cpp" />
|
||||
|
@ -422,6 +423,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
|
|||
<ClInclude Include="..\base\etc1.h" />
|
||||
<ClInclude Include="..\base\firePngData.h" />
|
||||
<ClInclude Include="..\base\ObjectFactory.h" />
|
||||
<ClInclude Include="..\base\pvr.h" />
|
||||
<ClInclude Include="..\base\s3tc.h" />
|
||||
<ClInclude Include="..\base\TGAlib.h" />
|
||||
<ClInclude Include="..\base\uthash.h" />
|
||||
|
|
|
@ -418,6 +418,9 @@
|
|||
<ClCompile Include="..\base\etc1.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\base\pvr.cpp">
|
||||
<Filter>platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\base\s3tc.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
|
@ -991,6 +994,9 @@
|
|||
<ClInclude Include="..\base\etc1.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\base\pvr.h">
|
||||
<Filter>platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\base\firePngData.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -0,0 +1,713 @@
|
|||
/******************************************************************************
|
||||
|
||||
@File PVRTDecompress.cpp
|
||||
|
||||
@Title
|
||||
|
||||
@Copyright Copyright (C) 2000 - 2008 by Imagination Technologies Limited.
|
||||
|
||||
@Platform ANSI compatible
|
||||
|
||||
@Description PVRTC Texture Decompression.
|
||||
|
||||
******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#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 uint32_t U32;
|
||||
typedef uint8_t 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);
|
||||
|
||||
return XDim*YDim/2;
|
||||
}
|
||||
|
||||
/*!***********************************************************************
|
||||
@Function util_number_is_power_2
|
||||
@Input input A number
|
||||
@Returns TRUE if the number is an integer power of two, else FALSE.
|
||||
@Description Check that a number is an integer power of two, i.e.
|
||||
1, 2, 4, 8, ... etc.
|
||||
Returns FALSE for zero.
|
||||
*************************************************************************/
|
||||
int util_number_is_power_2( unsigned input )
|
||||
{
|
||||
unsigned minus1;
|
||||
|
||||
if( !input ) return 0;
|
||||
|
||||
minus1 = input - 1;
|
||||
return ( (input | minus1) == (input ^ minus1) ) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*!***********************************************************************
|
||||
@Function Unpack5554Colour
|
||||
@Input pBlock
|
||||
@Input ABColours
|
||||
@Description Given a block, extract the colour information and convert
|
||||
to 5554 formats
|
||||
*************************************************************************/
|
||||
static void Unpack5554Colour(const AMTC_BLOCK_STRUCT *pBlock,
|
||||
int ABColours[2][4])
|
||||
{
|
||||
U32 RawBits[2];
|
||||
|
||||
int i;
|
||||
|
||||
// Extract A and B
|
||||
RawBits[0] = pBlock->PackedData[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)
|
||||
*****************************************************************************/
|
|
@ -0,0 +1,22 @@
|
|||
/******************************************************************************
|
||||
|
||||
@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__
|
||||
|
||||
|
||||
int PVRTDecompressPVRTC(const void * const pCompressedData,const int XDim,const int YDim,void *pDestData,const bool Do2bitMode);
|
||||
|
||||
|
||||
#endif //__PVR_H__
|
|
@ -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]);
|
||||
|
@ -395,6 +422,27 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
Texture2D::PixelFormat getDevicePixelFormat(Texture2D::PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case Texture2D::PixelFormat::PVRTC4:
|
||||
case Texture2D::PixelFormat::PVRTC4A:
|
||||
case Texture2D::PixelFormat::PVRTC2:
|
||||
case Texture2D::PixelFormat::PVRTC2A:
|
||||
if(Configuration::getInstance()->supportsPVRTC())
|
||||
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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -404,6 +452,7 @@ Image::Image()
|
|||
, _dataLen(0)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
, _unpack(false)
|
||||
, _fileType(Format::UNKOWN)
|
||||
, _renderFormat(Texture2D::PixelFormat::NONE)
|
||||
, _preMulti(false)
|
||||
|
@ -415,7 +464,13 @@ Image::Image()
|
|||
|
||||
Image::~Image()
|
||||
{
|
||||
CC_SAFE_FREE(_data);
|
||||
if(_unpack)
|
||||
{
|
||||
for (unsigned int i = 0; i < _numberOfMipmaps; ++i)
|
||||
CC_SAFE_DELETE_ARRAY(_mipmaps[i].address);
|
||||
}
|
||||
else
|
||||
CC_SAFE_FREE(_data);
|
||||
}
|
||||
|
||||
bool Image::initWithImageFile(const std::string& path)
|
||||
|
@ -1181,32 +1236,38 @@ 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::PVRTC2BPP_RGB ||
|
||||
format == PVR3TexturePixelFormat::PVRTC2BPP_RGBA ||
|
||||
format == PVR3TexturePixelFormat::PVRTC4BPP_RGB ||
|
||||
format == PVR3TexturePixelFormat::PVRTC4BPP_RGBA)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1317,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())
|
||||
{
|
||||
|
@ -1265,6 +1326,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;
|
||||
|
@ -1285,29 +1347,47 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
|
|||
while (dataOffset < dataLength)
|
||||
{
|
||||
switch (formatFlags) {
|
||||
case PVR2TexturePixelFormat::PVRTC2BPP_RGBA:
|
||||
blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
|
||||
widthBlocks = width / 8;
|
||||
heightBlocks = height / 4;
|
||||
break;
|
||||
case PVR2TexturePixelFormat::PVRTC4BPP_RGBA:
|
||||
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)
|
||||
{
|
||||
|
@ -1317,22 +1397,31 @@ 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;
|
||||
|
||||
|
||||
//Make record to the mipmaps array and increment counter
|
||||
_mipmaps[_numberOfMipmaps].address = _data + dataOffset;
|
||||
_mipmaps[_numberOfMipmaps].len = packetLength;
|
||||
if(!_unpack)
|
||||
{
|
||||
_mipmaps[_numberOfMipmaps].address = _data + dataOffset;
|
||||
_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);
|
||||
}
|
||||
|
||||
if(_unpack)
|
||||
{
|
||||
_data = _mipmaps[0].address;
|
||||
_dataLen = _mipmaps[0].len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1371,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())
|
||||
{
|
||||
|
@ -1381,6 +1470,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);
|
||||
|
@ -1410,29 +1500,65 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
|
|||
{
|
||||
switch ((PVR3TexturePixelFormat)pixelFormat)
|
||||
{
|
||||
case PVR3TexturePixelFormat::PVRTC2BPP_RGB :
|
||||
case PVR3TexturePixelFormat::PVRTC2BPP_RGBA :
|
||||
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 :
|
||||
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<const unsigned char*>(_data+dataOffset), static_cast<etc1_byte*>(_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
|
||||
|
@ -1445,12 +1571,15 @@ 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;
|
||||
|
||||
_mipmaps[i].address = _data + dataOffset;
|
||||
_mipmaps[i].len = static_cast<int>(packetLength);
|
||||
if(!_unpack)
|
||||
{
|
||||
_mipmaps[i].address = _data + dataOffset;
|
||||
_mipmaps[i].len = static_cast<int>(packetLength);
|
||||
}
|
||||
|
||||
dataOffset += packetLength;
|
||||
CCAssert(dataOffset <= _dataLen, "CCTexurePVR: Invalid lenght");
|
||||
|
@ -1459,6 +1588,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;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef struct _MipmapInfo
|
|||
{
|
||||
unsigned char* address;
|
||||
int len;
|
||||
_MipmapInfo():address(NULL),len(0){}
|
||||
}MipmapInfo;
|
||||
|
||||
class CC_DLL Image : public Ref
|
||||
|
@ -167,6 +168,7 @@ protected:
|
|||
ssize_t _dataLen;
|
||||
int _width;
|
||||
int _height;
|
||||
bool _unpack;
|
||||
Format _fileType;
|
||||
Texture2D::PixelFormat _renderFormat;
|
||||
bool _preMulti;
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue