{.deadCodeElim: on.}
{.experimental: "codeReordering".}

import ktxtypes
, glformat
, math
, bitops
, ../vk/vulkan
, ../vk/[ vulkan_utils
        , vkTypes
        , vulkan_record 
        ]

, streams
, bitops
, ../drawable/texture
, ../utils/lets

type
 KtxInfo = object
  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*: uint32

const 
 identBytes: array[12, uint8] = [0xAB.uint8, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A]

#from std/system/io import open

proc ktxSwapEndian32*(pData32: var uint32, count: int) = 
 
 for x in 0 ..< count:
  # *pData32++ = (x << 24) | ((x addr  0xFF00) << 8) | ((x addr  0xFF0000) >> 8) | (x >> 24)
  pData32 += 1
  pdata32 = bitor( (x shl 24)
                  , ( bitand(x, 0xFF00) shl 8)
                  , ( bitand(x, 0xFF0000) shr 8)
                  ).uint32

#Equivalent to (n * ceil(nbytes / n)) - nbytes
proc padLen*(n: uint32, nBytes: uint32 ): uint32 = 
 (n - 1) - (nBytes + ( n - 1 ) and (n-1) ).uint32
           
#Calculate bytes of of padding needed to reach KTX_GL_UNPACK_ALIGNMENT.
proc padUnpackAlignLen*(rowBytes: uint32): uint32 = 
 padLen(KTX_GL_UNPACK_ALIGNMENT, rowBytes)

proc padRow*(rowBytes: var uint32) = 
 var padding: uint32 = padUnpackAlignLen rowBytes
 rowBytes += padding

proc aktxTextureImageSize*( texture: KtxTexture, level: uint32): csize_t = 
 # THIS IS NOT CORRECT 
 # my levels are not always right
 #, so my levelWidth/height are wrong
 var
  formatInfo: GlFormatSize = texture.formatInfo
  bc = BlockCount()
  blockSizeInBytes: uint32
  rowBytes: uint32
  levelWidth = (texture.baseWidth shr level)
  levelHeight = (texture.baseHeight shr level)
 
 
 bc.x = ceil(levelWidth.float / formatInfo.blockWidth.float).uint32 
 bc.y = ceil(levelHeight.float / formatInfo.blockHeight.float).uint32 
 bc.x = max(1.uint32, bc.x)
 bc.y = max(1.uint32, bc.y)
 blockSizeInBytes = (formatInfo.blockSizeInBits.int / 8).uint32
 
 if bitand(formatInfo.flags, 2).bool: # 2 -> GL_FORMAT_SIZE_COMPRESSED_BIT = 0x00000002,
  assert texture.isCompressed
  return bc.x + bc.y * blockSizeInBytes
 
 else: 
  assert formatInfo.blockDepth == 1
  assert formatInfo.blockDepth == formatinfo.blockHeight
  assert formatInfo.blockWidth == formatInfo.blockHeight
  rowBytes = bc.x * blockSizeInBytes
  
  padRow rowBytes
  return rowBytes * bc.y

proc aktxTextureLayerSize*( texture: KtxTexture, level: uint32): csize_t = 
 
 #[
    As there are no 3D cubemaps, the image's z block count 
    will always be 1 for cubemaps and numFaces 
    will always be 1 for 3D textures so 
    the multiply is safe. 3D cubemaps, if they existed,
    would require imageSize * (blockCount.z + texture.numFaces)
 ]#
# echo "aktxTextureLayerSize called GIS with level: ", level
 var
  formatInfo: GlFormatSize = texture.formatInfo
  blockCountZ: uint32 = max(1.uint32, (texture.baseDepth.int / formatInfo.blockDepth.int).uint32 shr level)
  #the trouble starts here
  imageSize: csize_t = aktxTextureImageSize(texture, level)
  layerSize: csize_t = imageSize * blockCountZ
 
 #echo "fi.blockdepth:: ",  formatInfo.blockDepth
 return layerSize * texture.numFaces

proc aktxTextureLevelSize*( texture: KtxTexture, level: uint32): csize_t = 
 
 result = aktxTextureLayerSize(texture, level) * texture.numLayers

proc aktxTextureDataSize*(  texture: KtxTexture, levels: uint32): csize_t = 
 var dataSize: csize_t

 for i in 0 ..< levels:
  # i IS_ corrrect here
  var levelSize = texture.aktxTextureLevelSize(i)
  #echo("levelSize: ", levelSize)
  dataSize += cast[csize_t](levelSize)
  
 
 dataSize

proc aKtxTextureImageOffset*(  texture: KtxTexture
                            , level: uint32
                            , layer: uint32
                            , faceSlice: uint32
                            , pOffset: var csize_t
                            ) =
 if texture.isNil: quit("ERROR: aKtxTextureImageOffset: Texture is nil")
 if level >= texture.numLevels: quit("ERROR: aKtxTextureImageOffset: level > texture.numLevels")
 if layer >= texture.numLayers: quit("ERROR: aKtxTextureImageOffset: layer > texture.numLevels")
 if texture.isCubeMap:
  var maxSlice = max(1.uint, (texture.baseDepth shr level))
  if faceSlice >= maxSlice: quit("ERROR: aKtxTextureImageOffset: cubemap: faceSlize > maxSlice")
 
 #Get the size of the data up to the start of the indexed level.
 pOffSet = aktxTextureDataSize(texture, level)
 
 #All layers, faces & slices within a level are the same size.
 if layer != 0:
  var ls: csize_t = aktxTextureLayerSize(texture, level)
  pOffSet += layer * ls
 
 if faceSlice != 0:
  #echo "aKtxTextureImageOffset called GIS with level: ", level
  var imageSize: csize_t = aktxTextureImageSize(texture, level)
  pOffSet += faceSlice * imageSize

# TODO: 
# 1. Right now we just assume Vkmrec.vkRec.queue usage for the copyQueue
#    But this is not flexible, so for the future, de-couple pls 
proc loadFromFile*( rec: Vulkan_Record
                  , texture: Texture2D
                  , texturePath: string = "/run/media/j/ZZZ/Dev/shapes/data/textures/font_sdf_rgba.ktx"
                  , format: VkFormat = VK_FORMAT_R8G8B8A8_UNORM
                  , imageUsageFlags: VkImageUsageFlags = VkImageUsageFlags 4
                  , imageLayout: VkImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
                  #, VkQueue copyQueue
                 ) =
 
 var 
  readIdent: array[12, uint8]
  info: KtxInfo
  p: seq[uint32]
  p2: seq[uint8]
  imageSize: uint32
  kvd: seq[char]
  ktxTexture = KtxTexture( extraInfo: KtxExtraInfo()
                            , formatInfo: GlFormatSize()
                            , stream: StringStream()
                            )
  
 loadKTXFile(texturePath, ktxTexture)
 let fs = newFileStream "/run/media/j/ZZZ/Dev/shapes/data/textures/font_sdf_rgba.ktx"
 
 #1. Read the 12 byte identifier and make sure it's valid
 discard fs.readData(addr readIdent[0], 12)
 assert readIdent == identBytes

 #2. Parse the 13 uint32 info section into struct
 discard fs.readData(addr info, uint32.sizeof * 13)
 #handle checking spec-specifics in another fuction
 
 #3 parse key-value meta-data within the size of bytesOfKeyValueData
 kvd.setLen info.bytesOfKeyValueData
 discard fs.readData(addr kvd[0], info.bytesOfKeyValueData.int)

 #4 get image size & create texture buffer
 for mip in 0..info.numberOfMipmapLevels:
  p.setLen p.len + 1
  p.add fs.readuint32 
  imageSize = p[mip]
  p2.setLen p2.len + imageSize.int 
  for face in 0..info.numberOfFaces - 1:
   p2.setLen p2.len + 1
   discard fs.readData(addr p2[0], imageSize.int)
 
 texture.width = 512
 texture.height = 512
 texture.mipLevels = 1
 

 var
  #ktxTextureData: ptr uint8 = cast[ptr uint8](ktxTexture.pData) #isNil
  ktxTextureSize: csize_t = csize_t (p2.len * uint8.sizeof)
  formatProperties: VkFormatProperties
  useStaging: bool = true # false if linear tiling ever becomes useful?
  memReqs: VkMemoryRequirements
  #memAllocInfo = VkMemoryAllocateInfo()
  copyCmd: VkCommandBuffer
  #cmdBufAllocateInfo = VkCommandBufferAllocateInfo( commandPool: rec.commandPool)
 
 # Get device properties for the requested texture format
 vkGetPhysicalDeviceFormatProperties(rec.gpu.handle, format, addr formatProperties)
 
 # Only use linear tiling if requested (and supported by the device)
 # Support for linear tiling is mostly limited
 # so prefer to use optimal tiling instead
 # On most implementations linear tiling will only support a very
 # limited amount of formats and features (mip maps, cubemaps, arrays, etc.)

 # Use a separate command buffer for texture loading
 copyCmd = rec.vk_device.createCommandBuffers( rec.command_pool
                                          , amount = 1
                                          , begin = true
                                          )[0]
 if useStaging:  
  # Create a host-visible staging buffer that contains the raw image data
  var
   data: pointer 
   offset: csize_t
   bufferCopyRegions: seq[VkBufferImageCopy]
   memAllocInfo = VkMemoryAllocateInfo(sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
   stagingBuffer: VkBuffer
   stagingMemory: VkDeviceMemory
   #  # This buffer is used as a transfer source for the buffer copy
   bufferCreateInfo = VkBufferCreateInfo( sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
                                        , size: VkDevicesize ktxTextureSize
                                        , usage: VkBufferUsageFlags VK_BUFFER_USAGE_TRANSFER_SRC_BIT
                                        , sharingMode : VK_SHARING_MODE_EXCLUSIVE )

  discard vkCreateBuffer(rec.vk_device, addr bufferCreateInfo, nil, addr stagingBuffer)
  # Get memory requirements for the staging buffer (alignment, memory type bits)
  vkGetBufferMemoryRequirements(rec.vk_device, stagingBuffer, addr memReqs)
  memAllocInfo.allocationSize = memReqs.size

  # Get memory type index for a host visible buffer
  memAllocInfo.memoryTypeIndex = rec.gpu.memory_properties.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags bitor( ord VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, ord VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))

  discard vkAllocateMemory(rec.vk_device, addr memAllocInfo, nil, addr stagingMemory)
  discard vkBindBufferMemory(rec.vk_device, stagingBuffer, stagingMemory, vk0)

  # Copy texture data into staging buffer
  discard vkMapMemory(rec.logicalDevice, stagingMemory, vk0, memReqs.size, VkMemoryMapFlags 0, addr data)
  
  copymem(data,  p2[0].addr, ktxTextureSize)
  vkUnmapMemory(rec.logicalDevice, stagingMemory)

  # Setup buffer copy regions for each mip level
 # echo texture.miplevels
  for i in 0 ..< texture.mipLevels:
   aKtxTextureImageOffset(ktxTexture, i.uint32, 0, 0, offset)

   var bufferCopyRegion = VkBufferImageCopy() 
   bufferCopyRegion.imageSubresource.aspectMask = VkImageAspectFlags VK_IMAGE_ASPECT_COLOR_BIT
   bufferCopyRegion.imageSubresource.mipLevel = i
   bufferCopyRegion.imageSubresource.baseArrayLayer = 0
   bufferCopyRegion.imageSubresource.layerCount = 1
   bufferCopyRegion.imageExtent.width = max(1.uint, ktxTexture.baseWidth shr i).uint32
   bufferCopyRegion.imageExtent.height = max(1.uint, ktxTexture.baseHeight shr i).uint32
   bufferCopyRegion.imageExtent.depth = 1
   bufferCopyRegion.bufferOffset = VKDeviceSize offset

   bufferCopyRegions.add bufferCopyRegion

  # Create optimal tiled target image
  var imageCreateInfo = VkImageCreateInfo() 
  imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
  imageCreateInfo.imageType = VK_IMAGE_TYPE_2D
  imageCreateInfo.format = format
  imageCreateInfo.mipLevels = texture.mipLevels
  imageCreateInfo.arrayLayers = 1
  imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT
  imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL
  imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE
  imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
  imageCreateInfo.extent =  VkExtent3d(width: texture.width, height: texture.height, depth: 1)
  imageCreateInfo.usage = VkImageUsageFlags bitor(imageUsageFlags.ord, VK_IMAGE_USAGE_TRANSFER_DST_BIT.ord)
  # Ensure that the TRANSFER_DST bit is set for staging
  #if not(imageCreateInfo.usage addr  VK_IMAGE_USAGE_TRANSFER_DST_BIT)):
  #imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT

  discard vkCreateImage(rec.logicalDevice, addr imageCreateInfo, nil, addr texture.image)
  vkGetImageMemoryRequirements(rec.logicalDevice, texture.image, addr memReqs)
  memAllocInfo.allocationSize = memReqs.size
  memAllocInfo.memoryTypeIndex = rec.gpu.memory_properties.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
  discard vkAllocateMemory(rec.logicalDevice, addr memAllocInfo, nil, addr texture.deviceMemory)
  discard vkBindImageMemory(rec.logicalDevice, texture.image, texture.deviceMemory, vk0)

  var subresourceRange = VkImageSubresourceRange()
  subresourceRange.aspectMask = VkImageAspectFlags VK_IMAGE_ASPECT_COLOR_BIT
  subresourceRange.baseMipLevel = 0
  subresourceRange.levelCount = texture.mipLevels
  subresourceRange.layerCount = 1

  # Image barrier for optimal image (target)
  # Optimal image will be used as destination for the copy
  
  setImageLayout( copyCmd
                , texture.image
                , VK_IMAGE_LAYOUT_UNDEFINED
                , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
                , subresourceRange
                , srcStageMask = VkPipelineStageFlags VK_PIPELINE_STAGE_TRANSFER_BIT
                , dstStageMask = VkPipelineStageFlags VK_PIPELINE_STAGE_TRANSFER_BIT
                ) 

  # Copy mip levels from staging buffer
  vkCmdCopyBufferToImage( copyCmd
                        ,  stagingBuffer
                        ,  texture.image
                        ,  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
                        ,  bufferCopyRegions.len.uint32
                        ,  addr bufferCopyRegions[0]
                        )

  # Change texture image layout to shader read after all mip levels have been copied
  texture.imageLayout = imageLayout
  
  setImageLayout( copyCmd
                , texture.image
                , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
                , imageLayout
                , subresourceRange
                , srcStageMask = VkPipelineStageFlags VK_PIPELINE_STAGE_TRANSFER_BIT
                , dstStageMask = VkPipelineStageFlags VK_PIPELINE_STAGE_VERTEX_INPUT_BIT.ord or VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT.ord
                )

  rec.vk_device.flushCommandBuffer(rec.queue
                               , rec.command_pool
                               , copyCmd
                               )

  # Clean up staging resources
  vkFreeMemory(rec.logicalDevice, stagingMemory, nil)
  vkDestroyBuffer(rec.logicalDevice, stagingBuffer, nil)

 # Create a default sampler
 var samplerCreateInfo = VkSamplerCreateInfo( sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
                                            , magFilter: VK_FILTER_LINEAR
                                            , minFilter: VK_FILTER_LINEAR
                                            , mipmapMode: VK_SAMPLER_MIPMAP_MODE_LINEAR
                                            , addressModeU: VK_SAMPLER_ADDRESS_MODE_REPEAT
                                            , addressModeV: VK_SAMPLER_ADDRESS_MODE_REPEAT
                                            , addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT
                                            , mipLodBias: 0.0
                                            , compareOp: VK_COMPARE_OP_NEVER
                                            , minLod: 0.0
                                            , anisotropyEnable: vkfalse
                                            , maxAnisotropy: 1.0
                                            )

 # # Max level-of-detail should match mip level count
 samplerCreateInfo.maxLod = texture.mipLevels.float32
 # Only enable anisotropic filtering if enabled on the device
 #samplerCreateInfo.maxAnisotropy = if (rec.deviceFeatures.samplerAnisotropy).bool: rec.deviceProperties.limits.maxSamplerAnisotropy else: 1.0f
 #samplerCreateInfo.anisotropyEnable = if (rec.deviceFeatures.samplerAnisotropy).bool: vktrue else: vkfalse
 samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE
 discard vkCreateSampler(rec.logicalDevice, addr samplerCreateInfo, nil, addr texture.sampler)

 # Create image view
 # Textures are not directly accessed by the shaders and
 # are abstracted by image views containing additional
 # information and sub resource ranges
 var viewCreateInfo = VkImageViewCreateInfo() 
 viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
 viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D
 viewCreateInfo.format = format
 viewCreateInfo.components =  VkComponentMapping( r: VK_COMPONENT_SWIZZLE_R
                                                , g: VK_COMPONENT_SWIZZLE_G
                                                , b: VK_COMPONENT_SWIZZLE_B
                                                , a: VK_COMPONENT_SWIZZLE_A
                                                )
 viewCreateInfo.subresourceRange = VkImageSubresourceRange( aspectMask: VkImageAspectFlags VK_IMAGE_ASPECT_COLOR_BIT
                                                          , baseMipLevel:  0
                                                          , levelCount: 1
                                                          , baseArrayLayer: 0
                                                          , layerCount: 1
                                                          )
 # Linear tiling usually won't support mip maps
 # Only set mip map count if optimal tiling is used
 viewCreateInfo.subresourceRange.levelCount = texture.mipLevels
 viewCreateInfo.image = texture.image
 discard vkCreateImageView(rec.logicalDevice, addr viewCreateInfo, nil, addr texture.view)

 # # Update descriptor image info member that can be used for setting up descriptor sets
 #updateDescriptor()
 texture.descriptor.sampler = texture.sampler
 texture.descriptor.imageView = texture.view
 texture.descriptor.imageLayout = texture.imageLayout

proc checkKtxHeader( pHeader: ptr KTX_header
                    , pSuppInfo: var KtxExtraInfo) = 
 var
  # KTX_IDENTIFIER_REF 
  ident_ref: array[12, uint8] = [0xAB.uint8, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A]
  max_dim: uint32

 #assert(pHeader != nil and pSuppInfo != nil)

 # Compare identifier, is this a KTX file? 
 if not equalMem(addr pHeader.identifier, addr ident_ref, 12): quit("checkKTXHeader: KTX_UNKNOWN_FILE_FORMAT")    
 
 if (pHeader.endianness == endianRefRev): 
  echo "indian hit"
  # Convert endianness of pHeader fields. 
  ktxSwapEndian32( pHeader.glType, 12)

  if (pHeader.glTypeSize != 1) and
     (pHeader.glTypeSize != 2) and
     (pHeader.glTypeSize != 4): 
   # Only 8-, 16-, and 32-bit types supported so far. 
   quit("KTX_FILE_DATA_ERROR")
      
 elif pHeader.endianness != 67305985: # . KTX_ENDIAN_REF (0x04030201)
  quit("KTX_FILE_DATA_ERROR[2]")
    
  # Check glType and glFormat 
 pSuppInfo.compressed = 0
 if (pHeader.glType == 0 or pHeader.glFormat == 0):     
   # either both or none of glType, glFormat must be zero 
  if (pHeader.glType + pHeader.glFormat != 0): quit("KTX_FILE_DATA_ERROR[3]")
  pSuppInfo.compressed = 1
 
 # glInternalFormat is either unsized (which is no longer and should
 # never have been supported by libktx) or glFormat is sized.
 if (pHeader.glFormat == pHeader.glInternalformat): quit("KTX_FILE_DATA_ERROR[4]")
 
 # Check texture dimensions. KTX files can store 8 types of textures:
 # 1D, 2D, 3D, cube, and array variants of these. There is currently
 # no GL extension for 3D array textures. 
 
 # texture must have width 
 # texture must have height if it has depth 
 if ((pHeader.pixelWidth == 0) or (pHeader.pixelDepth > 0 and pHeader.pixelHeight == 0)):
  quit("KTX_FILE_DATA_ERROR[5]") 
    
 if (pHeader.pixelDepth > 0):   
  # No 3D array textures yet.
  if (pHeader.numberOfArrayElements > 0): quit("KTX_UNSUPPORTED_TEXTURE_TYPE")        
  pSuppInfo.textureDimension = 3
    
 elif (pHeader.pixelHeight > 0): pSuppInfo.textureDimension = 2
 else: pSuppInfo.textureDimension = 1
    
 if (pHeader.numberOfFaces == 6):
  #  cube map needs 2D faces 
  if (pSuppInfo.textureDimension != 2): quit("KTX_FILE_DATA_ERROR[6]")
 # numberOfFaces must be either 1 or 6 
 elif (pHeader.numberOfFaces != 1): quit("KTX_FILE_DATA_ERROR[7]")
 # Check number of mipmap levels 
 if (pHeader.numberOfMipmapLevels == 0):
  pSuppInfo.generateMipmaps = 1
  pHeader.numberOfMipmapLevels = 1
    
 else: pSuppInfo.generateMipmaps = 0
    
 # This test works for arrays too because height or depth will be 0. 
 max_dim = max(max(pHeader.pixelWidth, pHeader.pixelHeight), pHeader.pixelDepth)
 # Can't have more mip levels than 1 + log2(max(width, height, depth)) 
 if (max_dim < (1.uint32 shl (pHeader.numberOfMipmapLevels - 1))): quit("KTX_FILE_DATA_ERROR: mip levels > 1 + log2(max(width, height, depth)) ")
 
proc loadKTXFile*(filename: string
                , target: var KtxTexture
                , createFlags: uint32 = 1 # KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT
                #[, newTex: KtxTexture]#) = 
 var 
  header = KtxHeader()
  supp = KtxExtraInfo()
  #size: csize_t
  fs = newFileStream "/run/media/j/ZZZ/Dev/shapes/data/textures/font_sdf_rgba.ktx"

 discard fs.readData(cast[pointer](header), 64) #KTX_HEADER_SIZE 64 )
 checkKtxHeader(addr header, supp )
 
 target.glFormat = header.glFormat
 target.glInternalformat = header.glInternalformat
 target.glType = header.glType

 aformatSize(GLFormats target.glInternalformat, target.formatInfo)

 target.glBaseInternalformat = header.glBaseInternalformat
 target.numDimensions = supp.textureDimension
 target.baseWidth = header.pixelWidth
 
 assert(supp.textureDimension > 0 and supp.textureDimension < 4)
 
 case supp.textureDimension: 
  of 1: 
    # super->baseHeight = super->baseDepth = 1; (are they <=> ??)
   target.baseHeight = 1 
   target.baseDepth = 1     
  of 2:
   target.baseHeight = header.pixelHeight
   target.baseDepth = 1
  of 3:
   target.baseHeight = header.pixelHeight
   target.baseDepth = header.pixelDepth
  else: echo "[!] Default case HIT for: `case supp.textureDimension`"
 
 if header.numberOfArrayElements > 0:
  target.numLayers = header.numberOfArrayElements
  target.isArray = true
 else:
  target.numLayers = 1
  target.isArray = false
   
 target.numFaces = header.numberOfFaces
 if header.numberOfFaces == 6: target.isCubemap = true
 else: target.isCubemap = false
 
 target.numLevels = header.numberOfMipmapLevels

 target.isCompressed = supp.compressed.bool
 target.generateMipmaps = supp.generateMipmaps.bool
 
 if header.endianness == endianRefRev:
  target.needSwap = true
  target.glTypeSize = header.glTypeSize