// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm

__global__ void FUNCTION_NAME_7(warpKernel, mergerT, fromSphereToInput, isWithin, distortionMetersTransform, distortionPixelsTransform, PhotoCorrectionT)
           (global_mem uint32_t* g_odata, surface_t panoSurf, global_mem const unsigned char* mask,
           read_only image2d_t texture,
           int texWidth, int texHeight,
           int oWidth, int oHeight,
           int oOffsetX, int oOffsetY,
           int panoWidth, int panoHeight,
           int cropLeft, int cropRight, int cropTop, int cropBottom,
           const float2 panoScale,
           const vsfloat3x4 transform,
           const float2 inputScale,
           const vsDistortion distortion,
           const float2 centerShift,
           float3 rgbMult,
           float photoParam, const global_mem float* floatPtr,
           float vigCenterX, float vigCenterY,
           float inverseDemiDiagonalSquared,
           float vigCoeff0, float vigCoeff1, float vigCoeff2, float vigCoeff3
         ) {

  /* calculate normalized texture coordinates */
  const int x = get_global_id_x();
  const int y = get_global_id_y();
  const int panoX = (x + oOffsetX) % panoWidth;
  const int panoY = y + oOffsetY;
  const int srcIndex = oWidth * y + x;
  uint32_t p = 0;

  const lut_ptr float* lutPtr = FUNCTION_NAME_2(PhotoCorrectionT, setup)(floatPtr);
  if (x < oWidth && y < oHeight) {
    const bool isVisible = OutputRectCropper_isPanoPointVisible(panoX, panoY, panoWidth, panoHeight);
    if (isVisible) {

      float2 uv = make_float2((float)panoX, (float)panoY);

      /* compensate fetching offset by adding 0.5f */
      uv.x -= (panoWidth - 1) / 2.0f;
      uv.y -= (panoHeight - 1) / 2.0f;

      uv = FUNCTION_NAME_4(mapPanoramaToInput, fromSphereToInput, distortionMetersTransform, distortionPixelsTransform) (uv, panoScale, transform, inputScale, distortion, centerShift);

      uv.x += texWidth / 2.0f;
      uv.y += texHeight / 2.0f;

      p = FUNCTION_NAME_2(photoCorrectionFunction, PhotoCorrectionT)(uv, texture, texWidth, texHeight, rgbMult, photoParam, lutPtr, vigCenterX, vigCenterY, inverseDemiDiagonalSquared, vigCoeff0, vigCoeff1, vigCoeff2, vigCoeff3) *
                                isWithin(uv, (float)texWidth, (float)texHeight, (float)cropLeft, (float)cropRight, (float)cropTop, (float)cropBottom);
    }
    FUNCTION_NAME_1(mergerT)(isVisible, g_odata, panoSurf, p, mask, srcIndex, panoX, panoY, panoWidth);
  }
}