v 0. Pasted by Anonymous as cpp at 2014-10-31 19:09:58 MSK and set expiration to never.

Paste will expire never.

  1. #include "nu_StdHeader.h"
  2. #include "nu_Metal_Texture.h"
  3. #include "nu_ProjectFiles.h"
  4. #include "nu_Xml.h"
  5. #include "nu_Pak.h"
  6. #include "nu_TextureSetting.h"
  7. #include "nu_TextureLoader.h"
  8. #include "nu_FileStream.h"
  9. #include "PVRTTexture.h"
  10. #include "nu_Time.h"
  11.  
  12. NAMESPACE_NULIGINE_BEGIN;
  13.  
  14. Metal_Texture::Metal_Texture(Scene *_scene) : TextureGpuRaw(_scene){
  15.     nu_assert_ptr(scene);
  16.     render = dynamic_cast<Metal_Render*>(scene->render);
  17.     nu_assert_ptr(render);
  18.     nu_assert(render->device != nil);
  19. }
  20. Metal_Texture::~Metal_Texture(){
  21.     nu_assert(tex == nil);
  22.     nu_assert(tex_stencil == nil);
  23. }
  24. void Metal_Texture::DoDeleteInThreadGPU(){
  25.     tex = nil;
  26.     tex_stencil = nil;
  27. }
  28. void Metal_Texture::CreateTextureAsunc( size_t &size_move_to_gpu ){
  29.     if (desc.is_render_target){
  30.         Create(nullptr, desc.init_data.bits());
  31.         desc.init_data = UI_Image();
  32.     }
  33.     else if ( desc.is_from_file ){
  34.         if( desc.is_cube )
  35.             DoLoadCube( );
  36.         else
  37.             DoLoad2D( use_setting );
  38.     }
  39. }
  40. void Metal_Texture::Create(TextureSetting *ts, void *init_data){
  41.     MTLPixelFormat format = MTLPixelFormatInvalid;
  42.     switch (Desc().format) {
  43.         case TF_NULL_FORMAT: format = MTLPixelFormatInvalid; break;
  44.         case TF_R_8_UNORM: format = MTLPixelFormatR8Unorm; break;
  45.         case TF_R_16_UNORM: format = MTLPixelFormatR16Unorm; break;
  46.         case TF_R_32_FLOAT: format = MTLPixelFormatR32Float; break;
  47.         case TF_RG_16_UNORM: format = MTLPixelFormatRG16Unorm; break;
  48.         case TF_RGBA_8_UNORM: format = MTLPixelFormatRGBA8Unorm; break;
  49.         case TF_RGB_10_A2_UNORM: format = MTLPixelFormatRGB10A2Unorm; break;
  50.         case TF_RGBA_16_UNORM: format = MTLPixelFormatRGBA16Unorm; break;
  51.         case TF_RGBA_16_FLOAT: format = MTLPixelFormatRGBA16Float; break;
  52.         case TF_RGBA_32_FLOAT: format = MTLPixelFormatRGBA32Float; break;
  53.         case TF_D_16: format = MTLPixelFormatDepth32Float; break;
  54.         case TF_D_24: format = MTLPixelFormatDepth32Float; break;
  55.         case TF_D_24_S8: format = MTLPixelFormatDepth32Float; break;
  56.         case TF_D_32: format = MTLPixelFormatDepth32Float; break;
  57.     }
  58.     nu_assert(format != MTLPixelFormatInvalid);
  59.     MTLTextureDescriptor *texDesc = nil;
  60.     if (Desc().is_cube){
  61.         texDesc = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat: format
  62.                                                                         size: Desc().width
  63.                                                                    mipmapped: NO];
  64.     }
  65.     else{
  66.         texDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: format
  67.                                                                     width: Desc().width
  68.                                                                    height: Desc().height
  69.                                                                 mipmapped: NO];
  70.         // create stencil in to this texture, need bacause OpenGL and DX support only depth in texture inself
  71.         if(Desc().format == TF_D_24_S8){
  72.             MTLTextureDescriptor *stencilTexDesc =
  73.                 [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatStencil8
  74.                                                                    width: Desc().width
  75.                                                                   height: Desc().height
  76.                                                                mipmapped: NO];
  77.             tex_stencil = [render->device newTextureWithDescriptor: stencilTexDesc];
  78.         }
  79.     }
  80.     tex = [render->device newTextureWithDescriptor:texDesc];
  81.     if(init_data){
  82.         if (Desc().is_cube){
  83.             nu_assert_force;
  84.         }else{
  85.             [tex replaceRegion: MTLRegionMake2D(0, 0, Desc().width, Desc().height)
  86.                    mipmapLevel: 0
  87.                      withBytes: init_data
  88.                    bytesPerRow: Desc().width * 4 ];
  89.         }
  90.     }
  91. }
  92. void Metal_Texture::DoLoad2D(TextureSetting *ts ){
  93.     nu_assert( tex == 0 );
  94.     nu_assert_ptr( file_streams[0] );
  95.     CachFile *f= file_streams[0]->GetCachFile();
  96.     if( f->NotEmpty() ){
  97.         if( load_format[0] == tlf_PVR )
  98.             LoadPVR( f, ts, true );
  99.         else if( load_format[0] == tlf_Source )
  100.             LoadFromSource( f, ts, true );
  101.         else
  102.             nu_assert_force;
  103.     }
  104. }
  105. void Metal_Texture::DoLoadCube(){
  106.     nu_assert( !tex );
  107.     TextureSetting *ts = scene->GetTextureSettings()->Get( Desc().name );
  108.     for( int i =0; i < 6; i++ ){
  109.         FileStream *fs = file_streams[i];
  110.         if( fs ){
  111.             CachFile *f= fs->GetCachFile();
  112.             if( f->NotEmpty() ){
  113.                 if( load_format[i] == tlf_Source )
  114.                     LoadFromSource(  f, ts, false, i );
  115.                 else if( load_format[i] == tlf_PVR )
  116.                     LoadPVR(  f, ts, false, i );
  117.                 else
  118.                     nu_assert_force;
  119.             }
  120.         }
  121.     }
  122.     GL( glBindTexture( GL_TEXTURE_CUBE_MAP, 0 ) );
  123. }
  124. void Metal_Texture::LoadFromSource(CachFile *f , TextureSetting *ts, bool can_mip_map, int cube_index ){
  125.     UNUSED( ts );
  126.     nu_assert( f );
  127.     TextureLoader loader;
  128.     loader.Load( desc.name, f, scene->GetProjectFiles() );
  129.     loader.SetTextureSetting( ts );
  130.     loader.FlipVertical();
  131.     void *data = loader.GetData();
  132.     if( data ){
  133.         desc.width = loader.GetW();
  134.         desc.height = loader.GetH();
  135.         if(!tex){
  136.             MTLTextureDescriptor *texDesc = nil;
  137.             if(cube_index == -1) //2d tex
  138.                 texDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:Desc().width height: Desc().height mipmapped:NO];
  139.             else{
  140.                 nu_assert(cube_index == 0); // check on first slice, becase need create when create first slice
  141.                 texDesc = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm size:Desc().width mipmapped:NO];
  142.             }
  143.             nu_assert(texDesc);
  144.             //texDesc.mipmapLevelCount = 0;
  145.             tex = [render->device newTextureWithDescriptor:texDesc];
  146.         }
  147.         if(cube_index == -1){
  148.             [tex replaceRegion: MTLRegionMake2D(0, 0, Desc().width, Desc().height)
  149.                    mipmapLevel:0
  150.                      withBytes:data
  151.                    bytesPerRow:desc.width*4 ];
  152.         }
  153.         else{
  154.             [tex replaceRegion: MTLRegionMake2D(0, 0, Desc().width, Desc().height)
  155.                    mipmapLevel:0
  156.                          slice:cube_index
  157.                      withBytes:data
  158.                    bytesPerRow:desc.width*4
  159.                  bytesPerImage:desc.width*desc.height * 4];
  160.         }
  161.          desc.mip_count = 1;
  162. //        if(desc.is_gen_mip_map_if_source){
  163. //            GL( glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE));
  164. //            GL( glGenerateMipmap(target) );
  165. //            desc.mip_count = ceil(Math::Log2(nu_max(desc.width, desc.height))) + 1;
  166. //        }else{
  167. //            desc.mip_count = 1;
  168. //        }
  169.     }
  170. }
  171.  
  172.  
  173. #define PVR_TEXTURE_FLAG_TYPE_MASK  0xff
  174.  
  175. enum{
  176.     kPVRTextureFlagTypePVRTC_2 = 24,
  177.     kPVRTextureFlagTypePVRTC_4
  178. };
  179. typedef struct _PVRTexHeader{
  180.     uint32_t headerLength;
  181.     uint32_t height;
  182.     uint32_t width;
  183.     uint32_t numMipmaps;
  184.     uint32_t flags;
  185.     uint32_t dataLength;
  186.     uint32_t bpp;
  187.     uint32_t bitmaskRed;
  188.     uint32_t bitmaskGreen;
  189.     uint32_t bitmaskBlue;
  190.     uint32_t bitmaskAlpha;
  191.     uint32_t pvrTag;
  192.     uint32_t numSurfs;
  193. } PVRTexHeader;
  194.  
  195. void Metal_Texture::LoadPVR( CachFile *f, TextureSetting *ts, bool can_mip_map, int cube_index ){
  196.     UNUSED(ts);
  197.     if( !f->GetData() )
  198.         return;
  199.  
  200.     char *m_pData = (char*)f->GetData();
  201.    MTLPixelFormat m_glFormat = MTLPixelFormatInvalid;
  202.    int m_uiBPP = 0;
  203.    unsigned int m_uiMIP = 0;
  204.    char* m_pTextureData = 0;
  205.    bool m_bCompressed = false;
  206.    unsigned int m_iNumFaces = 0;
  207.    if(*(PVRTuint32*)m_pData != PVRTEX3_IDENT){
  208.        //std::cout<<"[CParser_PVR::Load] OLD PVR format"<<std::endl;
  209.        PVR_Texture_Header* pHeader;
  210.        pHeader = (PVR_Texture_Header*)m_pData;
  211.        if( (pHeader->dwpfFlags & PVRTEX_PIXELTYPE) == OGL_PVRTC2 ){
  212.            m_uiBPP = 2;
  213.            m_glFormat = pHeader->dwAlphaBitMask ? MTLPixelFormatPVRTC_RGBA_2BPP : MTLPixelFormatPVRTC_RGB_2BPP;
  214.        }else if( (pHeader->dwpfFlags & PVRTEX_PIXELTYPE) == OGL_PVRTC4 ){
  215.            m_uiBPP = 4;
  216.            m_glFormat = pHeader->dwAlphaBitMask ? MTLPixelFormatPVRTC_RGBA_4BPP : MTLPixelFormatPVRTC_RGB_4BPP;
  217.    
  218.        }else{
  219.            std::cout<<"[CParser_PVR::Load] Unsupported format for Texture Name : "<< desc.name.ToUtf8() <<"\n";
  220.            return;
  221.        }
  222.        desc.width = pHeader->dwWidth;
  223.        desc.height = pHeader->dwHeight;
  224.        m_uiMIP = pHeader->dwMipMapCount ? pHeader->dwMipMapCount : 1;
  225.        m_bCompressed = true;
  226.        m_pTextureData = m_pData + pHeader->dwHeaderSize;
  227.        m_iNumFaces = 1;
  228.    }
  229.    else{
  230.        //std::cout<<"[CParser_PVR::Load] NEW PVR format"<<std::endl;
  231.        PVRTextureHeaderV3* pHeader = (PVRTextureHeaderV3*)m_pData;
  232.        if(pHeader->u64PixelFormat == 0 ){ m_glFormat = MTLPixelFormatPVRTC_RGB_2BPP; m_uiBPP = 2; }
  233.        else if(pHeader->u64PixelFormat == 1 ){ m_glFormat = MTLPixelFormatPVRTC_RGBA_2BPP; m_uiBPP = 2; }
  234.        else if(pHeader->u64PixelFormat == 2 ){m_glFormat = MTLPixelFormatPVRTC_RGB_4BPP; m_uiBPP = 4; }
  235.        else if(pHeader->u64PixelFormat == 3 ){m_glFormat = MTLPixelFormatPVRTC_RGBA_4BPP; m_uiBPP = 4; }
  236.        else{
  237.            std::cout<<"[CParser_PVR::Load] Unsupported format for Texture Name : "<<desc.name.ToUtf8() <<"\n";
  238.            return;
  239.        }
  240.        desc.width = pHeader->u32Width;
  241.        desc.height = pHeader->u32Height;
  242.        m_uiMIP = pHeader->u32MIPMapCount ? pHeader->u32MIPMapCount : 1;
  243.        m_bCompressed = true;
  244.        m_pTextureData = m_pData + PVRTEX3_HEADERSIZE + pHeader->u32MetaDataSize;
  245.        m_iNumFaces = pHeader->u32NumFaces;
  246.    }
  247.    int skip_count = GetCountSckipMipLevels(m_uiMIP);
  248.    bool is_use_mips = GetUseMipLevels();
  249.    int use_mip_count = 0;
  250.    char* pData = m_pTextureData;
  251.    for(unsigned int iFaces = 0; iFaces < m_iNumFaces; iFaces++){
  252.        if (m_bCompressed){
  253.            int cur_w = desc.width;
  254.            int cur_h = desc.height;
  255.            for (int level = 0; cur_w > 0 && cur_h > 0; ++level){
  256.                GLsizei iSize = std::max(32, cur_w * cur_h * m_uiBPP / 8);
  257.                if (skip_count == 0 ){
  258.                    if(tex == nil){
  259.                        MTLTextureDescriptor *texDesc = nil;
  260.                        if(cube_index == -1)
  261.                            texDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:m_glFormat width:cur_w height:cur_h mipmapped:YES];
  262.                        else
  263.                            texDesc = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:m_glFormat size:cur_w mipmapped:can_mip_map ? YES : NO];
  264.                        //texDesc.mipmapLevelCount = 0;
  265.                        tex = [render->device newTextureWithDescriptor:texDesc];
  266.                    }
  267.                    nu_assert(tex);
  268.                    if(cube_index == -1){
  269.                        [tex replaceRegion: MTLRegionMake2D(0, 0, cur_w, cur_h)
  270.                               mipmapLevel:use_mip_count
  271.                                 withBytes:pData
  272.                               bytesPerRow:0 ];
  273.                    }else{
  274.                        [tex replaceRegion: MTLRegionMake2D(0, 0, cur_w, cur_h)
  275.                               mipmapLevel:use_mip_count
  276.                                     slice:cube_index
  277.                                 withBytes:pData
  278.                               bytesPerRow:0
  279.                             bytesPerImage:0]; // desc.width*desc.height * 4
  280.                    }
  281.                    use_mip_count++;
  282.                    if (!is_use_mips)
  283.                        break;
  284.                }
  285.                else{
  286.                    skip_count--;
  287.                }
  288.                pData += iSize;
  289.                cur_w >>= 1; cur_h >>= 1;
  290.            }
  291.        }else{
  292.            nu_assert_force;
  293.        }
  294.    }
  295.    desc.mip_count = use_mip_count;
  296. }
  297.  
  298. void Metal_Texture::ReadTextureData(){
  299.     //  if( GetCanUse() &&  Desc().width && Desc().height ){
  300.     //      LOCKER( readed_data_mutex );
  301.     //      readed_data_size = Desc().width * Desc().height * 4;
  302.     //      nu_assert(readed_data == nullptr);
  303.     //      NU_ALLOC( readed_data, readed_data_size );
  304.     //      GL( glFinish() );
  305.     //      GL( glBindTexture( GL_TEXTURE_2D, tex ) );
  306.     //#if IS_IPHONE_PLATFORM == 1
  307.     //        GLuint framebuffer = 0;
  308.     //        GLint glDefaultRenderBuffer = 0;
  309.     //        GL( glGetIntegerv(GL_FRAMEBUFFER_BINDING, &glDefaultRenderBuffer) );
  310.     //        GL( glGenFramebuffers(1, &framebuffer) );
  311.     //        GL( glBindFramebuffer(GL_FRAMEBUFFER, framebuffer) );
  312.     //        GL( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0) );
  313.     //        GLenum status;
  314.     //        GL( status = glCheckFramebufferStatus(GL_FRAMEBUFFER) );
  315.     //        if (status != GL_FRAMEBUFFER_COMPLETE) {
  316.     //            std::cout << "Problem with OpenGL framebuffer after specifying color render buffer: \n";
  317.     //            nu_assert_force;
  318.     //        }
  319.     //        GL( glReadPixels(0, 0, Desc().width, Desc().height,GL_RGBA, GL_UNSIGNED_BYTE, (GLubyte*)readed_data ) );
  320.     //        GL( glBindFramebuffer(GL_FRAMEBUFFER, glDefaultRenderBuffer) );
  321.     //        GL( glDeleteFramebuffers(1, &framebuffer) );
  322.     //#else
  323.     //      GL( glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLubyte*)readed_data ) );
  324.     //#endif
  325.     //      GL( glBindTexture( GL_TEXTURE_2D, 0 ) );
  326.     //  }
  327. }
  328.  
  329.  
  330.  
  331. NAMESPACE_NULIGINE_END;