text: //
  // Copyright 2016 Pixar
  //
  // Licensed under the Apache License, Version 2.0 (the "Apache License")
  // with the following modification; you may not use this file except in
  // compliance with the Apache License and the following modification to it:
  // Section 6. Trademarks. is deleted and replaced with:
  //
  // 6. Trademarks. This License does not grant permission to use the trade
  //    names, trademarks, service marks, or product names of the Licensor
  //    and its affiliates, except as required to comply with Section 4(c) of
  //    the License and to reproduce the content of the NOTICE file.
  //
  // You may obtain a copy of the Apache License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the Apache License with the above modification is
  // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied. See the Apache License for the specific
  // language governing permissions and limitations under the Apache License.
  //
  #include "pxr/imaging/glf/glew.h"
  
  #include "pxr/imaging/glf/uvTextureStorageData.h"
  
  #include "pxr/base/gf/vec3d.h"
  #include "pxr/base/gf/vec4d.h" 
  #include "pxr/base/tf/diagnostic.h"
  
  #include <vector>
  
  TF_DECLARE_WEAK_AND_REF_PTRS(GlfUVTextureStorageData);
  
  GlfUVTextureStorageDataRefPtr
  GlfUVTextureStorageData::New(
      unsigned int width,
      unsigned int height, 
      const VtValue &storageData)
  {
      return TfCreateRefPtr(new GlfUVTextureStorageData(
          width, height, storageData));
  }
  
  GlfUVTextureStorageData::~GlfUVTextureStorageData()
  {
      if (_rawBuffer) {
          delete [] _rawBuffer;
          _rawBuffer = nullptr; 
      }
  }
  
  int GlfUVTextureStorageData::ComputeBytesUsed() const
  {
      if (_rawBuffer) {
          return _resizedWidth * _resizedHeight * _bytesPerPixel;
      } else {
          return 0;
      }
  }
  
  bool GlfUVTextureStorageData::HasRawBuffer() const
  {
      return (_rawBuffer != nullptr);
  }
  
  unsigned char * GlfUVTextureStorageData::GetRawBuffer() const
  {
      return _rawBuffer;
  }
  
  bool GlfUVTextureStorageData::Read(int degradeLevel, bool generateMipmap) {
      _targetMemory = _size;
      std::vector<float> storageArray;
      if (_storageData.IsHolding<float>()) {
          storageArray.resize(1); 
          storageArray[0] = _storageData.Get<float>();
          _glInternalFormat = GL_RED;
          _glFormat = GL_RED; 
      } else if (_storageData.IsHolding<double>()) { 
          storageArray.resize(1); 
          storageArray[0] = _storageData.Get<double>();
          _glInternalFormat = GL_RED;
          _glFormat = GL_RED; 
      } else if (_storageData.IsHolding<GfVec3d>()) {
          GfVec3d storageVec3d = _storageData.Get<GfVec3d>();
          storageArray.resize(3); 
          storageArray[0] = storageVec3d[0]; 
          storageArray[1] = storageVec3d[1];
          storageArray[2] = storageVec3d[2]; 
          _glInternalFormat = GL_RGB;
          _glFormat = GL_RGB; 
      } else if (_storageData.IsHolding<GfVec4d>()) {
          GfVec4d storageVec4d = _storageData.Get<GfVec4d>();
          storageArray.resize(4); 
          storageArray[0] = storageVec4d[0]; 
          storageArray[1] = storageVec4d[1];
          storageArray[2] = storageVec4d[2]; 
          storageArray[3] = storageVec4d[3];
          _glInternalFormat = GL_RGBA;
          _glFormat = GL_RGBA; 
      } else {
          TF_CODING_ERROR("Unsupported texture storage data type");
          return false; 
      }
      _bytesPerPixel = GlfGetNumElements(_glFormat) * 
                           GlfGetElementSize(_glType);
  
      _size = _resizedWidth * _resizedHeight * _bytesPerPixel;
  
      if (_rawBuffer) {
          delete [] _rawBuffer;
          _rawBuffer = nullptr;
      }    
  
      _rawBuffer = new unsigned char[_size];
      if (_rawBuffer == nullptr) {
          TF_RUNTIME_ERROR("Unable to allocate buffer.");
          return false;
      }
  
      // Transfer value from Storage Data into raw buffer
      for (int y=0; y < _resizedHeight; ++y) {
          for (int x=0; x < _resizedWidth; ++x) {
              int destIndex = (y * _resizedWidth + x) * _bytesPerPixel; 
              memcpy(&_rawBuffer[destIndex], &storageArray[0], _bytesPerPixel); 
          }
      }
  
      return true; 
  }
  
  bool GlfUVTextureStorageData::IsCompressed() const {
      return false; 
  }
  
  GlfUVTextureStorageData::GlfUVTextureStorageData(
      unsigned int width,
      unsigned int height, 
      const VtValue &storageData)
      : _targetMemory(0)
      , _resizedWidth(width)
      , _resizedHeight(height)
      , _storageData(storageData)
      , _glInternalFormat(GL_RGB)
      , _glFormat(GL_RGB)
      , _glType(GL_FLOAT)
      , _size(0)
      , _rawBuffer(nullptr)
  {
      /* nothing */
  }