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 */; };
|
B24AA98B195A675C007B4522 /* CCFastTMXTiledMap.h in Headers */ = {isa = PBXBuildFile; fileRef = B24AA984195A675C007B4522 /* CCFastTMXTiledMap.h */; };
|
||||||
B24AA98C195A675C007B4522 /* 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 */; };
|
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 */; };
|
B29594B41926D5EC003EEF37 /* CCMeshCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B29594B21926D5EC003EEF37 /* CCMeshCommand.cpp */; };
|
||||||
B29594B51926D5EC003EEF37 /* 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 */; };
|
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; };
|
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; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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 */,
|
50ABBE141925AB6F00A911A9 /* etc1.cpp */,
|
||||||
50ABBE151925AB6F00A911A9 /* etc1.h */,
|
50ABBE151925AB6F00A911A9 /* etc1.h */,
|
||||||
50ABBE161925AB6F00A911A9 /* firePngData.h */,
|
50ABBE161925AB6F00A911A9 /* firePngData.h */,
|
||||||
|
A5BC6BA619430ABA00AD87B3 /* pvr.cpp */,
|
||||||
|
A5BC6BA719430ABA00AD87B3 /* pvr.h */,
|
||||||
50ABBE171925AB6F00A911A9 /* s3tc.cpp */,
|
50ABBE171925AB6F00A911A9 /* s3tc.cpp */,
|
||||||
50ABBE181925AB6F00A911A9 /* s3tc.h */,
|
50ABBE181925AB6F00A911A9 /* s3tc.h */,
|
||||||
50ABBE191925AB6F00A911A9 /* TGAlib.cpp */,
|
50ABBE191925AB6F00A911A9 /* TGAlib.cpp */,
|
||||||
|
@ -5159,6 +5167,7 @@
|
||||||
1A57011D180BC90D0088DEC7 /* CCGrabber.h in Headers */,
|
1A57011D180BC90D0088DEC7 /* CCGrabber.h in Headers */,
|
||||||
1A570121180BC90D0088DEC7 /* CCGrid.h in Headers */,
|
1A570121180BC90D0088DEC7 /* CCGrid.h in Headers */,
|
||||||
5034CA2D191D591100CE6051 /* ccShader_PositionTextureA8Color.frag in Headers */,
|
5034CA2D191D591100CE6051 /* ccShader_PositionTextureA8Color.frag in Headers */,
|
||||||
|
A5BC6BAA19430ABA00AD87B3 /* pvr.h in Headers */,,
|
||||||
1AC0269C1914068200FA920D /* ConvertUTF.h in Headers */,
|
1AC0269C1914068200FA920D /* ConvertUTF.h in Headers */,
|
||||||
50ABBED11925AB6F00A911A9 /* TGAlib.h in Headers */,
|
50ABBED11925AB6F00A911A9 /* TGAlib.h in Headers */,
|
||||||
1A57019F180BCB590088DEC7 /* CCFont.h in Headers */,
|
1A57019F180BCB590088DEC7 /* CCFont.h in Headers */,
|
||||||
|
@ -5613,6 +5622,7 @@
|
||||||
1A57034E180BD09B0088DEC7 /* tinyxml2.h in Headers */,
|
1A57034E180BD09B0088DEC7 /* tinyxml2.h in Headers */,
|
||||||
1A570357180BD0B00088DEC7 /* ioapi.h in Headers */,
|
1A570357180BD0B00088DEC7 /* ioapi.h in Headers */,
|
||||||
50ABBD4B1925AB0000A911A9 /* Mat4.h in Headers */,
|
50ABBD4B1925AB0000A911A9 /* Mat4.h in Headers */,
|
||||||
|
A5BC6BAB19430ABA00AD87B3 /* pvr.h in Headers */,
|
||||||
1A01C69B18F57BE800EFE3A6 /* CCSet.h in Headers */,
|
1A01C69B18F57BE800EFE3A6 /* CCSet.h in Headers */,
|
||||||
50ABBED61925AB6F00A911A9 /* utlist.h in Headers */,
|
50ABBED61925AB6F00A911A9 /* utlist.h in Headers */,
|
||||||
1A57035B180BD0B00088DEC7 /* unzip.h in Headers */,
|
1A57035B180BD0B00088DEC7 /* unzip.h in Headers */,
|
||||||
|
@ -6656,6 +6666,7 @@
|
||||||
1A12775C18DFCC590005F345 /* CCTweenFunction.cpp in Sources */,
|
1A12775C18DFCC590005F345 /* CCTweenFunction.cpp in Sources */,
|
||||||
1A5701E6180BCB8C0088DEC7 /* CCTransition.cpp in Sources */,
|
1A5701E6180BCB8C0088DEC7 /* CCTransition.cpp in Sources */,
|
||||||
B24AA985195A675C007B4522 /* CCFastTMXLayer.cpp in Sources */,
|
B24AA985195A675C007B4522 /* CCFastTMXLayer.cpp in Sources */,
|
||||||
|
A5BC6BA819430ABA00AD87B3 /* pvr.cpp in Sources */,
|
||||||
1A5701EA180BCB8C0088DEC7 /* CCTransitionPageTurn.cpp in Sources */,
|
1A5701EA180BCB8C0088DEC7 /* CCTransitionPageTurn.cpp in Sources */,
|
||||||
50ABBDAD1925AB4100A911A9 /* CCRenderer.cpp in Sources */,
|
50ABBDAD1925AB4100A911A9 /* CCRenderer.cpp in Sources */,
|
||||||
1A5701EE180BCB8C0088DEC7 /* CCTransitionProgress.cpp in Sources */,
|
1A5701EE180BCB8C0088DEC7 /* CCTransitionProgress.cpp in Sources */,
|
||||||
|
@ -6987,6 +6998,7 @@
|
||||||
1A5701E3180BCB8C0088DEC7 /* CCScene.cpp in Sources */,
|
1A5701E3180BCB8C0088DEC7 /* CCScene.cpp in Sources */,
|
||||||
50ABBD611925AB0000A911A9 /* Vec4.cpp in Sources */,
|
50ABBD611925AB0000A911A9 /* Vec4.cpp in Sources */,
|
||||||
50ABBD9C1925AB4100A911A9 /* ccGLStateCache.cpp in Sources */,
|
50ABBD9C1925AB4100A911A9 /* ccGLStateCache.cpp in Sources */,
|
||||||
|
A5BC6BA919430ABA00AD87B3 /* pvr.cpp in Sources */,
|
||||||
1A5701E7180BCB8C0088DEC7 /* CCTransition.cpp in Sources */,
|
1A5701E7180BCB8C0088DEC7 /* CCTransition.cpp in Sources */,
|
||||||
50ABC01E1926664800A911A9 /* CCThread.cpp in Sources */,
|
50ABC01E1926664800A911A9 /* CCThread.cpp in Sources */,
|
||||||
1A5701EB180BCB8C0088DEC7 /* CCTransitionPageTurn.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\ccUtils.cpp" />
|
||||||
<ClCompile Include="..\base\CCValue.cpp" />
|
<ClCompile Include="..\base\CCValue.cpp" />
|
||||||
<ClCompile Include="..\base\etc1.cpp" />
|
<ClCompile Include="..\base\etc1.cpp" />
|
||||||
|
<ClCompile Include="..\base\pvr.cpp" />
|
||||||
<ClCompile Include="..\base\ObjectFactory.cpp" />
|
<ClCompile Include="..\base\ObjectFactory.cpp" />
|
||||||
<ClCompile Include="..\base\s3tc.cpp" />
|
<ClCompile Include="..\base\s3tc.cpp" />
|
||||||
<ClCompile Include="..\base\TGAlib.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\etc1.h" />
|
||||||
<ClInclude Include="..\base\firePngData.h" />
|
<ClInclude Include="..\base\firePngData.h" />
|
||||||
<ClInclude Include="..\base\ObjectFactory.h" />
|
<ClInclude Include="..\base\ObjectFactory.h" />
|
||||||
|
<ClInclude Include="..\base\pvr.h" />
|
||||||
<ClInclude Include="..\base\s3tc.h" />
|
<ClInclude Include="..\base\s3tc.h" />
|
||||||
<ClInclude Include="..\base\TGAlib.h" />
|
<ClInclude Include="..\base\TGAlib.h" />
|
||||||
<ClInclude Include="..\base\uthash.h" />
|
<ClInclude Include="..\base\uthash.h" />
|
||||||
|
|
|
@ -418,6 +418,9 @@
|
||||||
<ClCompile Include="..\base\etc1.cpp">
|
<ClCompile Include="..\base\etc1.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\base\pvr.cpp">
|
||||||
|
<Filter>platform</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\base\s3tc.cpp">
|
<ClCompile Include="..\base\s3tc.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -991,6 +994,9 @@
|
||||||
<ClInclude Include="..\base\etc1.h">
|
<ClInclude Include="..\base\etc1.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\base\pvr.h">
|
||||||
|
<Filter>platform</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\base\firePngData.h">
|
<ClInclude Include="..\base\firePngData.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -140,6 +140,7 @@ base/ccTypes.cpp \
|
||||||
base/ccUTF8.cpp \
|
base/ccUTF8.cpp \
|
||||||
base/ccUtils.cpp \
|
base/ccUtils.cpp \
|
||||||
base/etc1.cpp \
|
base/etc1.cpp \
|
||||||
|
base/pvr.cpp \
|
||||||
base/s3tc.cpp \
|
base/s3tc.cpp \
|
||||||
base/CCController.cpp \
|
base/CCController.cpp \
|
||||||
base/CCController-android.cpp \
|
base/CCController-android.cpp \
|
||||||
|
|
|
@ -40,6 +40,7 @@ set(COCOS_BASE_SRC
|
||||||
base/ccUTF8.cpp
|
base/ccUTF8.cpp
|
||||||
base/ccUtils.cpp
|
base/ccUtils.cpp
|
||||||
base/etc1.cpp
|
base/etc1.cpp
|
||||||
|
base/pvr.cpp
|
||||||
base/s3tc.cpp
|
base/s3tc.cpp
|
||||||
base/ObjectFactory.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/s3tc.h"
|
||||||
#include "base/atitc.h"
|
#include "base/atitc.h"
|
||||||
|
#include "base/pvr.h"
|
||||||
#include "base/TGAlib.h"
|
#include "base/TGAlib.h"
|
||||||
|
|
||||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||||
|
@ -141,6 +142,34 @@ namespace
|
||||||
PVRTC2BPP_RGBA = 1ULL,
|
PVRTC2BPP_RGBA = 1ULL,
|
||||||
PVRTC4BPP_RGB = 2ULL,
|
PVRTC4BPP_RGB = 2ULL,
|
||||||
PVRTC4BPP_RGBA = 3ULL,
|
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,
|
BGRA8888 = 0x0808080861726762ULL,
|
||||||
RGBA8888 = 0x0808080861626772ULL,
|
RGBA8888 = 0x0808080861626772ULL,
|
||||||
|
@ -169,10 +198,8 @@ namespace
|
||||||
_pixel2_formathash::value_type(PVR2TexturePixelFormat::I8, Texture2D::PixelFormat::I8),
|
_pixel2_formathash::value_type(PVR2TexturePixelFormat::I8, Texture2D::PixelFormat::I8),
|
||||||
_pixel2_formathash::value_type(PVR2TexturePixelFormat::AI88, Texture2D::PixelFormat::AI88),
|
_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::PVRTC2BPP_RGBA, Texture2D::PixelFormat::PVRTC2A),
|
||||||
_pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC4BPP_RGBA, Texture2D::PixelFormat::PVRTC4A),
|
_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]);
|
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::L8, Texture2D::PixelFormat::I8),
|
||||||
_pixel3_formathash::value_type(PVR3TexturePixelFormat::LA88, Texture2D::PixelFormat::AI88),
|
_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_RGB, Texture2D::PixelFormat::PVRTC2),
|
||||||
_pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGBA, Texture2D::PixelFormat::PVRTC2A),
|
_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_RGB, Texture2D::PixelFormat::PVRTC4),
|
||||||
_pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGBA, Texture2D::PixelFormat::PVRTC4A),
|
_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]);
|
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
|
// Implement Image
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -404,6 +452,7 @@ Image::Image()
|
||||||
, _dataLen(0)
|
, _dataLen(0)
|
||||||
, _width(0)
|
, _width(0)
|
||||||
, _height(0)
|
, _height(0)
|
||||||
|
, _unpack(false)
|
||||||
, _fileType(Format::UNKOWN)
|
, _fileType(Format::UNKOWN)
|
||||||
, _renderFormat(Texture2D::PixelFormat::NONE)
|
, _renderFormat(Texture2D::PixelFormat::NONE)
|
||||||
, _preMulti(false)
|
, _preMulti(false)
|
||||||
|
@ -415,7 +464,13 @@ Image::Image()
|
||||||
|
|
||||||
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)
|
bool Image::initWithImageFile(const std::string& path)
|
||||||
|
@ -1181,32 +1236,38 @@ namespace
|
||||||
{
|
{
|
||||||
bool testFormatForPvr2TCSupport(PVR2TexturePixelFormat format)
|
bool testFormatForPvr2TCSupport(PVR2TexturePixelFormat format)
|
||||||
{
|
{
|
||||||
if (!Configuration::getInstance()->supportsPVRTC())
|
|
||||||
{
|
|
||||||
if (format == PVR2TexturePixelFormat::PVRTC2BPP_RGBA ||
|
|
||||||
format == PVR2TexturePixelFormat::PVRTC4BPP_RGBA)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool testFormatForPvr3TCSupport(PVR3TexturePixelFormat format)
|
bool testFormatForPvr3TCSupport(PVR3TexturePixelFormat format)
|
||||||
{
|
{
|
||||||
if (!Configuration::getInstance()->supportsPVRTC())
|
switch (format) {
|
||||||
{
|
case PVR3TexturePixelFormat::DXT1:
|
||||||
if (format == PVR3TexturePixelFormat::PVRTC2BPP_RGB ||
|
case PVR3TexturePixelFormat::DXT3:
|
||||||
format == PVR3TexturePixelFormat::PVRTC2BPP_RGBA ||
|
case PVR3TexturePixelFormat::DXT5:
|
||||||
format == PVR3TexturePixelFormat::PVRTC4BPP_RGB ||
|
return Configuration::getInstance()->supportsS3TC();
|
||||||
format == PVR3TexturePixelFormat::PVRTC4BPP_RGBA)
|
|
||||||
{
|
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 false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,7 +1317,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
|
||||||
return false;
|
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())
|
if (it == Texture2D::getPixelFormatInfoMap().end())
|
||||||
{
|
{
|
||||||
|
@ -1265,6 +1326,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFormat = it->first;
|
_renderFormat = it->first;
|
||||||
|
int bpp = it->second.bpp;
|
||||||
|
|
||||||
//Reset num of mipmaps
|
//Reset num of mipmaps
|
||||||
_numberOfMipmaps = 0;
|
_numberOfMipmaps = 0;
|
||||||
|
@ -1285,29 +1347,47 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
|
||||||
while (dataOffset < dataLength)
|
while (dataOffset < dataLength)
|
||||||
{
|
{
|
||||||
switch (formatFlags) {
|
switch (formatFlags) {
|
||||||
case PVR2TexturePixelFormat::PVRTC2BPP_RGBA:
|
case PVR2TexturePixelFormat::PVRTC2BPP_RGBA:
|
||||||
blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
|
if(!Configuration::getInstance()->supportsPVRTC())
|
||||||
widthBlocks = width / 8;
|
{
|
||||||
heightBlocks = height / 4;
|
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
|
||||||
break;
|
_unpack = true;
|
||||||
case PVR2TexturePixelFormat::PVRTC4BPP_RGBA:
|
_mipmaps[_numberOfMipmaps].len = width*height*4;
|
||||||
blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
|
_mipmaps[_numberOfMipmaps].address = new unsigned char[width*height*4];
|
||||||
widthBlocks = width / 4;
|
PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[_numberOfMipmaps].address, true);
|
||||||
heightBlocks = height / 4;
|
bpp = 2;
|
||||||
break;
|
}
|
||||||
case PVR2TexturePixelFormat::BGRA8888:
|
blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
|
||||||
if (Configuration::getInstance()->supportsBGRA8888() == false)
|
widthBlocks = width / 8;
|
||||||
{
|
heightBlocks = height / 4;
|
||||||
CCLOG("cocos2d: Image. BGRA8888 not supported on this device");
|
break;
|
||||||
return false;
|
case PVR2TexturePixelFormat::PVRTC4BPP_RGBA:
|
||||||
}
|
if(!Configuration::getInstance()->supportsPVRTC())
|
||||||
default:
|
{
|
||||||
blockSize = 1;
|
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
|
||||||
widthBlocks = width;
|
_unpack = true;
|
||||||
heightBlocks = height;
|
_mipmaps[_numberOfMipmaps].len = width*height*4;
|
||||||
break;
|
_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
|
// Clamp to minimum number of blocks
|
||||||
if (widthBlocks < 2)
|
if (widthBlocks < 2)
|
||||||
{
|
{
|
||||||
|
@ -1317,22 +1397,31 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
|
||||||
{
|
{
|
||||||
heightBlocks = 2;
|
heightBlocks = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
dataSize = widthBlocks * heightBlocks * ((blockSize * it->second.bpp) / 8);
|
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
|
||||||
int packetLength = (dataLength - dataOffset);
|
int packetLength = (dataLength - dataOffset);
|
||||||
packetLength = packetLength > dataSize ? dataSize : packetLength;
|
packetLength = packetLength > dataSize ? dataSize : packetLength;
|
||||||
|
|
||||||
//Make record to the mipmaps array and increment counter
|
//Make record to the mipmaps array and increment counter
|
||||||
_mipmaps[_numberOfMipmaps].address = _data + dataOffset;
|
if(!_unpack)
|
||||||
_mipmaps[_numberOfMipmaps].len = packetLength;
|
{
|
||||||
|
_mipmaps[_numberOfMipmaps].address = _data + dataOffset;
|
||||||
|
_mipmaps[_numberOfMipmaps].len = packetLength;
|
||||||
|
}
|
||||||
_numberOfMipmaps++;
|
_numberOfMipmaps++;
|
||||||
|
|
||||||
dataOffset += packetLength;
|
dataOffset += packetLength;
|
||||||
|
|
||||||
//Update width and height to the next lower power of two
|
//Update width and height to the next lower power of two
|
||||||
width = MAX(width >> 1, 1);
|
width = MAX(width >> 1, 1);
|
||||||
height = MAX(height >> 1, 1);
|
height = MAX(height >> 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(_unpack)
|
||||||
|
{
|
||||||
|
_data = _mipmaps[0].address;
|
||||||
|
_dataLen = _mipmaps[0].len;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1371,7 +1460,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
|
||||||
return false;
|
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())
|
if (it == Texture2D::getPixelFormatInfoMap().end())
|
||||||
{
|
{
|
||||||
|
@ -1381,6 +1470,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFormat = it->first;
|
_renderFormat = it->first;
|
||||||
|
int bpp = it->second.bpp;
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
int flags = CC_SWAP_INT32_LITTLE_TO_HOST(header->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)
|
switch ((PVR3TexturePixelFormat)pixelFormat)
|
||||||
{
|
{
|
||||||
case PVR3TexturePixelFormat::PVRTC2BPP_RGB :
|
case PVR3TexturePixelFormat::PVRTC2BPP_RGB :
|
||||||
case PVR3TexturePixelFormat::PVRTC2BPP_RGBA :
|
case PVR3TexturePixelFormat::PVRTC2BPP_RGBA :
|
||||||
blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
|
if(!Configuration::getInstance()->supportsPVRTC())
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
CCLOG("cocos2d: Image. BGRA8888 not supported on this device");
|
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
|
||||||
return false;
|
_unpack = true;
|
||||||
}
|
_mipmaps[i].len = width*height*4;
|
||||||
default:
|
_mipmaps[i].address = new unsigned char[width*height*4];
|
||||||
blockSize = 1;
|
PVRTDecompressPVRTC(_data+dataOffset,width,height,_mipmaps[i].address, true);
|
||||||
widthBlocks = width;
|
bpp = 2;
|
||||||
heightBlocks = height;
|
}
|
||||||
break;
|
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
|
// Clamp to minimum number of blocks
|
||||||
|
@ -1445,12 +1571,15 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
|
||||||
heightBlocks = 2;
|
heightBlocks = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
dataSize = widthBlocks * heightBlocks * ((blockSize * it->second.bpp) / 8);
|
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
|
||||||
auto packetLength = _dataLen - dataOffset;
|
auto packetLength = _dataLen - dataOffset;
|
||||||
packetLength = packetLength > dataSize ? dataSize : packetLength;
|
packetLength = packetLength > dataSize ? dataSize : packetLength;
|
||||||
|
|
||||||
_mipmaps[i].address = _data + dataOffset;
|
if(!_unpack)
|
||||||
_mipmaps[i].len = static_cast<int>(packetLength);
|
{
|
||||||
|
_mipmaps[i].address = _data + dataOffset;
|
||||||
|
_mipmaps[i].len = static_cast<int>(packetLength);
|
||||||
|
}
|
||||||
|
|
||||||
dataOffset += packetLength;
|
dataOffset += packetLength;
|
||||||
CCAssert(dataOffset <= _dataLen, "CCTexurePVR: Invalid lenght");
|
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);
|
width = MAX(width >> 1, 1);
|
||||||
height = MAX(height >> 1, 1);
|
height = MAX(height >> 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(_unpack)
|
||||||
|
{
|
||||||
|
_data = _mipmaps[0].address;
|
||||||
|
_dataLen = _mipmaps[0].len;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef struct _MipmapInfo
|
||||||
{
|
{
|
||||||
unsigned char* address;
|
unsigned char* address;
|
||||||
int len;
|
int len;
|
||||||
|
_MipmapInfo():address(NULL),len(0){}
|
||||||
}MipmapInfo;
|
}MipmapInfo;
|
||||||
|
|
||||||
class CC_DLL Image : public Ref
|
class CC_DLL Image : public Ref
|
||||||
|
@ -167,6 +168,7 @@ protected:
|
||||||
ssize_t _dataLen;
|
ssize_t _dataLen;
|
||||||
int _width;
|
int _width;
|
||||||
int _height;
|
int _height;
|
||||||
|
bool _unpack;
|
||||||
Format _fileType;
|
Format _fileType;
|
||||||
Texture2D::PixelFormat _renderFormat;
|
Texture2D::PixelFormat _renderFormat;
|
||||||
bool _preMulti;
|
bool _preMulti;
|
||||||
|
|
|
@ -33,12 +33,6 @@ THE SOFTWARE.
|
||||||
|
|
||||||
#define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8
|
#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 // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||||
|
|
||||||
#endif // __CCGL_H__
|
#endif // __CCGL_H__
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GL_ETC1_RGB8_OES
|
#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
|
#endif
|
||||||
|
|
||||||
#ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
#ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
||||||
|
|
|
@ -378,6 +378,8 @@
|
||||||
"cocos/base/etc1.cpp",
|
"cocos/base/etc1.cpp",
|
||||||
"cocos/base/etc1.h",
|
"cocos/base/etc1.h",
|
||||||
"cocos/base/firePngData.h",
|
"cocos/base/firePngData.h",
|
||||||
|
"cocos/base/pvr.cpp",
|
||||||
|
"cocos/base/pvr.h",
|
||||||
"cocos/base/s3tc.cpp",
|
"cocos/base/s3tc.cpp",
|
||||||
"cocos/base/s3tc.h",
|
"cocos/base/s3tc.h",
|
||||||
"cocos/base/uthash.h",
|
"cocos/base/uthash.h",
|
||||||
|
|
Loading…
Reference in New Issue