// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/renderbuffer_manager.h"

#include <stddef.h>
#include <stdint.h>

#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/decoder_context.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/trace_util.h"

namespace gpu {
namespace gles2 {

// This should contain everything to uniquely identify a Renderbuffer.
static const char RenderbufferTag[] = "|Renderbuffer|";
struct RenderbufferSignature {
  GLenum internal_format_;
  GLsizei samples_;
  GLsizei width_;
  GLsizei height_;

  // Since we will be hashing this signature structure, the padding must be
  // zero initialized. Although the C++11 specifications specify that this is
  // true, we will use a constructor with a memset to further enforce it instead
  // of relying on compilers adhering to this deep dark corner specification.
  RenderbufferSignature(GLenum internal_format,
                        GLsizei samples,
                        GLsizei width,
                        GLsizei height) {
    UNSAFE_TODO(memset(this, 0, sizeof(RenderbufferSignature)));
    internal_format_ = internal_format;
    samples_ = samples;
    width_ = width;
    height_ = height;
  }
};

RenderbufferManager::RenderbufferManager(
    scoped_refptr<MemoryTracker> memory_tracker,
    GLint max_renderbuffer_size,
    GLint max_samples,
    FeatureInfo* feature_info)
    : memory_type_tracker_(new MemoryTypeTracker(std::move(memory_tracker))),
      max_renderbuffer_size_(max_renderbuffer_size),
      max_samples_(max_samples),
      feature_info_(feature_info),
      num_uncleared_renderbuffers_(0),
      renderbuffer_count_(0),
      have_context_(true) {
  // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
  // so don't register a dump provider.
  if (memory_type_tracker_->memory_tracker()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "gpu::RenderbufferManager",
        base::SingleThreadTaskRunner::GetCurrentDefault());
  }
}

RenderbufferManager::~RenderbufferManager() {
  DCHECK(renderbuffers_.empty());
  // If this triggers, that means something is keeping a reference to
  // a Renderbuffer belonging to this.
  CHECK_EQ(renderbuffer_count_, 0u);

  DCHECK_EQ(0, num_uncleared_renderbuffers_);

  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

size_t Renderbuffer::EstimatedSize() {
  uint32_t size = 0;
  manager_->ComputeEstimatedRenderbufferSize(
      width_, height_, samples_, internal_format_, &size);
  return size;
}


size_t Renderbuffer::GetSignatureSize() const {
  return sizeof(RenderbufferTag) + sizeof(RenderbufferSignature);
}

void Renderbuffer::SetInfoAndInvalidate(GLsizei samples,
                                        GLenum internalformat,
                                        GLsizei width,
                                        GLsizei height) {
  samples_ = samples;
  internal_format_ = internalformat;
  width_ = width;
  height_ = height;
  cleared_ = false;
  allocated_ = true;
  for (auto& point : framebuffer_attachment_points_) {
    point.first->UnmarkAsComplete();
  }
}

void Renderbuffer::SetAllocationFailed() {
  samples_ = 1;
  internal_format_ = 0x0;
  width_ = 0;
  height_ = 0;
  cleared_ = false;
  allocated_ = false;
  for (auto& point : framebuffer_attachment_points_) {
    point.first->UnmarkAsComplete();
  }
}

void Renderbuffer::AddToSignature(std::string* signature) const {
  DCHECK(signature);
  RenderbufferSignature signature_data(internal_format_,
                                       samples_,
                                       width_,
                                       height_);

  signature->append(RenderbufferTag, sizeof(RenderbufferTag));
  signature->append(reinterpret_cast<const char*>(&signature_data),
                    sizeof(signature_data));
}

Renderbuffer::Renderbuffer(RenderbufferManager* manager,
                           GLuint client_id,
                           GLuint service_id)
    : manager_(manager),
      client_id_(client_id),
      service_id_(service_id),
      cleared_(true),
      allocated_(false),
      has_been_bound_(false),
      samples_(0),
      internal_format_(GL_RGBA4),
      width_(0),
      height_(0) {
  manager_->StartTracking(this);
}

bool Renderbuffer::RegenerateAndBindBackingObjectIfNeeded(
    const DecoderContext* decoder,
    const GpuDriverBugWorkarounds& workarounds) {
  bool multisample_workaround =
      workarounds.multisample_renderbuffer_resize_emulation;
  if (!multisample_workaround) {
    return false;
  }

  if (!allocated_ || !has_been_bound_) {
    return false;
  }

  bool workaround_needed = (multisample_workaround && samples_ > 0);
  if (!workaround_needed) {
    return false;
  }

  GLint original_fbo = 0;
  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &original_fbo);

  glDeleteRenderbuffersEXT(1, &service_id_);
  service_id_ = 0;
  glGenRenderbuffersEXT(1, &service_id_);
  glBindRenderbufferEXT(GL_RENDERBUFFER, service_id_);

  // Attach new renderbuffer to all framebuffers
  for (auto& point : framebuffer_attachment_points_) {
    decoder->BindFramebuffer(GL_DRAW_FRAMEBUFFER, point.first->service_id());
    glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER, point.second,
                                 GL_RENDERBUFFER, service_id_);
  }

  glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, original_fbo);

  allocated_ = false;
  return true;
}

void Renderbuffer::AddFramebufferAttachmentPoint(Framebuffer* framebuffer,
                                                 GLenum attachment) {
  DCHECK_NE(static_cast<GLenum>(GL_DEPTH_STENCIL_ATTACHMENT), attachment);
  framebuffer_attachment_points_.insert(
      std::make_pair(framebuffer, attachment));
}

void Renderbuffer::RemoveFramebufferAttachmentPoint(Framebuffer* framebuffer,
                                                    GLenum attachment) {
  DCHECK_NE(static_cast<GLenum>(GL_DEPTH_STENCIL_ATTACHMENT), attachment);
  framebuffer_attachment_points_.erase(std::make_pair(framebuffer, attachment));
}

Renderbuffer::~Renderbuffer() {
  if (manager_) {
    if (manager_->have_context_) {
      GLuint id = service_id();
      glDeleteRenderbuffersEXT(1, &id);
    }
    manager_->StopTracking(this);
    manager_ = nullptr;
  }
}

void RenderbufferManager::Destroy(bool have_context) {
  have_context_ = have_context;
  renderbuffers_.clear();
  DCHECK_EQ(0u, memory_type_tracker_->GetMemRepresented());
}

void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) {
  ++renderbuffer_count_;
}

void RenderbufferManager::StopTracking(Renderbuffer* renderbuffer) {
  --renderbuffer_count_;
  if (!renderbuffer->cleared()) {
    --num_uncleared_renderbuffers_;
  }
  memory_type_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
}

void RenderbufferManager::SetInfoAndInvalidate(Renderbuffer* renderbuffer,
                                               GLsizei samples,
                                               GLenum internalformat,
                                               GLsizei width,
                                               GLsizei height) {
  DCHECK(renderbuffer);
  if (!renderbuffer->cleared()) {
    --num_uncleared_renderbuffers_;
  }
  memory_type_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
  renderbuffer->SetInfoAndInvalidate(samples, internalformat, width, height);
  memory_type_tracker_->TrackMemAlloc(renderbuffer->EstimatedSize());
  if (!renderbuffer->cleared()) {
    ++num_uncleared_renderbuffers_;
  }
}

void RenderbufferManager::SetAllocationFailed(Renderbuffer* renderbuffer) {
  DCHECK(renderbuffer);
  if (!renderbuffer->cleared()) {
    --num_uncleared_renderbuffers_;
  }
  memory_type_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
  renderbuffer->SetAllocationFailed();
  memory_type_tracker_->TrackMemAlloc(renderbuffer->EstimatedSize());
  if (!renderbuffer->cleared()) {
    ++num_uncleared_renderbuffers_;
  }
}

void RenderbufferManager::SetCleared(Renderbuffer* renderbuffer,
                                     bool cleared) {
  DCHECK(renderbuffer);
  if (!renderbuffer->cleared()) {
    --num_uncleared_renderbuffers_;
  }
  renderbuffer->set_cleared(cleared);
  if (!renderbuffer->cleared()) {
    ++num_uncleared_renderbuffers_;
  }
}

void RenderbufferManager::CreateRenderbuffer(
    GLuint client_id, GLuint service_id) {
  auto renderbuffer =
      base::MakeRefCounted<Renderbuffer>(this, client_id, service_id);
  std::pair<RenderbufferMap::iterator, bool> result =
      renderbuffers_.insert(std::make_pair(client_id, renderbuffer));
  DCHECK(result.second);
  if (!renderbuffer->cleared()) {
    ++num_uncleared_renderbuffers_;
  }
}

Renderbuffer* RenderbufferManager::GetRenderbuffer(
    GLuint client_id) {
  RenderbufferMap::iterator it = renderbuffers_.find(client_id);
  return it != renderbuffers_.end() ? it->second.get() : nullptr;
}

void RenderbufferManager::RemoveRenderbuffer(GLuint client_id) {
  RenderbufferMap::iterator it = renderbuffers_.find(client_id);
  if (it != renderbuffers_.end()) {
    Renderbuffer* renderbuffer = it->second.get();
    renderbuffer->MarkAsDeleted();
    renderbuffers_.erase(it);
  }
}

bool RenderbufferManager::ComputeEstimatedRenderbufferSize(
    int width,
    int height,
    int samples,
    int internal_format,
    uint32_t* size) const {
  DCHECK(size);
  GLenum impl_format = InternalRenderbufferFormatToImplFormat(internal_format);
  uint32_t bytes_per_pixel = GLES2Util::RenderbufferBytesPerPixel(impl_format);
  base::CheckedNumeric<uint32_t> checked_size = width;
  checked_size *= height;
  checked_size *= (samples == 0 ? 1 : samples);
  checked_size *= bytes_per_pixel;
  return checked_size.AssignIfValid(size);
}

GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat(
    GLenum impl_format) const {
  // Upgrade 16-bit depth to 24-bit if possible.
  if (impl_format == GL_DEPTH_COMPONENT16 &&
      feature_info_->feature_flags().oes_depth24) {
    return GL_DEPTH_COMPONENT24;
  }
  return impl_format;
}

bool RenderbufferManager::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  using base::trace_event::MemoryDumpLevelOfDetail;
  const uint64_t context_group_tracing_id =
      memory_type_tracker_->memory_tracker()
          ? memory_type_tracker_->memory_tracker()->ContextGroupTracingId()
          : 0;

  if (args.level_of_detail == MemoryDumpLevelOfDetail::kBackground) {
    std::string dump_name =
        base::StringPrintf("gpu/gl/renderbuffers/context_group_0x%" PRIX64,
                           context_group_tracing_id);
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes, mem_represented());

    // Early out, no need for more detail in a BACKGROUND dump.
    return true;
  }

  for (const auto& renderbuffer_entry : renderbuffers_) {
    const auto& client_renderbuffer_id = renderbuffer_entry.first;
    const auto& renderbuffer = renderbuffer_entry.second;

    std::string dump_name =
        base::StringPrintf("gpu/gl/renderbuffers/context_group_0x%" PRIX64
                           "/renderbuffer_0x%" PRIX32,
                           context_group_tracing_id, client_renderbuffer_id);
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes,
                    static_cast<uint64_t>(renderbuffer->EstimatedSize()));

    auto guid = gl::GetGLRenderbufferGUIDForTracing(context_group_tracing_id,
                                                    client_renderbuffer_id);
    pmd->CreateSharedGlobalAllocatorDump(guid);
    pmd->AddOwnershipEdge(dump->guid(), guid);
  }

  return true;
}

}  // namespace gles2
}  // namespace gpu
