/*
 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#import "RTCI420TextureCache.h"

#import <OpenGLES/ES3/gl.h>

#import "base/RTCI420Buffer.h"
#import "base/RTCVideoFrameBuffer.h"

#include <vector>

// Two sets of 3 textures are used here, one for each of the Y, U and V planes. Having two sets
// alleviates CPU blockage in the event that the GPU is asked to render to a texture that is already
// in use.
static const GLsizei kNumTextureSets = 2;
static const GLsizei kNumTexturesPerSet = 3;
static const GLsizei kNumTextures = kNumTexturesPerSet * kNumTextureSets;

@implementation RTCI420TextureCache {
  BOOL _hasUnpackRowLength;
  GLint _currentTextureSet;
  // Handles for OpenGL constructs.
  GLuint _textures[kNumTextures];
  // Used to create a non-padded plane for GPU upload when we receive padded frames.
  std::vector<uint8_t> _planeBuffer;
}

- (GLuint)yTexture {
  return _textures[_currentTextureSet * kNumTexturesPerSet];
}

- (GLuint)uTexture {
  return _textures[_currentTextureSet * kNumTexturesPerSet + 1];
}

- (GLuint)vTexture {
  return _textures[_currentTextureSet * kNumTexturesPerSet + 2];
}

- (instancetype)initWithContext:(GlContextType *)context {
  if (self = [super init]) {
    _hasUnpackRowLength = (context.API == kEAGLRenderingAPIOpenGLES3);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    [self setupTextures];
  }
  return self;
}

- (void)dealloc {
  glDeleteTextures(kNumTextures, _textures);
}

- (void)setupTextures {
  glGenTextures(kNumTextures, _textures);
  // Set parameters for each of the textures we created.
  for (GLsizei i = 0; i < kNumTextures; i++) {
    glBindTexture(GL_TEXTURE_2D, _textures[i]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  }
}

- (void)uploadPlane:(const uint8_t *)plane
            texture:(GLuint)texture
              width:(size_t)width
             height:(size_t)height
             stride:(int32_t)stride {
  glBindTexture(GL_TEXTURE_2D, texture);

  const uint8_t *uploadPlane = plane;
  if ((size_t)stride != width) {
   if (_hasUnpackRowLength) {
      // GLES3 allows us to specify stride.
      glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
      glTexImage2D(GL_TEXTURE_2D,
                   0,
                   RTC_PIXEL_FORMAT,
                   static_cast<GLsizei>(width),
                   static_cast<GLsizei>(height),
                   0,
                   RTC_PIXEL_FORMAT,
                   GL_UNSIGNED_BYTE,
                   uploadPlane);
      glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
      return;
    } else {
      // Make an unpadded copy and upload that instead. Quick profiling showed
      // that this is faster than uploading row by row using glTexSubImage2D.
      uint8_t *unpaddedPlane = _planeBuffer.data();
      for (size_t y = 0; y < height; ++y) {
        memcpy(unpaddedPlane + y * width, plane + y * stride, width);
      }
      uploadPlane = unpaddedPlane;
    }
  }
  glTexImage2D(GL_TEXTURE_2D,
               0,
               RTC_PIXEL_FORMAT,
               static_cast<GLsizei>(width),
               static_cast<GLsizei>(height),
               0,
               RTC_PIXEL_FORMAT,
               GL_UNSIGNED_BYTE,
               uploadPlane);
}

- (void)uploadFrameToTextures:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
  _currentTextureSet = (_currentTextureSet + 1) % kNumTextureSets;

  id<RTC_OBJC_TYPE(RTCI420Buffer)> buffer = [frame.buffer toI420];

  const int chromaWidth = buffer.chromaWidth;
  const int chromaHeight = buffer.chromaHeight;
  if (buffer.strideY != frame.width || buffer.strideU != chromaWidth ||
      buffer.strideV != chromaWidth) {
    _planeBuffer.resize(buffer.width * buffer.height);
  }

  [self uploadPlane:buffer.dataY
            texture:self.yTexture
              width:buffer.width
             height:buffer.height
             stride:buffer.strideY];

  [self uploadPlane:buffer.dataU
            texture:self.uTexture
              width:chromaWidth
             height:chromaHeight
             stride:buffer.strideU];

  [self uploadPlane:buffer.dataV
            texture:self.vTexture
              width:chromaWidth
             height:chromaHeight
             stride:buffer.strideV];
}

@end
