diff --git a/KREngine/Kraken.xcodeproj/project.pbxproj b/KREngine/Kraken.xcodeproj/project.pbxproj index f7686fe..18e49e4 100644 --- a/KREngine/Kraken.xcodeproj/project.pbxproj +++ b/KREngine/Kraken.xcodeproj/project.pbxproj @@ -12,6 +12,10 @@ 10CC33A5168534F000BB9846 /* KRCamera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E48B3CBF14393E2F000C50E2 /* KRCamera.cpp */; }; E4030E4C160A3CF000592648 /* KRStockGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = E4030E4B160A3CF000592648 /* KRStockGeometry.h */; settings = {ATTRIBUTES = (); }; }; E4030E4D160A3CF000592648 /* KRStockGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = E4030E4B160A3CF000592648 /* KRStockGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E404702018695DD200F01F42 /* KRTextureKTX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E404701E18695DD200F01F42 /* KRTextureKTX.cpp */; }; + E404702118695DD200F01F42 /* KRTextureKTX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E404701E18695DD200F01F42 /* KRTextureKTX.cpp */; }; + E404702218695DD200F01F42 /* KRTextureKTX.h in Headers */ = {isa = PBXBuildFile; fileRef = E404701F18695DD200F01F42 /* KRTextureKTX.h */; }; + E404702318695DD200F01F42 /* KRTextureKTX.h in Headers */ = {isa = PBXBuildFile; fileRef = E404701F18695DD200F01F42 /* KRTextureKTX.h */; }; E40BA45415EFF79500D7C3DD /* KRAABB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40BA45215EFF79500D7C3DD /* KRAABB.cpp */; }; E40BA45515EFF79500D7C3DD /* KRAABB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40BA45215EFF79500D7C3DD /* KRAABB.cpp */; }; E40BA45615EFF79500D7C3DD /* KRAABB.h in Headers */ = {isa = PBXBuildFile; fileRef = E40BA45315EFF79500D7C3DD /* KRAABB.h */; settings = {ATTRIBUTES = (); }; }; @@ -409,6 +413,8 @@ 104A335D1672D31C001C8BA6 /* KRCollider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KRCollider.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 10CC33A3168530A300BB9846 /* libPVRTexLib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPVRTexLib.a; path = Utilities/PVRTexLib/MacOS/libPVRTexLib.a; sourceTree = PVRSDK; }; E4030E4B160A3CF000592648 /* KRStockGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRStockGeometry.h; sourceTree = ""; }; + E404701E18695DD200F01F42 /* KRTextureKTX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRTextureKTX.cpp; sourceTree = ""; }; + E404701F18695DD200F01F42 /* KRTextureKTX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRTextureKTX.h; sourceTree = ""; }; E40BA45215EFF79500D7C3DD /* KRAABB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRAABB.cpp; sourceTree = ""; }; E40BA45315EFF79500D7C3DD /* KRAABB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRAABB.h; sourceTree = ""; }; E40F982A184A7A2700CFA4D8 /* KRMeshQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRMeshQuad.cpp; sourceTree = ""; }; @@ -922,6 +928,8 @@ E460292716681D1000261BB9 /* KRTextureAnimated.cpp */, E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */, E43F70E41824D9AB00136169 /* KRTextureStreamer.h */, + E404701E18695DD200F01F42 /* KRTextureKTX.cpp */, + E404701F18695DD200F01F42 /* KRTextureKTX.h */, ); name = Texture; sourceTree = ""; @@ -1301,6 +1309,7 @@ E499BF1E16AE751E007FCDBE /* KRSceneManager.h in Headers */, E499BF2016AE755B007FCDBE /* KRPointLight.h in Headers */, E499BF2116AE75A7007FCDBE /* KREngine-common.h in Headers */, + E404702218695DD200F01F42 /* KRTextureKTX.h in Headers */, E4F027D016979CE200D4427D /* KRAudioSample.h in Headers */, E450273B16E0491D00FDEC5C /* KRReverbZone.h in Headers */, E4FE6AA816B21D660058B8CE /* forsyth.h in Headers */, @@ -1369,6 +1378,7 @@ E4324BA516444C0D0043185B /* KRParticleSystem.h in Headers */, E4324BAC16444DEF0043185B /* KRParticleSystemNewtonian.h in Headers */, E4C454AD167BB8EC003586CD /* KRMeshCube.h in Headers */, + E404702318695DD200F01F42 /* KRTextureKTX.h in Headers */, E414F9A91694D977000B3D58 /* KRUnknownManager.h in Headers */, E48B68181697794F00D99917 /* KRAudioSource.h in Headers */, E4F027CA16979CCD00D4427D /* KRAudioManager.h in Headers */, @@ -1626,6 +1636,7 @@ E43B0AD615DDCA0F00A5CB9F /* KRContextObject.cpp in Sources */, E4924C2615EE95E800B965C6 /* KROctree.cpp in Sources */, E4924C2B15EE96AB00B965C6 /* KROctreeNode.cpp in Sources */, + E404702018695DD200F01F42 /* KRTextureKTX.cpp in Sources */, E40BA45415EFF79500D7C3DD /* KRAABB.cpp in Sources */, E488399415F928CA00BD66D5 /* KRBundle.cpp in Sources */, E488399C15F92BE000BD66D5 /* KRBundleManager.cpp in Sources */, @@ -1742,6 +1753,7 @@ E4F027CF16979CE200D4427D /* KRAudioSample.cpp in Sources */, E4F027DF1697BFFF00D4427D /* KRAudioBuffer.cpp in Sources */, E4943232169E08D200BCB891 /* KRAmbientZone.cpp in Sources */, + E404702118695DD200F01F42 /* KRTextureKTX.cpp in Sources */, E450273A16E0491D00FDEC5C /* KRReverbZone.cpp in Sources */, E4AE635E1704FB0A00B460CD /* KRLODGroup.cpp in Sources */, E4EC73C21720B1FF0065299F /* KRVector4.cpp in Sources */, diff --git a/KREngine/kraken/KRContext.cpp b/KREngine/kraken/KRContext.cpp index aa44b5c..60a4dff 100644 --- a/KREngine/kraken/KRContext.cpp +++ b/KREngine/kraken/KRContext.cpp @@ -219,6 +219,8 @@ void KRContext::loadResource(const std::string &file_name, KRDataBlock *data) { m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data); } else if(extension.compare("pvr") == 0) { m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); + } else if(extension.compare("ktx") == 0) { + m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); } else if(extension.compare("tga") == 0) { m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); } else if(extension.compare("vsh") == 0) { diff --git a/KREngine/kraken/KRMeshStreamer.mm b/KREngine/kraken/KRMeshStreamer.mm index 1fd6560..704a646 100644 --- a/KREngine/kraken/KRMeshStreamer.mm +++ b/KREngine/kraken/KRMeshStreamer.mm @@ -42,11 +42,11 @@ void KRMeshStreamer::startStreamer() #elif TARGET_OS_MAC NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, 0 }; NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes] autorelease]; - gMeshStreamerContext = [[[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ] autorelease]; + gMeshStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ]; #else #error Unsupported Platform #endif diff --git a/KREngine/kraken/KRTexture.h b/KREngine/kraken/KRTexture.h index 592ac14..defc431 100644 --- a/KREngine/kraken/KRTexture.h +++ b/KREngine/kraken/KRTexture.h @@ -59,7 +59,7 @@ public: virtual void resetPoolExpiry(); virtual bool isAnimated(); - KRTexture *compress(); + virtual KRTexture *compress(); int getCurrentLodMaxDim(); int getMaxMipMap(); int getMinMipMap(); diff --git a/KREngine/kraken/KRTexture2D.h b/KREngine/kraken/KRTexture2D.h index 139e5d5..f7f4303 100644 --- a/KREngine/kraken/KRTexture2D.h +++ b/KREngine/kraken/KRTexture2D.h @@ -46,7 +46,7 @@ public: virtual bool save(const std::string& path); virtual bool save(KRDataBlock &data); - virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim) = 0; + virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false) = 0; virtual void bind(GLuint texture_unit); protected: diff --git a/KREngine/kraken/KRTextureKTX.cpp b/KREngine/kraken/KRTextureKTX.cpp new file mode 100644 index 0000000..2270bfd --- /dev/null +++ b/KREngine/kraken/KRTextureKTX.cpp @@ -0,0 +1,277 @@ +// +// KRTextureKTX.cpp +// KREngine +// +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#include "KRTextureKTX.h" +#include "KRTextureManager.h" + +#include "KREngine-common.h" + +Byte _KTXFileIdentifier[12] = { + 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A +}; + +KRTextureKTX::KRTextureKTX(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) { + m_pData->copy(&m_header, 0, sizeof(KTXHeader)); + if(memcmp(_KTXFileIdentifier, m_header.identifier, 12) != 0) { + assert(false); // Header not recognized + } + if(m_header.endianness != 0x04030201) { + assert(false); // Endianness not (yet) supported + } + if(m_header.pixelDepth != 0) { + assert(false); // 3d textures not (yet) supported + } + if(m_header.numberOfArrayElements != 0) { + assert(false); // Array textures not (yet) supported + } + if(m_header.numberOfFaces != 1) { + assert(false); // Cube-map textures are only supported as a file for each separate face (for now) + } + + uint32_t blockStart = sizeof(KTXHeader) + m_header.bytesOfKeyValueData; + uint32_t width = m_header.pixelWidth, height = m_header.pixelHeight; + + for(int mipmap_level=0; mipmap_level < KRMIN(m_header.numberOfMipmapLevels, 1); mipmap_level++) { + uint32_t blockLength; + data->copy(&blockLength, blockStart, 4); + + m_blocks.push_back(m_pData->getSubBlock(blockStart, blockLength)); + + blockStart += blockLength; + blockStart = KRALIGN(blockStart); + + width = width >> 1; + if(width < 1) { + width = 1; + } + height = height >> 1; + if(height < 1) { + height = 1; + } + } + + m_max_lod_max_dim = KRMAX(m_header.pixelWidth, m_header.pixelHeight); + m_min_lod_max_dim = KRMAX(width, height); +} + +KRTextureKTX::KRTextureKTX(KRContext &context, std::string name, GLenum internal_format, GLenum base_internal_format, int width, int height, const std::list &blocks) : KRTexture2D(context, new KRDataBlock(), name) +{ + memcpy(_KTXFileIdentifier, m_header.identifier, 12); + m_header.endianness = 0x04030201; + m_header.glType = 0; + m_header.glTypeSize = 1; + m_header.glFormat = 0; + m_header.glInternalFormat = internal_format; + m_header.glBaseInternalFormat = base_internal_format; + m_header.pixelWidth = width; + m_header.pixelHeight = height; + m_header.pixelDepth = 0; + m_header.numberOfArrayElements = 0; + m_header.numberOfFaces = 1; + m_header.numberOfMipmapLevels = (UInt32)blocks.size(); + m_header.bytesOfKeyValueData = 0; + + m_pData->append(&m_header, sizeof(m_header)); + for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) { + KRDataBlock *source_block = *block_itr; + UInt32 block_size = (UInt32)source_block->getSize(); + m_pData->append(&block_size, 4); + m_pData->append(*source_block); + m_blocks.push_back(m_pData->getSubBlock((int)m_pData->getSize() - (int)block_size, (int)block_size)); + size_t alignment_padding_size = KRALIGN(m_pData->getSize()) - m_pData->getSize(); + Byte alignment_padding[4] = {0, 0, 0, 0}; + if(alignment_padding_size > 0) { + m_pData->append(&alignment_padding, alignment_padding_size); + } + } +} + +KRTextureKTX::~KRTextureKTX() { + for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + KRDataBlock *block = *itr; + delete block; + } + m_blocks.clear(); +} + +long KRTextureKTX::getMemRequiredForSize(int max_dim) +{ + int target_dim = max_dim; + if(target_dim < m_min_lod_max_dim) target_dim = target_dim; + + // Determine how much memory will be consumed + + int width = m_header.pixelWidth; + int height = m_header.pixelHeight; + long memoryRequired = 0; + + for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + KRDataBlock *block = *itr; + if(width <= target_dim && height <= target_dim) { + memoryRequired += block->getSize(); + } + + width = width >> 1; + if(width < 1) { + width = 1; + } + height = height >> 1; + if(height < 1) { + height = 1; + } + } + + return memoryRequired; +} + +bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress) +{ + int target_dim = lod_max_dim; + if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + + if(m_blocks.size() == 0) { + return false; + } + + // Determine how much memory will be consumed + int width = m_header.pixelWidth; + int height = m_header.pixelHeight; + long memoryRequired = 0; + long memoryTransferred = 0; + + +#if GL_EXT_texture_storage + + if(target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || target == GL_TEXTURE_2D) { + // Call glTexStorage2DEXT only for the first uploadTexture used when creating a texture + int level_count=0; + int max_lod_width=0; + int max_lod_height=0; + for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + if(width <= target_dim && height <= target_dim) { + if(max_lod_width == 0) { + max_lod_width = width; + max_lod_height = height; + } + + level_count++; + } + + width = width >> 1; + if(width < 1) { + width = 1; + } + height = height >> 1; + if(height < 1) { + height = 1; + } + } + width = m_iWidth; + height = m_iHeight; + + if(target == GL_TEXTURE_CUBE_MAP_POSITIVE_X) { + glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, level_count, (GLenum)m_header.glInternalFormat, max_lod_width, max_lod_height); + } else if(target == GL_TEXTURE_2D) { + glTexStorage2DEXT(target, level_count, (GLenum)m_header.glInternalFormat, max_lod_width, max_lod_height); + } + } +#endif + + // Upload texture data + int destination_level=0; + int source_level = 0; + for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + KRDataBlock *block = *itr; + if(width <= target_dim && height <= target_dim) { + + if(width > current_lod_max_dim) { + current_lod_max_dim = width; + } + if(height > current_lod_max_dim) { + current_lod_max_dim = height; + } +#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage + if(target == GL_TEXTURE_2D && width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + //GLDEBUG(glCompressedTexImage2D(target, i, (GLenum)m_header.glInternalFormat, width, height, 0, block.length, NULL)); // Allocate, but don't copy + // GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); + GLDEBUG(glCopyTextureLevelsAPPLE(m_iNewHandle, m_iHandle, source_level, 1)); + } else { + block->lock(); + GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, (GLenum)m_header.glInternalFormat, (GLsizei)block->getSize(), block->getStart())); + block->unlock(); + + memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE + } +#else + block->lock(); +#if GL_EXT_texture_storage + GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, (GLenum)m_header.glInternalFormat, (GLsizei)block->getSize(), block->getStart())); +#else + GLDEBUG(glCompressedTexImage2D(target, destination_level, (GLenum)m_header.glInternalFormat, width, height, 0, (GLsizei)block->getSize(), block->getStart())); +#endif + block->unlock(); + memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE +#endif + memoryRequired += block->getSize(); + // + // err = glGetError(); + // if (err != GL_NO_ERROR) { + // assert(false); + // return false; + // } + // + + destination_level++; + } + + if(width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + source_level++; + } + + width = width >> 1; + if(width < 1) { + width = 1; + } + height = height >> 1; + if(height < 1) { + height = 1; + } + } + + return true; + +} + +std::string KRTextureKTX::getExtension() +{ + return "ktx"; +} + diff --git a/KREngine/kraken/KRTextureKTX.h b/KREngine/kraken/KRTextureKTX.h new file mode 100644 index 0000000..13308b8 --- /dev/null +++ b/KREngine/kraken/KRTextureKTX.h @@ -0,0 +1,51 @@ +// +// KRTextureKTX.h +// KREngine +// +// Created by Kearwood Gilbert on 2012-10-23. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#ifndef KRTEXTUREKTX_H +#define KRTEXTUREKTX_H + +#include "KRTexture2D.h" + +class KRTextureKTX : public KRTexture2D +{ +public: + KRTextureKTX(KRContext &context, KRDataBlock *data, std::string name); + KRTextureKTX(KRContext &context, std::string name, GLenum internal_format, GLenum base_internal_format, int width, int height, const std::list &blocks); + virtual ~KRTextureKTX(); + virtual std::string getExtension(); + + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false); + + virtual long getMemRequiredForSize(int max_dim); + +protected: + + std::list m_blocks; + + typedef struct _KTXHeader + { + Byte identifier[12]; + UInt32 endianness; + UInt32 glType; + UInt32 glTypeSize; + UInt32 glFormat; + UInt32 glInternalFormat; + UInt32 glBaseInternalFormat; + UInt32 pixelWidth; + UInt32 pixelHeight; + UInt32 pixelDepth; + UInt32 numberOfArrayElements; + UInt32 numberOfFaces; + UInt32 numberOfMipmapLevels; + UInt32 bytesOfKeyValueData; + } KTXHeader; + + KTXHeader m_header; +}; + +#endif diff --git a/KREngine/kraken/KRTextureManager.cpp b/KREngine/kraken/KRTextureManager.cpp index 74b718f..2f554c8 100644 --- a/KREngine/kraken/KRTextureManager.cpp +++ b/KREngine/kraken/KRTextureManager.cpp @@ -35,6 +35,7 @@ #include "KRTexture2D.h" #include "KRTexturePVR.h" #include "KRTextureTGA.h" +#include "KRTextureKTX.h" #include "KRTextureCube.h" #include "KRTextureAnimated.h" #include "KRContext.h" @@ -127,6 +128,8 @@ KRTexture *KRTextureManager::loadTexture(const char *szName, const char *szExten pTexture = new KRTexturePVR(getContext(), data, szName); } else if(strcmp(szExtension, "tga") == 0) { pTexture = new KRTextureTGA(getContext(), data, szName); + } else if(strcmp(szExtension, "ktx") == 0) { + pTexture = new KRTextureKTX(getContext(), data, szName); } if(pTexture) { diff --git a/KREngine/kraken/KRTexturePVR.cpp b/KREngine/kraken/KRTexturePVR.cpp index 6ce9a65..419ccbe 100644 --- a/KREngine/kraken/KRTexturePVR.cpp +++ b/KREngine/kraken/KRTexturePVR.cpp @@ -173,7 +173,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim) return memoryRequired; } -bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim) +bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress) { int target_dim = lod_max_dim; if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; diff --git a/KREngine/kraken/KRTexturePVR.h b/KREngine/kraken/KRTexturePVR.h index 974619e..ea15878 100644 --- a/KREngine/kraken/KRTexturePVR.h +++ b/KREngine/kraken/KRTexturePVR.h @@ -18,7 +18,7 @@ public: virtual ~KRTexturePVR(); virtual std::string getExtension(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false); virtual long getMemRequiredForSize(int max_dim); diff --git a/KREngine/kraken/KRTextureStreamer.mm b/KREngine/kraken/KRTextureStreamer.mm index 5185c22..8731730 100644 --- a/KREngine/kraken/KRTextureStreamer.mm +++ b/KREngine/kraken/KRTextureStreamer.mm @@ -47,11 +47,11 @@ void KRTextureStreamer::startStreamer() NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, 0 }; NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes] autorelease]; - gTextureStreamerContext = [[[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ] autorelease]; + gTextureStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ]; #else diff --git a/KREngine/kraken/KRTextureTGA.cpp b/KREngine/kraken/KRTextureTGA.cpp index 373385b..a94bc58 100644 --- a/KREngine/kraken/KRTextureTGA.cpp +++ b/KREngine/kraken/KRTextureTGA.cpp @@ -9,6 +9,7 @@ #include "KRTextureTGA.h" #include "KREngine-common.h" #include "KRContext.h" +#include "KRTextureKTX.h" typedef struct { char idlength; @@ -69,11 +70,20 @@ KRTextureTGA::~KRTextureTGA() } -bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim) +bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress) { m_pData->lock(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER); + + + GLenum base_internal_format = pHeader->bitsperpixel == 24 ? GL_BGR : GL_BGRA; + + GLenum internal_format = 0; + if(compress) { + internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } + if(pHeader->colourmaptype != 0) { m_pData->unlock(); @@ -104,7 +114,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo pSource += 3; } //#endif - glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image); + glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGR, GL_UNSIGNED_BYTE, (GLvoid *)converted_image); free(converted_image); err = glGetError(); if (err != GL_NO_ERROR) { @@ -116,7 +126,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo break; case 32: { - glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData); + glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData); err = glGetError(); if (err != GL_NO_ERROR) { m_pData->unlock(); @@ -139,6 +149,72 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo return true; } +KRTexture *KRTextureTGA::compress() +{ + m_pData->lock(); + + std::list blocks; + + getContext().getTextureManager()->_setActiveTexture(0); + + GLuint compressed_handle = 0; + GLDEBUG(glGenTextures(1, &compressed_handle)); + + GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle)); + + int current_max_dim = 0; + if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, 0, true)) { + assert(false); // Failed to upload the texture + } + GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D)); + + GLint width = 0, height = 0, internal_format, base_internal_format = GL_BGRA; + GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width)); + GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height)); + GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format)); + + + GLuint lod_level = 0; + GLint compressed_size = 0; + GLenum err = GL_NO_ERROR; + while(err == GL_NO_ERROR) { + glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size); + err = glGetError(); + if(err == GL_NO_ERROR) { + KRDataBlock *new_block = new KRDataBlock(); + new_block->expand(compressed_size); + new_block->lock(); + GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart())); + new_block->unlock(); + blocks.push_back(new_block); + + lod_level++; + } + } + if(err != GL_INVALID_VALUE) { + // err will equal GL_INVALID_VALUE when + // assert(false); // Unexpected error + } + + + GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); + getContext().getTextureManager()->selectTexture(0, NULL); + GLDEBUG(glDeleteTextures(1, &compressed_handle)); + + KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks); + + KRResource *test_resource = new_texture; + + m_pData->unlock(); + + for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) { + KRDataBlock *block = *block_itr; + delete block; + } + + return new_texture; +} + long KRTextureTGA::getMemRequiredForSize(int max_dim) { return m_imageSize; diff --git a/KREngine/kraken/KRTextureTGA.h b/KREngine/kraken/KRTextureTGA.h index 82826d7..34edb9d 100644 --- a/KREngine/kraken/KRTextureTGA.h +++ b/KREngine/kraken/KRTextureTGA.h @@ -18,7 +18,8 @@ public: virtual ~KRTextureTGA(); virtual std::string getExtension(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false); + virtual KRTexture *compress(); virtual long getMemRequiredForSize(int max_dim); private: