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

#include "media/gpu/rendering_helper.h"

#include <string.h>

#include <algorithm>
#include <memory>
#include <numeric>
#include <vector>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringize_macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

#if defined(USE_X11)
#include "ui/gfx/x/x11_types.h"  // nogncheck
#endif

#if defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
#include "ui/gl/gl_surface_glx.h"
#define GL_VARIANT_GLX 1
#else
#include "ui/gl/gl_surface_egl.h"
#define GL_VARIANT_EGL 1
#endif

#if defined(USE_OZONE)
#if defined(OS_CHROMEOS)
#include "ui/display/manager/chromeos/display_configurator.h"
#include "ui/display/types/native_display_delegate.h"
#endif  // defined(OS_CHROMEOS)
#include "ui/ozone/public/ozone_platform.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
#endif  // defined(USE_OZONE)

// Helper for Shader creation.
static void CreateShader(GLuint program,
                         GLenum type,
                         const char* source,
                         int size) {
  GLuint shader = glCreateShader(type);
  glShaderSource(shader, 1, &source, &size);
  glCompileShader(shader);
  int result = GL_FALSE;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
  if (!result) {
    char log[4096];
    glGetShaderInfoLog(shader, arraysize(log), NULL, log);
    LOG(FATAL) << log;
  }
  glAttachShader(program, shader);
  glDeleteShader(shader);
  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}

namespace media {
namespace {

void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) {
  callback.Run();
}

}  // namespace

#if defined(USE_OZONE)

class DisplayConfiguratorObserver
    : public display::DisplayConfigurator::Observer {
 public:
  explicit DisplayConfiguratorObserver(base::RunLoop* loop) : loop_(loop) {}
  ~DisplayConfiguratorObserver() override {}

 private:
  // display::DisplayConfigurator::Observer overrides:
  void OnDisplayModeChanged(
      const display::DisplayConfigurator::DisplayStateList& outputs) override {
    if (!loop_)
      return;
    loop_->Quit();
    loop_ = nullptr;
  }
  void OnDisplayModeChangeFailed(
      const display::DisplayConfigurator::DisplayStateList& outputs,
      display::MultipleDisplayState failed_new_state) override {
    LOG(FATAL) << "Could not configure display";
  }

  base::RunLoop* loop_;

  DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorObserver);
};

class RenderingHelper::StubOzoneDelegate : public ui::PlatformWindowDelegate {
 public:
  StubOzoneDelegate() : accelerated_widget_(gfx::kNullAcceleratedWidget) {
    platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow(
        this, gfx::Rect());
  }
  ~StubOzoneDelegate() override {}

  void OnBoundsChanged(const gfx::Rect& new_bounds) override {}

  void OnDamageRect(const gfx::Rect& damaged_region) override {}

  void DispatchEvent(ui::Event* event) override {}

  void OnCloseRequest() override {}
  void OnClosed() override {}

  void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}

  void OnLostCapture() override {}

  void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
                                    float device_pixel_ratio) override {
    accelerated_widget_ = widget;
  }

  void OnAcceleratedWidgetDestroyed() override { NOTREACHED(); }

  void OnActivationChanged(bool active) override {}

  gfx::AcceleratedWidget accelerated_widget() const {
    return accelerated_widget_;
  }

  gfx::Size GetSize() { return platform_window_->GetBounds().size(); }

  ui::PlatformWindow* platform_window() const { return platform_window_.get(); }

 private:
  std::unique_ptr<ui::PlatformWindow> platform_window_;
  gfx::AcceleratedWidget accelerated_widget_;

  DISALLOW_COPY_AND_ASSIGN(StubOzoneDelegate);
};

#endif  // defined(USE_OZONE)

RenderingHelperParams::RenderingHelperParams()
    : rendering_fps(0), warm_up_iterations(0), render_as_thumbnails(false) {}

RenderingHelperParams::RenderingHelperParams(
    const RenderingHelperParams& other) = default;

RenderingHelperParams::~RenderingHelperParams() {}

VideoFrameTexture::VideoFrameTexture(uint32_t texture_target,
                                     uint32_t texture_id,
                                     const base::Closure& no_longer_needed_cb)
    : texture_target_(texture_target),
      texture_id_(texture_id),
      no_longer_needed_cb_(no_longer_needed_cb) {
  DCHECK(!no_longer_needed_cb_.is_null());
}

VideoFrameTexture::~VideoFrameTexture() {
  base::ResetAndReturn(&no_longer_needed_cb_).Run();
}

RenderingHelper::RenderedVideo::RenderedVideo()
    : is_flushing(false), frames_to_drop(0) {}

RenderingHelper::RenderedVideo::RenderedVideo(const RenderedVideo& other) =
    default;

RenderingHelper::RenderedVideo::~RenderedVideo() {}

// static
void RenderingHelper::InitializeOneOff(base::WaitableEvent* done) {
  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
#if GL_VARIANT_GLX
  cmd_line->AppendSwitchASCII(switches::kUseGL,
                              gl::kGLImplementationDesktopName);
#else
  cmd_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationEGLName);
#endif

#if defined(USE_OZONE)
  ui::OzonePlatform::InitParams params;
  params.single_process = true;
  ui::OzonePlatform::InitializeForGPU(params);
#endif

  if (!gl::init::InitializeGLOneOff())
    LOG(FATAL) << "Could not initialize GL";
  done->Signal();
}

RenderingHelper::RenderingHelper() : ignore_vsync_(false) {
  window_ = gfx::kNullAcceleratedWidget;
  Clear();
}

RenderingHelper::~RenderingHelper() {
  CHECK_EQ(videos_.size(), 0U) << "Must call UnInitialize before dtor.";
  Clear();
}

void RenderingHelper::Setup() {
#if defined(USE_X11)
  Display* display = gfx::GetXDisplay();
  Screen* screen = DefaultScreenOfDisplay(display);

  CHECK(display);

  XSetWindowAttributes window_attributes;
  memset(&window_attributes, 0, sizeof(window_attributes));
  window_attributes.background_pixel =
      BlackPixel(display, DefaultScreen(display));
  window_attributes.override_redirect = true;
  int depth = DefaultDepth(display, DefaultScreen(display));

  window_ = XCreateWindow(display,
                          DefaultRootWindow(display),
                          0, 0,
                          XWidthOfScreen(screen),
                          XHeightOfScreen(screen),
                          0 /* border width */,
                          depth,
                          CopyFromParent /* class */,
                          CopyFromParent /* visual */,
                          (CWBackPixel | CWOverrideRedirect),
                          &window_attributes);
  XStoreName(display, window_, "VideoDecodeAcceleratorTest");
  XSelectInput(display, window_, ExposureMask);
  XMapWindow(display, window_);
#elif defined(USE_OZONE)
  base::MessageLoop::ScopedNestableTaskAllower nest_loop(
      base::MessageLoop::current());
  base::RunLoop wait_window_resize;

  platform_window_delegate_.reset(new RenderingHelper::StubOzoneDelegate());
  window_ = platform_window_delegate_->accelerated_widget();
  gfx::Size window_size(800, 600);
  // Ignore the vsync provider by default. On ChromeOS this will be set
  // accordingly based on the display configuration.
  ignore_vsync_ = true;
#if defined(OS_CHROMEOS)
  // We hold onto the main loop here to wait for the DisplayController
  // to give us the size of the display so we can create a window of
  // the same size.
  base::RunLoop wait_display_setup;
  DisplayConfiguratorObserver display_setup_observer(&wait_display_setup);
  display_configurator_.reset(new display::DisplayConfigurator());
  display_configurator_->SetDelegateForTesting(0);
  display_configurator_->AddObserver(&display_setup_observer);
  display_configurator_->Init(
      ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate(), true);
  display_configurator_->ForceInitialConfigure(0);
  // Make sure all the display configuration is applied.
  wait_display_setup.Run();
  display_configurator_->RemoveObserver(&display_setup_observer);

  gfx::Size framebuffer_size = display_configurator_->framebuffer_size();
  if (!framebuffer_size.IsEmpty()) {
    window_size = framebuffer_size;
    ignore_vsync_ = false;
  }
#endif
  if (ignore_vsync_)
    DVLOG(1) << "Ignoring vsync provider";

  platform_window_delegate_->platform_window()->SetBounds(
      gfx::Rect(window_size));

  // On Ozone/DRI, platform windows are associated with the physical
  // outputs. Association is achieved by matching the bounds of the
  // window with the origin & modeset of the display output. Until a
  // window is associated with a display output, we cannot get vsync
  // events, because there is no hardware to get events from. Here we
  // wait for the window to resized and therefore associated with
  // display output to be sure that we will get such events.
  wait_window_resize.RunUntilIdle();
#elif !defined(OS_WIN)
#error unknown platform
#endif
}

void RenderingHelper::TearDown() {
#if defined(USE_X11)
  // Destroy resources acquired in Initialize, in reverse-acquisition order.
  if (window_) {
    CHECK(XUnmapWindow(gfx::GetXDisplay(), window_));
    CHECK(XDestroyWindow(gfx::GetXDisplay(), window_));
  }
#elif defined(USE_OZONE)
  platform_window_delegate_.reset();
#if defined(OS_CHROMEOS)
  display_configurator_->PrepareForExit();
  display_configurator_.reset();
#endif
#endif
  window_ = gfx::kNullAcceleratedWidget;
}

void RenderingHelper::Initialize(const RenderingHelperParams& params,
                                 base::WaitableEvent* done) {
#if defined(OS_WIN)
  window_ = CreateWindowEx(
      0, L"Static", L"VideoDecodeAcceleratorTest",
      WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, GetSystemMetrics(SM_CXSCREEN),
      GetSystemMetrics(SM_CYSCREEN), NULL, NULL, NULL, NULL);
#endif
  CHECK(window_ != gfx::kNullAcceleratedWidget);
  // Use videos_.size() != 0 as a proxy for the class having already been
  // Initialize()'d, and UnInitialize() before continuing.
  if (videos_.size()) {
    base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
    UnInitialize(&done);
    done.Wait();
  }

  render_task_.Reset(
      base::Bind(&RenderingHelper::RenderContent, base::Unretained(this)));

  frame_duration_ = params.rendering_fps > 0
                        ? base::TimeDelta::FromSeconds(1) / params.rendering_fps
                        : base::TimeDelta();

  render_as_thumbnails_ = params.render_as_thumbnails;
  task_runner_ = base::ThreadTaskRunnerHandle::Get();

  gl_surface_ = gl::init::CreateViewGLSurface(window_);
#if defined(USE_OZONE)
  gl_surface_->Resize(platform_window_delegate_->GetSize(), 1.f,
                      gl::GLSurface::ColorSpace::UNSPECIFIED, true);
#endif  // defined(USE_OZONE)
  screen_size_ = gl_surface_->GetSize();

  gl_context_ = gl::init::CreateGLContext(nullptr, gl_surface_.get(),
                                          gl::GLContextAttribs());
  CHECK(gl_context_->MakeCurrent(gl_surface_.get()));

  CHECK_GT(params.window_sizes.size(), 0U);
  videos_.resize(params.window_sizes.size());
  LayoutRenderingAreas(params.window_sizes);

  if (render_as_thumbnails_) {
    CHECK_EQ(videos_.size(), 1U);

    GLint max_texture_size;
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
    CHECK_GE(max_texture_size, params.thumbnails_page_size.width());
    CHECK_GE(max_texture_size, params.thumbnails_page_size.height());

    thumbnails_fbo_size_ = params.thumbnails_page_size;
    thumbnail_size_ = params.thumbnail_size;

    glGenFramebuffersEXT(1, &thumbnails_fbo_id_);
    glGenTextures(1, &thumbnails_texture_id_);
    glBindTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGB,
                 thumbnails_fbo_size_.width(), thumbnails_fbo_size_.height(),
                 0,
                 GL_RGB,
                 GL_UNSIGNED_SHORT_5_6_5,
                 NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);

    glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                              GL_TEXTURE_2D, thumbnails_texture_id_, 0);

    GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
    CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status;
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindFramebufferEXT(GL_FRAMEBUFFER,
                         gl_surface_->GetBackingFramebufferObject());
  }

  // These vertices and texture coords. map (0,0) in the texture to the
  // bottom left of the viewport.  Since we get the video frames with the
  // the top left at (0,0) we need to flip the texture y coordinate
  // in the vertex shader for this to be rendered the right way up.
  // In the case of thumbnail rendering we use the same vertex shader
  // to render the FBO the screen, where we do not want this flipping.
  // Vertices are 2 floats for position and 2 floats for texcoord each.
  static const float kVertices[] = {
      -1, 1,  0, 1,  // Vertex 0
      -1, -1, 0, 0,  // Vertex 1
      1,  1,  1, 1,  // Vertex 2
      1,  -1, 1, 0,  // Vertex 3
  };
  static const GLvoid* kVertexPositionOffset = 0;
  static const GLvoid* kVertexTexcoordOffset =
      reinterpret_cast<GLvoid*>(sizeof(float) * 2);
  static const GLsizei kVertexStride = sizeof(float) * 4;

  glGenBuffersARB(1, &vertex_buffer_);
  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
  glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);

  static const char kVertexShader[] =
      STRINGIZE(varying vec2 interp_tc; attribute vec4 in_pos;
                attribute vec2 in_tc; uniform bool tex_flip; void main() {
                  if (tex_flip)
                    interp_tc = vec2(in_tc.x, 1.0 - in_tc.y);
                  else
                    interp_tc = in_tc;
                  gl_Position = in_pos;
                });

#if GL_VARIANT_EGL && !defined(OS_WIN)
  static const char kFragmentShader[] =
      "#extension GL_OES_EGL_image_external : enable\n"
      "precision mediump float;\n"
      "varying vec2 interp_tc;\n"
      "uniform sampler2D tex;\n"
      "#ifdef GL_OES_EGL_image_external\n"
      "uniform samplerExternalOES tex_external;\n"
      "#endif\n"
      "void main() {\n"
      "  vec4 color = texture2D(tex, interp_tc);\n"
      "#ifdef GL_OES_EGL_image_external\n"
      "  color += texture2D(tex_external, interp_tc);\n"
      "#endif\n"
      "  gl_FragColor = color;\n"
      "}\n";
#else
  static const char kFragmentShader[] =
      "#ifdef GL_ES\n"
      "precision mediump float;\n"
      "#endif\n"
      "varying vec2 interp_tc;\n"
      "uniform sampler2D tex;\n"
      "void main() {\n"
      "  gl_FragColor = texture2D(tex, interp_tc);\n"
      "}\n";
#endif
  program_ = glCreateProgram();
  CreateShader(program_, GL_VERTEX_SHADER, kVertexShader,
               arraysize(kVertexShader));
  CreateShader(program_, GL_FRAGMENT_SHADER, kFragmentShader,
               arraysize(kFragmentShader));
  glLinkProgram(program_);
  int result = GL_FALSE;
  glGetProgramiv(program_, GL_LINK_STATUS, &result);
  if (!result) {
    char log[4096];
    glGetShaderInfoLog(program_, arraysize(log), NULL, log);
    LOG(FATAL) << log;
  }
  glUseProgram(program_);
  glDeleteProgram(program_);

  glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0);
  glUniform1i(glGetUniformLocation(program_, "tex"), 0);
  GLint tex_external = glGetUniformLocation(program_, "tex_external");
  if (tex_external != -1) {
    glUniform1i(tex_external, 1);
  }
  int pos_location = glGetAttribLocation(program_, "in_pos");
  glEnableVertexAttribArray(pos_location);
  glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, kVertexStride,
                        kVertexPositionOffset);
  int tc_location = glGetAttribLocation(program_, "in_tc");
  glEnableVertexAttribArray(tc_location);
  glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, kVertexStride,
                        kVertexTexcoordOffset);

  // Unbind the vertex buffer
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  if (!frame_duration_.is_zero()) {
    int warm_up_iterations = params.warm_up_iterations;
#if defined(USE_OZONE)
    // On Ozone the VSyncProvider can't provide a vsync interval until
    // we render at least a frame, so we warm up with at least one
    // frame.
    // On top of this, we want to make sure all the buffers backing
    // the GL surface are cleared, otherwise we can see the previous
    // test's last frames, so we set warm up iterations to 2, to clear
    // the front and back buffers.
    warm_up_iterations = std::max(2, warm_up_iterations);
#endif
    WarmUpRendering(warm_up_iterations);
  }

  // It's safe to use Unretained here since |rendering_thread_| will be stopped
  // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is
  // a member of that class. (See video_decode_accelerator_unittest.cc.)
  gfx::VSyncProvider* vsync_provider = gl_surface_->GetVSyncProvider();

  // VSync providers rely on the underlying CRTC to get the timing. In headless
  // mode the surface isn't associated with a CRTC so the vsync provider can not
  // get the timing, meaning it will not call UpdateVsyncParameters() ever.
  if (!ignore_vsync_ && vsync_provider && !frame_duration_.is_zero()) {
    vsync_provider->GetVSyncParameters(base::Bind(
        &RenderingHelper::UpdateVSyncParameters, base::Unretained(this), done));
  } else {
    done->Signal();
  }
}

// The rendering for the first few frames is slow (e.g., 100ms on Peach Pit).
// This affects the numbers measured in the performance test. We try to render
// several frames here to warm up the rendering.
void RenderingHelper::WarmUpRendering(int warm_up_iterations) {
  unsigned int texture_id;
  std::unique_ptr<GLubyte[]> emptyData(
      new GLubyte[screen_size_.GetArea() * 2]());
  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  glTexImage2D(GL_TEXTURE_2D,
               0,
               GL_RGB,
               screen_size_.width(), screen_size_.height(),
               0,
               GL_RGB,
               GL_UNSIGNED_SHORT_5_6_5,
               emptyData.get());
  for (int i = 0; i < warm_up_iterations; ++i) {
    RenderTexture(GL_TEXTURE_2D, texture_id);

    // Need to allow nestable tasks since WarmUpRendering() is called from
    // within another task on the renderer thread.
    base::MessageLoop::ScopedNestableTaskAllower allow(
        base::MessageLoop::current());
    base::RunLoop wait_for_swap_ack;
    if (gl_surface_->SupportsAsyncSwap()) {
      gl_surface_->SwapBuffersAsync(
          base::Bind(&WaitForSwapAck, wait_for_swap_ack.QuitClosure()));
      wait_for_swap_ack.Run();
    } else {
      gl_surface_->SwapBuffers();
    }
  }
  glDeleteTextures(1, &texture_id);
}

void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
  CHECK(task_runner_->BelongsToCurrentThread());

  render_task_.Cancel();

  if (render_as_thumbnails_) {
    glDeleteTextures(1, &thumbnails_texture_id_);
    glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_);
  }

  glDeleteBuffersARB(1, &vertex_buffer_);

  gl_context_->ReleaseCurrent(gl_surface_.get());
  gl_context_ = NULL;
  gl_surface_ = NULL;

  Clear();

#if defined(OS_WIN)
  if (window_)
    DestroyWindow(window_);
  window_ = gfx::kNullAcceleratedWidget;
#endif

  done->Signal();
}

void RenderingHelper::CreateTexture(uint32_t texture_target,
                                    uint32_t* texture_id,
                                    const gfx::Size& size,
                                    base::WaitableEvent* done) {
  if (!task_runner_->BelongsToCurrentThread()) {
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this),
                   texture_target, texture_id, size, done));
    return;
  }
  glGenTextures(1, texture_id);
  glBindTexture(texture_target, *texture_id);
  if (texture_target == GL_TEXTURE_2D) {
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGBA,
                 size.width(), size.height(),
                 0,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 NULL);
  }
  glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures.
  glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
  done->Signal();
}

// Helper function to set GL viewport.
static inline void GLSetViewPort(const gfx::Rect& area) {
  glViewport(area.x(), area.y(), area.width(), area.height());
  glScissor(area.x(), area.y(), area.width(), area.height());
}

void RenderingHelper::RenderThumbnail(uint32_t texture_target,
                                      uint32_t texture_id) {
  CHECK(task_runner_->BelongsToCurrentThread());
  const int width = thumbnail_size_.width();
  const int height = thumbnail_size_.height();
  const int thumbnails_in_row = thumbnails_fbo_size_.width() / width;
  const int thumbnails_in_column = thumbnails_fbo_size_.height() / height;
  const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column;
  const int col = frame_count_ % thumbnails_in_row;

  gfx::Rect area(col * width, row * height, width, height);

  glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0);
  glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
  GLSetViewPort(area);
  RenderTexture(texture_target, texture_id);
  glBindFramebufferEXT(GL_FRAMEBUFFER,
                       gl_surface_->GetBackingFramebufferObject());

  // Need to flush the GL commands before we return the tnumbnail texture to
  // the decoder.
  glFlush();
  ++frame_count_;
}

void RenderingHelper::QueueVideoFrame(
    size_t window_id,
    scoped_refptr<VideoFrameTexture> video_frame) {
  CHECK(task_runner_->BelongsToCurrentThread());
  RenderedVideo* video = &videos_[window_id];
  DCHECK(!video->is_flushing);

  video->pending_frames.push(video_frame);

  if (video->frames_to_drop > 0 && video->pending_frames.size() > 1) {
    --video->frames_to_drop;
    video->pending_frames.pop();
  }

  // Schedules the first RenderContent() if need.
  if (scheduled_render_time_.is_null()) {
    scheduled_render_time_ = base::TimeTicks::Now();
    task_runner_->PostTask(FROM_HERE, render_task_.callback());
  }
}

void RenderingHelper::RenderTexture(uint32_t texture_target,
                                    uint32_t texture_id) {
  // The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler
  // is bound to GL_TEXTURE0.
  if (texture_target == GL_TEXTURE_2D) {
    glActiveTexture(GL_TEXTURE0 + 0);
  } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
    glActiveTexture(GL_TEXTURE0 + 1);
  }
  glBindTexture(texture_target, texture_id);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  glBindTexture(texture_target, 0);
  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}

void RenderingHelper::DeleteTexture(uint32_t texture_id) {
  CHECK(task_runner_->BelongsToCurrentThread());
  glDeleteTextures(1, &texture_id);
  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}

gl::GLContext* RenderingHelper::GetGLContext() {
  return gl_context_.get();
}

void* RenderingHelper::GetGLDisplay() {
  return gl_surface_->GetDisplay();
}

void RenderingHelper::Clear() {
  videos_.clear();
  task_runner_ = nullptr;
  gl_context_ = NULL;
  gl_surface_ = NULL;

  render_as_thumbnails_ = false;
  frame_count_ = 0;
  thumbnails_fbo_id_ = 0;
  thumbnails_texture_id_ = 0;
}

void RenderingHelper::GetThumbnailsAsRGBA(std::vector<unsigned char>* rgba,
                                          base::WaitableEvent* done) {
  CHECK(render_as_thumbnails_);

  const size_t num_pixels = thumbnails_fbo_size_.GetArea();
  rgba->resize(num_pixels * 4);
  glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
  glPixelStorei(GL_PACK_ALIGNMENT, 1);
  // We can only count on GL_RGBA/GL_UNSIGNED_BYTE support.
  glReadPixels(0, 0, thumbnails_fbo_size_.width(),
               thumbnails_fbo_size_.height(), GL_RGBA, GL_UNSIGNED_BYTE,
               &(*rgba)[0]);
  glBindFramebufferEXT(GL_FRAMEBUFFER,
                       gl_surface_->GetBackingFramebufferObject());

  done->Signal();
}

void RenderingHelper::Flush(size_t window_id) {
  videos_[window_id].is_flushing = true;
}

void RenderingHelper::RenderContent() {
  CHECK(task_runner_->BelongsToCurrentThread());

  // Update the VSync params.
  //
  // It's safe to use Unretained here since |rendering_thread_| will be stopped
  // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is
  // a member of that class. (See video_decode_accelerator_unittest.cc.)
  gfx::VSyncProvider* vsync_provider = gl_surface_->GetVSyncProvider();
  if (vsync_provider && !ignore_vsync_) {
    vsync_provider->GetVSyncParameters(base::Bind(
        &RenderingHelper::UpdateVSyncParameters, base::Unretained(this),
        static_cast<base::WaitableEvent*>(NULL)));
  }

  int tex_flip = !gl_surface_->FlipsVertically();
#if defined(USE_OZONE)
  // Ozone surfaceless renders flipped from normal GL, so there's no need to
  // do an extra flip.
  tex_flip = 0;
#endif  // defined(USE_OZONE)
  glUniform1i(glGetUniformLocation(program_, "tex_flip"), tex_flip);

  // Frames that will be returned to the client (via the no_longer_needed_cb)
  // after this vector falls out of scope at the end of this method. We need
  // to keep references to them until after SwapBuffers() call below.
  std::vector<scoped_refptr<VideoFrameTexture>> frames_to_be_returned;
  bool need_swap_buffer = false;
  if (render_as_thumbnails_) {
    // In render_as_thumbnails_ mode, we render the FBO content on the
    // screen instead of the decoded textures.
    GLSetViewPort(videos_[0].render_area);
    RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
    need_swap_buffer = true;
  } else {
    for (RenderedVideo& video : videos_) {
      if (video.pending_frames.empty())
        continue;
      need_swap_buffer = true;
      scoped_refptr<VideoFrameTexture> frame = video.pending_frames.front();
      GLSetViewPort(video.render_area);
      RenderTexture(frame->texture_target(), frame->texture_id());

      if (video.pending_frames.size() > 1 || video.is_flushing) {
        frames_to_be_returned.push_back(video.pending_frames.front());
        video.pending_frames.pop();
      } else {
        ++video.frames_to_drop;
      }
    }
  }

  base::Closure schedule_frame = base::Bind(
      &RenderingHelper::ScheduleNextRenderContent, base::Unretained(this));
  if (!need_swap_buffer) {
    schedule_frame.Run();
    return;
  }

  if (gl_surface_->SupportsAsyncSwap()) {
    gl_surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, schedule_frame));
  } else {
    gl_surface_->SwapBuffers();
    ScheduleNextRenderContent();
  }
}

// Helper function for the LayoutRenderingAreas(). The |lengths| are the
// heights(widths) of the rows(columns). It scales the elements in
// |lengths| proportionally so that the sum of them equal to |total_length|.
// It also outputs the coordinates of the rows(columns) to |offsets|.
static void ScaleAndCalculateOffsets(std::vector<int>* lengths,
                                     std::vector<int>* offsets,
                                     int total_length) {
  int sum = std::accumulate(lengths->begin(), lengths->end(), 0);
  for (size_t i = 0; i < lengths->size(); ++i) {
    lengths->at(i) = lengths->at(i) * total_length / sum;
    offsets->at(i) = (i == 0) ? 0 : offsets->at(i - 1) + lengths->at(i - 1);
  }
}

void RenderingHelper::LayoutRenderingAreas(
    const std::vector<gfx::Size>& window_sizes) {
  // Find the number of colums and rows.
  // The smallest n * n or n * (n + 1) > number of windows.
  size_t cols = sqrt(videos_.size() - 1) + 1;
  size_t rows = (videos_.size() + cols - 1) / cols;

  // Find the widths and heights of the grid.
  std::vector<int> widths(cols);
  std::vector<int> heights(rows);
  std::vector<int> offset_x(cols);
  std::vector<int> offset_y(rows);

  for (size_t i = 0; i < window_sizes.size(); ++i) {
    const gfx::Size& size = window_sizes[i];
    widths[i % cols] = std::max(widths[i % cols], size.width());
    heights[i / cols] = std::max(heights[i / cols], size.height());
  }

  ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width());
  ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height());

  // Put each render_area_ in the center of each cell.
  for (size_t i = 0; i < window_sizes.size(); ++i) {
    const gfx::Size& size = window_sizes[i];
    float scale =
        std::min(static_cast<float>(widths[i % cols]) / size.width(),
                 static_cast<float>(heights[i / cols]) / size.height());

    // Don't scale up the texture.
    scale = std::min(1.0f, scale);

    size_t w = scale * size.width();
    size_t h = scale * size.height();
    size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2;
    size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2;
    videos_[i].render_area = gfx::Rect(x, y, w, h);
  }
}

void RenderingHelper::UpdateVSyncParameters(base::WaitableEvent* done,
                                            const base::TimeTicks timebase,
                                            const base::TimeDelta interval) {
  vsync_timebase_ = timebase;
  vsync_interval_ = interval;

  if (done)
    done->Signal();
}

void RenderingHelper::DropOneFrameForAllVideos() {
  for (RenderedVideo& video : videos_) {
    if (video.pending_frames.empty())
      continue;

    if (video.pending_frames.size() > 1 || video.is_flushing) {
      video.pending_frames.pop();
    } else {
      ++video.frames_to_drop;
    }
  }
}

void RenderingHelper::ScheduleNextRenderContent() {
  scheduled_render_time_ += frame_duration_;
  base::TimeTicks now = base::TimeTicks::Now();
  base::TimeTicks target;

  if (vsync_interval_.is_zero()) {
    target = std::max(now, scheduled_render_time_);
  } else {
    // Schedules the next RenderContent() at latest VSYNC before the
    // |scheduled_render_time_|.
    target = std::max(now + vsync_interval_, scheduled_render_time_);

    int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
    target = vsync_timebase_ + intervals * vsync_interval_;
  }

  // When the rendering falls behind, drops frames.
  while (scheduled_render_time_ < target) {
    scheduled_render_time_ += frame_duration_;
    DropOneFrameForAllVideos();
  }

  task_runner_->PostDelayedTask(FROM_HERE, render_task_.callback(),
                                target - now);
}
}  // namespace media
