/*
* Copyright (c) 2016 - 2017, 2020-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*  * Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*  * Redistributions in binary form must reproduce the above
*    copyright notice, this list of conditions and the following
*    disclaimer in the documentation and/or other materials provided
*    with the distribution.
*  * Neither the name of The Linux Foundation nor the names of its
*    contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <QtiGralloc.h>
#include <sync/sync.h>

#include <TonemapFactory.h>

#include <core/buffer_allocator.h>

#include <utils/constants.h>
#include <utils/debug.h>
#include <utils/formats.h>
#include <utils/rect.h>
#include <utils/utils.h>

#include <vector>

#include "hwc_debugger.h"
#include "hwc_tonemapper.h"

#define __CLASS__ "HWCToneMapper"

namespace sdm {

ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator)
  : tone_map_task_(*this), buffer_allocator_(buffer_allocator) {
  buffer_info_.resize(kNumIntermediateBuffers);
}

ToneMapSession::~ToneMapSession() {
  tone_map_task_.PerformTask(ToneMapTaskCode::kCodeDestroy, nullptr);
  FreeIntermediateBuffers();
  buffer_info_.clear();
}

void ToneMapSession::OnTask(const ToneMapTaskCode &task_code,
                            SyncTask<ToneMapTaskCode>::TaskContext *task_context) {
  switch (task_code) {
#ifndef TARGET_HEADLESS
    case ToneMapTaskCode::kCodeGetInstance: {
        ToneMapGetInstanceContext *ctx = static_cast<ToneMapGetInstanceContext *>(task_context);
        Lut3d &lut_3d = ctx->layer->lut_3d;
        Color10Bit *grid_entries = NULL;
        int grid_size = 0;
        if (lut_3d.validGridEntries) {
          grid_entries = lut_3d.gridEntries;
          grid_size = INT(lut_3d.gridSize);
        }
        gpu_tone_mapper_ = TonemapperFactory_GetInstance(tone_map_config_.type,
                                                         lut_3d.lutEntries, lut_3d.dim,
                                                         grid_entries, grid_size,
                                                         tone_map_config_.secure);
      }
      break;

    case ToneMapTaskCode::kCodeBlit: {
        ToneMapBlitContext *ctx = static_cast<ToneMapBlitContext *>(task_context);
        uint8_t buffer_index = current_buffer_index_;
        const void *dst_hnd = reinterpret_cast<const void *>
                                (buffer_info_[buffer_index].private_data);
        const void *src_hnd = reinterpret_cast<const void *>
                                (ctx->layer->input_buffer.buffer_id);
        int fence = gpu_tone_mapper_->blit(dst_hnd, src_hnd, Fence::Dup(ctx->merged));
        ctx->fence = Fence::Create(fence, "tonemap");
      }
      break;

    case ToneMapTaskCode::kCodeDestroy: {
        delete gpu_tone_mapper_;
      }
      break;

#endif
    default:
      break;
  }
}

DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
    BufferInfo &buffer_info = buffer_info_[i];
    buffer_info.buffer_config.width = layer->request.width;
    buffer_info.buffer_config.height = layer->request.height;
    buffer_info.buffer_config.format = layer->request.format;
    buffer_info.buffer_config.secure = layer->request.flags.secure;
    buffer_info.buffer_config.gfx_client = true;
    int err = buffer_allocator_->AllocateBuffer(&buffer_info);
    if (err != 0) {
      FreeIntermediateBuffers();
      return kErrorUndefined;
    }
  }

  return kErrorNone;
}

void ToneMapSession::FreeIntermediateBuffers() {
  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
    BufferInfo &buffer_info = buffer_info_[i];
    if (buffer_info.private_data) {
      buffer_allocator_->FreeBuffer(&buffer_info);
    }
  }
}

void ToneMapSession::UpdateBuffer(const shared_ptr<Fence> &acquire_fence, LayerBuffer *buffer) {
  // Acquire fence will be closed by HWC Display.
  // Fence returned by GPU will be closed in PostCommit.
  buffer->acquire_fence = acquire_fence;
  buffer->size = buffer_info_[current_buffer_index_].alloc_buffer_info.size;
  buffer->planes[0].fd = buffer_info_[current_buffer_index_].alloc_buffer_info.fd;
  buffer->handle_id = buffer_info_[current_buffer_index_].alloc_buffer_info.id;
}

void ToneMapSession::SetReleaseFence(const shared_ptr<Fence> &fd) {
  release_fence_[current_buffer_index_] = fd;
}

void ToneMapSession::SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
  // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
  tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
  tone_map_config_.blend_cs = blend_cs;
  tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
  tone_map_config_.secure = layer->request.flags.secure;
  tone_map_config_.format = layer->request.format;
}

bool ToneMapSession::IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
  LayerBuffer& buffer = layer->input_buffer;
  native_handle_t *handle = static_cast<native_handle_t *>(buffer_info_[0].private_data);
  int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;

  uint32_t handle_unaligned_width, handle_unaligned_height = 0;
  buffer_allocator_->GetUnalignedWidth(handle, handle_unaligned_width);
  buffer_allocator_->GetUnalignedHeight(handle, handle_unaligned_height);
  return ((tonemap_type == tone_map_config_.type) && (blend_cs == tone_map_config_.blend_cs) &&
          (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
          (layer->request.flags.secure == tone_map_config_.secure) &&
          (layer->request.format == tone_map_config_.format) &&
          (layer->request.width == handle_unaligned_width) &&
          (layer->request.height == handle_unaligned_height));
}

int HWCToneMapper::HandleToneMap(LayerStack *layer_stack) {
  uint32_t gpu_count = 0;
  DisplayError error = kErrorNone;

  for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
    uint32_t session_index = 0;
    Layer *layer = layer_stack->layers.at(i);
    if (layer->composition == kCompositionGPU) {
      gpu_count++;
    }

    if (layer->request.flags.tone_map) {
      DLOGV_IF(kTagClient, "Tonemapping for layer at index %d", i);
      switch (layer->composition) {
      case kCompositionGPUTarget:
        if (!gpu_count) {
          // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
          // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
          // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
          // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
          if (!tone_map_sessions_.empty() && (fb_session_index_ >= 0)) {
            ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(UINT32(fb_session_index_));
            fb_tone_map_session->UpdateBuffer(nullptr /* acquire_fence */, &layer->input_buffer);
            fb_tone_map_session->layer_index_ = INT(i);
            fb_tone_map_session->acquired_ = true;
            return 0;
          }
        }
        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
        fb_session_index_ = INT(session_index);
        break;
      default:
        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
        break;
      }

      if (error != kErrorNone) {
        Terminate();
        return -1;
      }

      ToneMapSession *session = tone_map_sessions_.at(session_index);
      ToneMap(layer, session);
      DLOGI_IF(kTagClient, "Layer %d associated with session index %d", i, session_index);
      session->layer_index_ = INT(i);
    }
  }

  return 0;
}

void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
  ToneMapBlitContext ctx = {};
  ctx.layer = layer;

  uint8_t buffer_index = session->current_buffer_index_;

  // use and close the layer->input_buffer acquire fence fd.
  // remove create when rf made it as a shared_ptr
  ctx.merged = Fence::Merge(session->release_fence_[buffer_index],
                            layer->input_buffer.acquire_fence);

  DTRACE_BEGIN("GPU_TM_BLIT");
  session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeBlit, &ctx);
  DTRACE_END();

  DumpToneMapOutput(session, ctx.fence);
  session->UpdateBuffer(ctx.fence, &layer->input_buffer);
}

void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
  auto it = tone_map_sessions_.begin();
  while (it != tone_map_sessions_.end()) {
    uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
    ToneMapSession *session = tone_map_sessions_.at(session_index);
    if (session->acquired_) {
      Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
      // Close the fd returned by GPU ToneMapper and set release fence.
      LayerBuffer &layer_buffer = layer->input_buffer;
      session->SetReleaseFence(layer_buffer.release_fence);
      session->acquired_ = false;
      it++;
    } else {
      DLOGI_IF(kTagClient, "Tone map session %d closed.", session_index);
      delete session;
      it = tone_map_sessions_.erase(it);
      int deleted_session = INT(session_index);
      // If FB tonemap session gets deleted, reset fb_session_index_, else update it.
      if (deleted_session == fb_session_index_) {
        fb_session_index_ = -1;
      } else if (deleted_session < fb_session_index_) {
        fb_session_index_--;
      }
    }
  }
}

void HWCToneMapper::Terminate() {
  if (tone_map_sessions_.size()) {
    while (!tone_map_sessions_.empty()) {
      delete tone_map_sessions_.back();
      tone_map_sessions_.pop_back();
    }
    fb_session_index_ = -1;
  }
}

void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
  DLOGI("Dump FrameConfig count = %d", count);
  dump_frame_count_ = count;
  dump_frame_index_ = 0;
}

void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, shared_ptr<Fence> acquire_fd) {
  int error = -1;
  if (!dump_frame_count_) {
    return;
  }

  BufferInfo &buffer_info = session->buffer_info_[session->current_buffer_index_];
  native_handle_t *target_buffer = static_cast<native_handle_t *>(buffer_info.private_data);
  Fence::Wait(acquire_fd);

  void *base_ptr = NULL;
  error = buffer_allocator_->MapBuffer(target_buffer, acquire_fd, &base_ptr);
  if (error != 0) {
    DLOGE("MapBuffer failed, base addr = %p", base_ptr);
    return;
  }

  size_t result = 0;
  char dump_file_name[PATH_MAX];
  uint32_t width, height, size = 0;
  buffer_allocator_->GetWidth((void *)target_buffer, width);
  buffer_allocator_->GetHeight((void *)target_buffer, height);
  buffer_allocator_->GetAllocationSize((void *)target_buffer, size);

  snprintf(dump_file_name, sizeof(dump_file_name),
           "%s/frame_dump_primary"
           "/tonemap_%dx%d_frame%d.raw",
           HWCDebugHandler::DumpDir(), width, height, dump_frame_index_);

  if (base_ptr != nullptr) {
    FILE* fp = fopen(dump_file_name, "w+");
    if (fp) {
      DLOGI("base addr = %p", base_ptr);
      result = fwrite(base_ptr, size, 1, fp);
      fclose(fp);
    }
  }

  dump_frame_count_--;
  dump_frame_index_++;
}

DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index,
                                                  PrimariesTransfer blend_cs) {
  // When the property vendor.display.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
  // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
  // for Tonemapping.
  if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
    // Atleast lutEntries must be valid for GPU Tonemapper.
    DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
    return kErrorParameters;
  }

  // Check if we can re-use an existing tone map session.
  for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
    ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer, blend_cs)) {
      tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
                                                ToneMapSession::kNumIntermediateBuffers;
      tonemap_session->acquired_ = true;
      *session_index = i;
      return kErrorNone;
    }
  }

  ToneMapSession *session = new ToneMapSession(buffer_allocator_);
  if (!session) {
    return kErrorMemory;
  }

  session->SetToneMapConfig(layer, blend_cs);

  ToneMapGetInstanceContext ctx;
  ctx.layer = layer;
  session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeGetInstance, &ctx);

  if (session->gpu_tone_mapper_ == NULL) {
    DLOGE("Get Tonemapper failed!");
    delete session;
    return kErrorNotSupported;
  }
  DisplayError error = session->AllocateIntermediateBuffers(layer);
  if (error != kErrorNone) {
    DLOGE("Allocation of Intermediate Buffers failed!");
    delete session;
    return error;
  }

  session->acquired_ = true;
  tone_map_sessions_.push_back(session);
  *session_index = UINT32(tone_map_sessions_.size() - 1);

  return kErrorNone;
}

}  // namespace sdm
