/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ResTexture.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 16563 $ *---------------------------------------------------------------------------*/ #include "../precompiled.h" #include #include #include #include #include #include #include #include namespace nw { namespace gfx { namespace res { typedef void (*SetupFunc)(ResTexture resTex); static void ResImageTexture_Setup(ResTexture resTex); static void ResCubeTexture_Setup(ResTexture resTex); static void ResReferenceTexture_Setup(ResTexture resTex); static void ResProceduralTexture_Setup(ResTexture resTex); static void ResShadowTexture_Setup(ResTexture resTex); static void ResImageTexture_Cleanup(ResTexture resTex); static void ResCubeTexture_Cleanup(ResTexture resTex); static void ResReferenceTexture_Cleanup(ResTexture resTex); static void ResProceduralTexture_Cleanup(ResTexture resTex); static void ResShadowTexture_Cleanup(ResTexture resTex); static SetupFunc s_TextureSetupTable[] = { ResImageTexture_Setup, ResCubeTexture_Setup, ResReferenceTexture_Setup, ResProceduralTexture_Setup, ResShadowTexture_Setup }; static SetupFunc s_TextureCleanupTable[] = { ResImageTexture_Cleanup, ResCubeTexture_Cleanup, ResReferenceTexture_Cleanup, ResProceduralTexture_Cleanup, ResShadowTexture_Cleanup }; //--------------------------------------------------------------------------- //! @brief 必要であればテクスチャのコピー用のメモリを確保し、転送をおこないます。 //! //! @param[in] texID メモリ確保用のテクスチャIDです。 //! @param[in] resImage イメージリソースです。 //! @param[in] loadFlag テクスチャの配置メモリフラグです。 //--------------------------------------------------------------------------- static void TexImage2D( u32 texID, ResPixelBasedImage resImage, u32 loadFlag ) { u32 size = resImage.GetImageDataCount(); GLenum transtype = loadFlag & 0xFFFF0000; const u32 NN_GX_MEM_MASK = 0x00030000; void* address = NULL; if (size == 0) { size = resImage.GetWidth() * resImage.GetHeight() * resImage.GetBitsPerPixel() / 8; } switch (transtype) { case (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP): nngxUpdateBuffer( resImage.GetImageData(), size ); break; case (NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP): case (NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP): { GLuint area = (transtype & NN_GX_MEM_MASK); address = __dmpgl_allocator(area, NN_GX_MEM_TEXTURE, texID, size); if ( resImage.GetImageData() ) { nngxUpdateBuffer( resImage.GetImageData(), size ); nngxAddVramDmaCommand( resImage.GetImageData(), address, size ); } resImage.SetLocationAddress( address ); resImage.ref().m_MemoryArea = area; } break; case (NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP): { address = __dmpgl_allocator(NN_GX_MEM_FCRAM, NN_GX_MEM_TEXTURE, texID, size); if ( resImage.GetImageData() ) { std::memcpy( address, resImage.GetImageData(), size ); nngxUpdateBuffer( address, size ); } resImage.SetLocationAddress( address ); resImage.ref().m_MemoryArea = NN_GX_MEM_FCRAM; } break; case (NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP): case (NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP): NW_FATAL_ERROR("(GL_COPY_FCRAM_DMP | NN_GX_MEM_VRAM) is not supported!"); break; default: break; } } //--------------------------------------------------------------------------- //! @brief テクスチャ用のコピーメモリを解放します。 //! //! @param[in] texID メモリ確保用のテクスチャIDです。 //! @param[in] resImage リソースのイメージです。 //--------------------------------------------------------------------------- static void DeleteImage2D( u32 texID, ResPixelBasedImage resImage ) { GLuint area = resImage.ref().m_MemoryArea; if (area != ResPixelBasedImageData::AREA_NO_MALLOC) { void* address = reinterpret_cast( resImage.GetLocationAddress() ); __dmpgl_deallocator( area, NN_GX_MEM_TEXTURE, texID, address ); resImage.SetLocationAddress( static_cast(NULL) ); } } //--------------------------------------------------------------------------- //! @brief テクスチャイメージの設定を行ないます。 //! //! @param[in] resImage 設定するイメージリソースです。 //! @param[in] loadFlag テクスチャのメモリ配置指定フラグです。 //--------------------------------------------------------------------------- static inline void SetTexImage2D( u32 texID, ResPixelBasedImage resImage, u32 loadFlag ) { NW_ASSERT( resImage.IsValid() ); // 既にアドレスが設定されている場合はデータのコピーをおこなわない。 if (resImage.GetLocationAddress() != NULL) { resImage.ref().m_MemoryArea = ResPixelBasedImageData::AREA_NO_MALLOC; return; } // テクスチャのメモリへの読み込み指定 // デフォルトは、FCRAM から NO_COPY。 if (loadFlag == 0) { loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; } // FCRAM, NO_COPY の場合は、アライメントチェック。デバイスメモリ 且つ 128バイトアライメント。 NW_ASSERT( (loadFlag != (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP)) || resImage.CheckMemoryLocation() ); TexImage2D( texID, resImage, loadFlag ); } /*!--------------------------------------------------------------------------* @brief イメージテクスチャをセットアップします。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResImageTexture_Setup(ResTexture resTex) { ResImageTexture resImgTex = ResDynamicCast( resTex ); NW_ASSERT( resImgTex.IsValid() ); if ( resImgTex.GetTextureObject() != 0 ) { return; } u32 texID = reinterpret_cast(resTex.ptr()); resImgTex.SetTextureObject( texID ); ResPixelBasedImage resImage = resImgTex.GetImage(); u32 loadFlag = resImgTex.GetLocationFlag(); SetTexImage2D( texID, resImage, loadFlag ); } /*!--------------------------------------------------------------------------* @brief シャドウテクスチャをセットアップします。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResShadowTexture_Setup(ResTexture resTex) { ResShadowTexture resSdwTex = ResDynamicCast( resTex ); NW_ASSERT( resSdwTex.IsValid() ); if ( resSdwTex.GetTextureObject() != 0 ) { return; } u32 texID = reinterpret_cast(resTex.ptr()); resSdwTex.SetTextureObject( texID ); ResPixelBasedImage resImage = resSdwTex.GetImage(); u32 loadFlag = resSdwTex.GetLocationFlag(); SetTexImage2D( texID, resImage, loadFlag ); } /*!--------------------------------------------------------------------------* @brief キューブテクスチャをセットアップします。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResCubeTexture_Setup(ResTexture resTex) { ResCubeTexture resCubeTex = ResDynamicCast( resTex ); NW_ASSERT( resCubeTex.IsValid() ); if ( resCubeTex.GetTextureObject() != 0 ) { return; } u32 texID = reinterpret_cast(resTex.ptr()); resCubeTex.SetTextureObject( texID ); u32 loadFlag = resCubeTex.GetLocationFlag(); // 各フェイスのテクスチャをセットアップする。 // 同じテクスチャが別のフェイスに張られている場合もあるので注意。 for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face ) { ResPixelBasedImage resImage = resCubeTex.GetImage( static_cast( face ) ); SetTexImage2D( texID, resImage, loadFlag ); } } /*!--------------------------------------------------------------------------* @brief 参照テクスチャを有効にします。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResReferenceTexture_Setup(ResTexture resTex) { ResReferenceTexture resRefTex = ResDynamicCast( resTex ); NW_ASSERT( resRefTex.IsValid() ); NW_ASSERT( resRefTex.GetTargetTexture().IsValid() ); switch(resRefTex.GetTargetTexture().ref().typeInfo) { case ResImageTexture::TYPE_INFO: { ResImageTexture_Setup(resRefTex.GetTargetTexture()); break; } case ResCubeTexture::TYPE_INFO: { ResCubeTexture_Setup(resRefTex.GetTargetTexture()); break; } case ResReferenceTexture::TYPE_INFO: { ResReferenceTexture_Setup(resRefTex.GetTargetTexture()); break; } case ResProceduralTexture::TYPE_INFO: { ResProceduralTexture_Setup(resRefTex.GetTargetTexture()); break; } case ResShadowTexture::TYPE_INFO: { ResShadowTexture_Setup(resRefTex.GetTargetTexture()); break; } default: { NW_FATAL_ERROR("Unsupported texture type.\n"); } } } /*!--------------------------------------------------------------------------* @brief プロシージャルテクスチャをセットアップします。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResProceduralTexture_Setup(ResTexture resTex) { NW_UNUSED_VARIABLE( resTex ) } /*!--------------------------------------------------------------------------* @brief イメージテクスチャの終了処理をおこないます。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResImageTexture_Cleanup(ResTexture resTex) { ResImageTexture resImgTex = ResDynamicCast( resTex ); NW_ASSERT( resImgTex.IsValid() ); GLuint texID = resImgTex.GetTextureObject(); if ( texID == 0 ) { return; } ResPixelBasedImage resImage = resImgTex.GetImage(); DeleteImage2D( texID, resImage ); resImgTex.SetTextureObject( 0 ); } /*!--------------------------------------------------------------------------* @brief シャドウテクスチャの終了処理をおこないます。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResShadowTexture_Cleanup(ResTexture resTex) { ResShadowTexture resSdwTex = ResDynamicCast( resTex ); NW_ASSERT( resSdwTex.IsValid() ); GLuint texID = resSdwTex.GetTextureObject(); if ( texID == 0 ) { return; } ResPixelBasedImage resImage = resSdwTex.GetImage(); DeleteImage2D( texID, resImage ); resSdwTex.SetTextureObject( 0 ); } /*!--------------------------------------------------------------------------* @brief イメージテクスチャの終了処理をおこないます。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResCubeTexture_Cleanup(ResTexture resTex) { ResCubeTexture resCubeTex = ResDynamicCast( resTex ); NW_ASSERT( resCubeTex.IsValid() ); GLuint texID = resCubeTex.GetTextureObject(); if ( texID == 0 ) { return; } for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face ) { ResPixelBasedImage resImage = resCubeTex.GetImage( static_cast( face ) ); DeleteImage2D( texID, resImage ); } resCubeTex.SetTextureObject( 0 ); } /*!--------------------------------------------------------------------------* @brief 参照テクスチャの終了処理をおこないます。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResReferenceTexture_Cleanup(ResTexture resTex) { ResReferenceTexture resRefTex = ResDynamicCast( resTex ); NW_ASSERT( resRefTex.IsValid() ); } /*!--------------------------------------------------------------------------* @brief プロシージャルテクスチャの終了処理をおこないます。 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。 *---------------------------------------------------------------------------*/ static void ResProceduralTexture_Cleanup(ResTexture resTex) { ResProceduralTexture resProcTex = ResDynamicCast( resTex ); NW_ASSERT( resProcTex.IsValid() ); ResProceduralNoise noise = resProcTex.GetNoise(); ut::SafeCleanup(noise.GetNoiseTable()); ResProceduralClampShift clamp = resProcTex.GetClampShift(); ResProceduralMapping mapping = resProcTex.GetMapping(); ut::SafeCleanup(mapping.GetMappingTable()); ut::SafeCleanup(mapping.GetAlphaMappingTable()); ResProceduralColor color = resProcTex.GetColor(); ut::SafeCleanup(color.GetColorTables(0)); ut::SafeCleanup(color.GetColorTables(1)); ut::SafeCleanup(color.GetColorTables(2)); ut::SafeCleanup(color.GetColorTables(3)); } //------------------------------------------------------------------------- Result ResTexture::Setup(os::IAllocator* allocator, ResGraphicsFile graphicsFile) { NW_UNUSED_VARIABLE(allocator); NW_UNUSED_VARIABLE(graphicsFile); NW_ASSERT( internal::ResCheckRevision( *this ) ); Result result = RESOURCE_RESULT_OK; switch ( this->ref().typeInfo ) { case ResImageTexture::TYPE_INFO: { s_TextureSetupTable[0]( *this ); } break; case ResCubeTexture::TYPE_INFO: { s_TextureSetupTable[1]( *this ); } break; case ResReferenceTexture::TYPE_INFO: { s_TextureSetupTable[2]( *this ); } break; case ResProceduralTexture::TYPE_INFO: { s_TextureSetupTable[3]( *this ); } break; case ResShadowTexture::TYPE_INFO: { s_TextureSetupTable[4]( *this ); } break; default: { NW_FATAL_ERROR("Unsupported texture type.\n"); } } return result; } /*---------------------------------------------------------------------------* @brief テクスチャリソースの後始末をします。 *---------------------------------------------------------------------------*/ void ResTexture::Cleanup() { switch ( this->ref().typeInfo ) { case ResImageTexture::TYPE_INFO: { s_TextureCleanupTable[0]( *this ); } break; case ResCubeTexture::TYPE_INFO: { s_TextureCleanupTable[1]( *this ); } break; case ResReferenceTexture::TYPE_INFO: { s_TextureCleanupTable[2]( *this ); } break; case ResProceduralTexture::TYPE_INFO: { s_TextureCleanupTable[3]( *this ); } break; case ResShadowTexture::TYPE_INFO: { s_TextureCleanupTable[4]( *this ); } break; default: { NW_FATAL_ERROR("Unsupported texture type.\n"); } } } //---------------------------------------- ResImageTexture ResImageTexture::DynamicBuilder::Create( os::IAllocator* allocator ) { NW_NULL_ASSERT(allocator); // 2のべき乗のチェック NW_ASSERT( (m_Description.height & (m_Description.height - 1)) == 0 ); NW_ASSERT( (m_Description.width & (m_Description.width - 1)) == 0 ); // テクスチャサイズのチェック const s32 TEXTURE_SIZE_MAX = 1024; const s32 TEXTURE_SIZE_MIN = ( m_Description.formatHW == ResPixelBasedTexture::FORMAT_HW_ETC1 ? 16 : 8 ); NW_MINMAX_ASSERT( m_Description.height, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX ); NW_MINMAX_ASSERT( m_Description.width, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX ); // ミップマップサイズは 1 以上を指定する必要があります。 NW_ASSERT(m_Description.mipmapSize > 0); // ピクセルフォーマットを取得するためのテーブルです。 static const uint GL_FORMAT_TABLE[] = { GL_RGBA_NATIVE_DMP, // 1ピクセルが4バイト、RGBAが各8ビットのフォーマットです。 GL_RGB_NATIVE_DMP, // 1ピクセルが4バイト、RGBが各8ビットのフォーマットです。 GL_RGBA_NATIVE_DMP, // 1ピクセルが2バイト、RGBが各5ビット、Aが1ビットのフォーマットです。 GL_RGB_NATIVE_DMP, // 1ピクセルが2バイト、RGBが各5,6,5ビットのフォーマットです。 GL_RGBA_NATIVE_DMP, // 1ピクセルが2バイト、RGBAが各4ビットのフォーマットです。 GL_LUMINANCE_ALPHA_NATIVE_DMP, // 1ピクセルが2バイト、AlpahとLuminanceが各8ビットのフォーマットです。 GL_HILO8_DMP_NATIVE_DMP, // 1ピクセルが2バイト、X,Yが各8ビットのフォーマットです。 GL_LUMINANCE_NATIVE_DMP, // 1ピクセルが1バイト、Luminanceが8ビットのフォーマットです。 GL_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、Alphaが8ビットのフォーマットです。 GL_LUMINANCE_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、AlpahとLuminanceが各4ビットのフォーマットです。 GL_LUMINANCE_NATIVE_DMP, // 1ピクセルが1バイト、Luminanceが4ビットのフォーマットです。 GL_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、Alphaが4ビットのフォーマットです。 GL_ETC1_RGB8_NATIVE_DMP, // 1ピクセルが4ビット相当の圧縮フォーマットです。 GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP // 1ピクセルが8ビット相当の圧縮フォーマットです。 }; static const uint GL_FORMAT_TYPE_TABLE[] = { GL_UNSIGNED_BYTE, // 1ピクセルが4バイト、RGBAが各8ビットのフォーマットです。 GL_UNSIGNED_BYTE, // 1ピクセルが4バイト、RGBが各8ビットのフォーマットです。 GL_UNSIGNED_SHORT_5_5_5_1, // 1ピクセルが2バイト、RGBが各5ビット、Aが1ビットのフォーマットです。 GL_UNSIGNED_SHORT_5_6_5, // 1ピクセルが2バイト、RGBが各5,6,5ビットのフォーマットです。 GL_UNSIGNED_SHORT_4_4_4_4, // 1ピクセルが2バイト、RGBAが各4ビットのフォーマットです。 GL_UNSIGNED_BYTE, // 1ピクセルが2バイト、AlpahとLuminanceが各8ビットのフォーマットです。 GL_UNSIGNED_BYTE, // 1ピクセルが2バイト、X,Yが各8ビットのフォーマットです。 GL_UNSIGNED_BYTE, // 1ピクセルが1バイト、Luminanceが8ビットのフォーマットです。 GL_UNSIGNED_BYTE, // 1ピクセルが1バイト、Alphaが8ビットのフォーマットです。 GL_UNSIGNED_BYTE_4_4_DMP, // 1ピクセルが1バイト、AlpahとLuminanceが各4ビットのフォーマットです GL_UNSIGNED_4BITS_DMP, // 1ピクセルが1バイト、Luminanceが4ビットのフォーマットです。 GL_UNSIGNED_4BITS_DMP, // 1ピクセルが1バイト、Alphaが4ビットのフォーマットです。 0, // 1ピクセルが4ビット相当の圧縮フォーマットです。 0 // 1ピクセルが8ビット相当の圧縮フォーマットです。 }; // ResImageTextureData のメモリ確保 void* textureDataMemory = allocator->Alloc(sizeof(ResImageTextureData)); NW_NULL_ASSERT(textureDataMemory); ResImageTextureData* textureData = new(textureDataMemory) ResImageTextureData(); //-------------------------------- // ResSceneObjectData のメンバ初期化 textureData->typeInfo = ResImageTexture::TYPE_INFO; textureData->m_Header.revision = ResImageTexture::BINARY_REVISION; textureData->m_Header.signature = ResImageTexture::SIGNATURE; textureData->toName.set_ptr(NULL); textureData->m_UserDataDicCount = 0; textureData->toUserDataDic.set_ptr(NULL); //-------------------------------- // ResPixelBasedTextureData のメンバ初期化 textureData->m_Height = m_Description.height; textureData->m_Width = m_Description.width; textureData->m_Format = GL_FORMAT_TABLE[m_Description.formatHW]; textureData->m_FormatType = GL_FORMAT_TYPE_TABLE[m_Description.formatHW]; textureData->m_MipmapSize = m_Description.mipmapSize; textureData->m_TextureObject = 0; textureData->m_LocationFlag = m_Description.locationFlag; textureData->m_FormatHW = m_Description.formatHW; // ResPixelBasedImageData のメモリ確保 void* imageDataMemory = allocator->Alloc(sizeof(ResPixelBasedImageData)); NW_NULL_ASSERT(imageDataMemory); ResPixelBasedImageData* imageData = new(imageDataMemory) ResPixelBasedImageData(); imageData->m_DynamicAllocator = allocator; imageData->m_Height = m_Description.height; imageData->m_Width = m_Description.width; imageData->m_LocationAddress = m_Description.locationAddress; const f32 BYTESIZE_4 = 4.0f; const f32 BYTESIZE_2 = 2.0f; const f32 BYTESIZE_1 = 1.0f; const f32 BYTESIZE_HALF = 0.5f; static const f32 BYTESIZE_PER_PIXEL_TABLE[] = { BYTESIZE_4, BYTESIZE_4, BYTESIZE_2, BYTESIZE_2, BYTESIZE_2, BYTESIZE_2, BYTESIZE_2, BYTESIZE_1, BYTESIZE_1, BYTESIZE_1, BYTESIZE_1, BYTESIZE_1, BYTESIZE_HALF, BYTESIZE_1 }; f32 bytesizePerPixel = BYTESIZE_PER_PIXEL_TABLE[m_Description.formatHW]; imageData->m_BitsPerPixel = static_cast(bytesizePerPixel * 8); u32 byteCount = 0; s32 h = m_Description.height; s32 w = m_Description.width; // テクスチャのために確保するメモリサイズを計算します。 // ミップマップを使用する場合、ミップマップ数に応じたメモリ確保量を計算します。 for (s32 mipmapSize = m_Description.mipmapSize; mipmapSize > 0; --mipmapSize) { byteCount += static_cast(bytesizePerPixel * h * w); if (h == TEXTURE_SIZE_MIN && w == TEXTURE_SIZE_MIN) { textureData->m_MipmapSize = m_Description.mipmapSize - mipmapSize + 1; break; } if (h > TEXTURE_SIZE_MIN) { h /= 2; } if (w > TEXTURE_SIZE_MIN) { w /= 2; } } // ピクセルデータ のメモリ確保 // isDynamicAllocation が指定されていた場合はメモリ確保を行う if (m_Description.isDynamicAllocation) { const u8 ALIGNMENT = 128; NW_ASSERT(byteCount != 0); void* bufferMemory = allocator->Alloc(byteCount, ALIGNMENT); NW_NULL_ASSERT(bufferMemory); u8* buffer = static_cast(bufferMemory); if (m_Description.executingMemoryFill) { std::fill_n(NW_CHECKED_ARRAY_ITERATOR(buffer, byteCount), byteCount, 0); } imageData->m_ImageDataTableCount = byteCount; imageData->toImageDataTable.set_ptr(buffer); } else { imageData->m_ImageDataTableCount = 0; imageData->toImageDataTable.set_ptr(NULL); } //-------------------------------- // ResImageTextureData のメンバ初期化 textureData->toImage.set_ptr(imageData); return ResImageTexture(textureData); } //---------------------------------------- ResShadowTexture ResShadowTexture::DynamicBuilder::Create( os::IAllocator* allocator ) { NW_NULL_ASSERT(allocator); // 2のべき乗のチェック NW_ASSERT( (m_Description.height & (m_Description.height - 1)) == 0 ); NW_ASSERT( (m_Description.width & (m_Description.width - 1)) == 0 ); // テクスチャサイズのチェック const s32 TEXTURE_SIZE_MAX = 1024; const s32 TEXTURE_SIZE_MIN = 8; NW_MINMAX_ASSERT( m_Description.height, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX ); NW_MINMAX_ASSERT( m_Description.width, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX ); // ResShadowTextureData のメモリ確保 void* textureDataMemory = allocator->Alloc(sizeof(ResShadowTextureData)); NW_NULL_ASSERT(textureDataMemory); ResShadowTextureData* textureData = new(textureDataMemory) ResShadowTextureData(); //-------------------------------- // ResSceneObjectData のメンバ初期化 textureData->typeInfo = ResShadowTexture::TYPE_INFO; textureData->m_Header.revision = ResShadowTexture::BINARY_REVISION; textureData->m_Header.signature = ResShadowTexture::SIGNATURE; textureData->toName.set_ptr(NULL); textureData->m_UserDataDicCount = 0; textureData->toUserDataDic.set_ptr(NULL); //-------------------------------- // ResPixelBasedTextureData のメンバ初期化 textureData->m_Height = m_Description.height; textureData->m_Width = m_Description.width; textureData->m_Format = GL_SHADOW_DMP; textureData->m_FormatType = GL_UNSIGNED_INT; textureData->m_MipmapSize = 0; textureData->m_TextureObject = 0; textureData->m_LocationFlag = m_Description.locationFlag; textureData->m_FormatHW = ResPixelBasedTexture::FORMAT_HW_RGBA8; // ResPixelBasedImageData のメモリ確保 void* imageDataMemory = allocator->Alloc(sizeof(ResPixelBasedImageData)); NW_NULL_ASSERT(imageDataMemory); ResPixelBasedImageData* imageData = new(imageDataMemory) ResPixelBasedImageData(); imageData->m_DynamicAllocator = allocator; imageData->m_Height = m_Description.height; imageData->m_Width = m_Description.width; imageData->m_LocationAddress = m_Description.locationAddress; const f32 BYTESIZE_4 = 4.0f; f32 bytesizePerPixel = BYTESIZE_4; imageData->m_BitsPerPixel = static_cast(bytesizePerPixel * 8); u32 byteCount = 0; s32 h = m_Description.height; s32 w = m_Description.width; // テクスチャのために確保するメモリサイズを計算します。 // ミップマップを使用する場合、ミップマップ数に応じたメモリ確保量を計算します。 byteCount += static_cast(bytesizePerPixel * h * w); // ピクセルデータ のメモリ確保 // isDynamicAllocation が指定されていた場合はメモリ確保を行う if (m_Description.isDynamicAllocation) { const u8 ALIGNMENT = 128; NW_ASSERT(byteCount); void* bufferMemory = allocator->Alloc(byteCount, ALIGNMENT); NW_NULL_ASSERT(bufferMemory); u8* buffer = static_cast(bufferMemory); if (m_Description.executingMemoryFill) { std::fill_n(NW_CHECKED_ARRAY_ITERATOR(buffer, byteCount), byteCount, 0); } imageData->m_ImageDataTableCount = byteCount; imageData->toImageDataTable.set_ptr(buffer); } else { imageData->m_ImageDataTableCount = 0; imageData->toImageDataTable.set_ptr(NULL); } //-------------------------------- // ResImageTextureData のメンバ初期化 textureData->toImage.set_ptr(imageData); //-------------------------------- // ResShadowTextureData のメンバ初期化 textureData->m_IsPerspectiveShadow = m_Description.isPerspectiveShadow; textureData->m_ShadowZBias = m_Description.shadowZBias; textureData->m_ShadowZScale = m_Description.shadowZScale; return ResShadowTexture(textureData); } //----------------------------------------- void ResImageTexture::DynamicDestroy() { os::IAllocator* allocator = this->GetImage().ref().m_DynamicAllocator; NW_NULL_ASSERT( allocator ); if (this->IsValid()) { ResPixelBasedImage resPixelBasedImage = this->GetImage(); if (resPixelBasedImage.IsValid()) { // ピクセルデータ のメモリ開放 if (resPixelBasedImage.ptr()->toImageDataTable.to_ptr() != NULL) { allocator->Free(resPixelBasedImage.ptr()->toImageDataTable.to_ptr()); resPixelBasedImage.ptr()->toImageDataTable.set_ptr(NULL); } // ResPixelBasedImageData のメモリ開放 allocator->Free(resPixelBasedImage.ptr()); } resPixelBasedImage.ptr()->m_DynamicAllocator = NULL; // ResImageTextureData のメモリ開放 allocator->Free(this->ptr()); this->ptr()->toImage.set_ptr(NULL); this->invalidate(); } } //----------------------------------------- void ResShadowTexture::DynamicDestroy() { os::IAllocator* allocator = this->GetImage().ref().m_DynamicAllocator; NW_NULL_ASSERT( allocator ); ResPixelBasedImage resPixelBasedImage = this->GetImage(); if(resPixelBasedImage.IsValid()) { // ピクセルデータ のメモリ開放 if (resPixelBasedImage.ptr()->toImageDataTable.to_ptr() != NULL) { allocator->Free(resPixelBasedImage.ptr()->toImageDataTable.to_ptr()); resPixelBasedImage.ptr()->toImageDataTable.set_ptr(NULL); } // ResPixelBasedImageData のメモリ開放 allocator->Free(resPixelBasedImage.ptr()); } resPixelBasedImage.ptr()->m_DynamicAllocator = NULL; // ResImageTextureData のメモリ開放 allocator->Free(this->ptr()); this->ptr()->toImage.set_ptr(NULL); this->invalidate(); } //--------------------------------------------------------------------------- bool ResPixelBasedImage::CheckMemoryLocation() const { if (! nw::os::IsDeviceMemory(this->GetImageData())) { return false; } u32 startAddress = reinterpret_cast( this->GetImageData() ); u32 endAddress = reinterpret_cast( this->GetImageData() ) + static_cast(this->GetImageDataCount()) - 1; // 128 バイトアライメントチェック。 if ((startAddress & 0x7F) != 0) { return false; } // 32MB 境界チェックは ハードウェア的に問題が無いことが分かったので削除。 return true; } } /* namespace res */ } /* namespace gfx */ } /* namespace nw */