text: /*
   * Copyright (C) 2015 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #ifndef TNT_FILAMENT_DETAILS_TEXTURE_H
  #define TNT_FILAMENT_DETAILS_TEXTURE_H
  
  #include "upcast.h"
  
  #include <backend/Handle.h>
  
  #include <filament/Texture.h>
  
  #include <utils/compiler.h>
  
  namespace filament {
  
  class FEngine;
  class FStream;
  
  class FTexture : public Texture {
  public:
      FTexture(FEngine& engine, const Builder& builder);
  
      // frees driver resources, object becomes invalid
      void terminate(FEngine& engine);
  
      backend::Handle<backend::HwTexture> getHwHandle() const noexcept { return mHandle; }
  
      size_t getWidth(size_t level = 0) const noexcept;
      size_t getHeight(size_t level = 0) const noexcept;
      size_t getDepth(size_t level = 0) const noexcept;
      size_t getLevelCount() const noexcept { return mLevelCount; }
      size_t getMaxLevelCount() const noexcept { return FTexture::maxLevelCount(mWidth, mHeight); }
      Sampler getTarget() const noexcept { return mTarget; }
      InternalFormat getFormat() const noexcept { return mFormat; }
      Usage getUsage() const noexcept { return mUsage; }
  
      void setImage(FEngine& engine, size_t level,
              uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
              PixelBufferDescriptor&& buffer) const;
  
      void setImage(FEngine& engine, size_t level,
              uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
              uint32_t width, uint32_t height, uint32_t depth,
              PixelBufferDescriptor&& buffer) const;
  
      void setImage(FEngine& engine, size_t level,
              PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
  
      void generatePrefilterMipmap(FEngine& engine,
              PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
              PrefilterOptions const* options);
  
      void setExternalImage(FEngine& engine, void* image) noexcept;
      void setExternalImage(FEngine& engine, void* image, size_t plane) noexcept;
      void setExternalStream(FEngine& engine, FStream* stream) noexcept;
  
      void generateMipmaps(FEngine& engine) const noexcept;
  
      void setSampleCount(size_t sampleCount) noexcept { mSampleCount = uint8_t(sampleCount); }
      size_t getSampleCount() const noexcept { return mSampleCount; }
      bool isMultisample() const noexcept { return mSampleCount > 1; }
      bool isCompressed() const noexcept { return backend::isCompressedFormat(mFormat); }
  
      bool isCubemap() const noexcept { return mTarget == Sampler::SAMPLER_CUBEMAP; }
  
      FStream const* getStream() const noexcept { return mStream; }
  
      /*
       * Utilities
       */
  
      // synchronous call to the backend. returns whether a backend supports a particular format.
      static bool isTextureFormatSupported(FEngine& engine, InternalFormat format) noexcept;
  
      // synchronous call to the backend. returns whether a backend supports texture swizzling.
      static bool isTextureSwizzleSupported(FEngine& engine) noexcept;
  
      // storage needed on the CPU side for texture data uploads
      static size_t computeTextureDataSize(Texture::Format format, Texture::Type type,
              size_t stride, size_t height, size_t alignment) noexcept;
  
      // Size a of a pixel in bytes for the given format
      static size_t getFormatSize(InternalFormat format) noexcept;
  
      // Returns the with or height for a given mipmap level from the base value.
      static inline size_t valueForLevel(uint8_t level, size_t baseLevelValue) {
          return std::max(size_t(1), baseLevelValue >> level);
      }
  
      // Returns the max number of levels for a texture of given max dimensions
      static inline uint8_t maxLevelCount(uint32_t maxDimension) noexcept {
          return std::max(1, std::ilogbf(maxDimension) + 1);
      }
  
      // Returns the max number of levels for a texture of given dimensions
      static inline uint8_t maxLevelCount(uint32_t width, uint32_t height) noexcept {
          return std::max(1, std::ilogbf(std::max(width, height)) + 1);
      }
  
      static bool validatePixelFormatAndType(backend::TextureFormat internalFormat,
              backend::PixelDataFormat format, backend::PixelDataType type) noexcept;
  
  private:
      friend class Texture;
      FStream* mStream = nullptr;
      backend::Handle<backend::HwTexture> mHandle;
      uint32_t mWidth = 1;
      uint32_t mHeight = 1;
      uint32_t mDepth = 1;
      InternalFormat mFormat = InternalFormat::RGBA8;
      Sampler mTarget = Sampler::SAMPLER_2D;
      uint8_t mLevelCount = 1;
      uint8_t mSampleCount = 1;
      Usage mUsage = Usage::DEFAULT;
  };
  
  
  FILAMENT_UPCAST(Texture)
  
  } // namespace filament
  
  #endif // TNT_FILAMENT_DETAILS_TEXTURE_H
  