// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/lib/external_rasterizer.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/threading/thread_checker.h"
#include "cobalt/math/clamp.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/renderer/backend/egl/graphics_context.h"
#include "cobalt/renderer/backend/egl/render_target.h"
#include "cobalt/renderer/rasterizer/common/find_node.h"
#include "cobalt/renderer/rasterizer/egl/hardware_rasterizer.h"
#include "cobalt/renderer/rasterizer/lib/exported/graphics.h"
#include "cobalt/renderer/rasterizer/lib/exported/video.h"
#include "cobalt/renderer/rasterizer/skia/hardware_image.h"
#include "cobalt/renderer/rasterizer/skia/hardware_mesh.h"
#include "cobalt/renderer/rasterizer/skia/hardware_rasterizer.h"
#include "starboard/shared/gles/gl_call.h"
#include "third_party/glm/glm/gtc/matrix_transform.hpp"
#include "third_party/glm/glm/gtc/type_ptr.hpp"

#ifdef ANGLE_ENABLE_D3D11
// Normally, ANGLE defines this symbol internally using its gyp files.
//
// This code is temporary, so for now just enforce that we are truly building
// Windows when this code path is taken.
#if !defined(_WIN32) && !defined(_WIN64)
#error Direct mirroring to the system window is only supported for Windows!
#endif
#define ANGLE_PLATFORM_WINDOWS 1

#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <d3d11.h>

#include "third_party/angle/src/libANGLE/Context.h"
#include "third_party/angle/src/libANGLE/Display.h"
#include "third_party/angle/src/libANGLE/Surface.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#endif

COMPILE_ASSERT(
    cobalt::render_tree::kMono == kCbLibVideoStereoModeMono &&
        cobalt::render_tree::kLeftRight ==
            kCbLibVideoStereoModeStereoLeftRight &&
        cobalt::render_tree::kTopBottom ==
            kCbLibVideoStereoModeStereoTopBottom &&
        cobalt::render_tree::kLeftRightUnadjustedTextureCoords ==
            kCbLibVideoStereoModeStereoLeftRightUnadjustedCoordinates,
    lib_video_and_map_to_mesh_stereo_mode_constants_mismatch);

using cobalt::renderer::rasterizer::lib::ExternalRasterizer;

namespace {

static const float kMaxRenderTargetSize = 15360.0f;

// The minimum amount of change required in the desired texture size to generate
// a new offscreen render target for the quad texture.
static const float kMinTextureSizeEpsilon = 20.0f;

// Matches the signatures of the callback setter functions in exported/video.h
// and exported/graphics.h.
template <typename Ret, typename... Args>
using CallbackSetter = void(void*, Ret (*)(void*, Args...));

template <typename T, T* t, const char* ErrorMessage>
struct CallbackUpdate;

// Defines useful base:: wrappers for callback setter functions.
template <typename Ret, typename... Args, CallbackSetter<Ret, Args...>* Setter,
          const char* ErrorMessage>
struct CallbackUpdate<CallbackSetter<Ret, Args...>, Setter, ErrorMessage> {
  // Equivalent to the callback types defined in exported/video.h and
  // exported/graphics.h but with the context bound.
  using Callback = base::Callback<Ret(Args...)>;

  static Ret DefaultImplementation(Args...) { LOG(WARNING) << ErrorMessage; }

  struct LazyTraits {
    static const bool kRegisterOnExit = true;
    static const bool kAllowedToAccessOnNonjoinableThread = false;

    static Callback* New(void* instance) {
      return new (instance) Callback(base::Bind(DefaultImplementation));
    }
    static void Delete(Callback* instance) {
      return base::LazyInstanceTraitsBase<Callback>::CallDestructor(instance);
    }
  };

  // This provides a default warning function for the callbacks and allows to
  // set them even before the external rasterizer is created.
  using LazyCallback = base::LazyInstance<Callback, LazyTraits>;
};

// Creates an instance for the above template for a given callback setter
// function, with an error message.
// We must use 'extern' in here as otherwise we get compiler error C2970 when
// using MSVC for compilation.
#define INSTANCE_CALLBACK_UPDATE(instance_name, callback_setter)  \
  extern const char kWarningMessageDidNotSet##instance_name[] =   \
      #callback_setter                                            \
      "was never called to set a callback, yet Cobalt is "        \
      "attempting to call it.";                                   \
  using instance_name =                                           \
      CallbackUpdate<decltype(callback_setter), &callback_setter, \
                     kWarningMessageDidNotSet##instance_name>;

INSTANCE_CALLBACK_UPDATE(UpdateMeshes, CbLibVideoSetOnUpdateMeshes);
INSTANCE_CALLBACK_UPDATE(UpdateRgbTextureId, CbLibVideoSetOnUpdateRgbTextureId);
INSTANCE_CALLBACK_UPDATE(UpdateProjectionTypeAndStereoMode,
                         CbLibVideoSetOnUpdateProjectionTypeAndStereoMode);
INSTANCE_CALLBACK_UPDATE(UpdateAspectRatio, CbLibVideoSetOnUpdateAspectRatio);
INSTANCE_CALLBACK_UPDATE(GraphicsContextCreated,
                         CbLibGraphicsSetContextCreatedCallback);
INSTANCE_CALLBACK_UPDATE(RenderFrame, CbLibGraphicsSetRenderFrameCallback);
#undef INSTANCE_CALLBACK_UPDATE

UpdateMeshes::LazyCallback g_update_meshes_callback = LAZY_INSTANCE_INITIALIZER;
UpdateRgbTextureId::LazyCallback g_update_rgb_texture_id_callback =
    LAZY_INSTANCE_INITIALIZER;
UpdateProjectionTypeAndStereoMode::LazyCallback
    g_update_projection_type_and_stereo_mode_callback =
        LAZY_INSTANCE_INITIALIZER;
UpdateAspectRatio::LazyCallback g_update_aspect_ratio_callback =
    LAZY_INSTANCE_INITIALIZER;
GraphicsContextCreated::LazyCallback g_graphics_context_created_callback =
    LAZY_INSTANCE_INITIALIZER;
RenderFrame::LazyCallback g_render_frame_callback = LAZY_INSTANCE_INITIALIZER;

bool ApproxEqual(const cobalt::math::Size& a, const cobalt::math::Size& b,
                 float epsilon) {
  return std::abs(a.width() - b.width()) < epsilon &&
         std::abs(a.height() - b.height()) < epsilon;
}

cobalt::math::Size CobaltSizeFromCbLibSize(CbLibSize size) {
  return cobalt::math::Size(size.width, size.height);
}

ExternalRasterizer::Impl* g_external_rasterizer_impl = nullptr;

}  // namespace

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace lib {

class ExternalRasterizer::Impl {
 public:
  Impl(backend::GraphicsContext* graphics_context, int skia_atlas_width,
       int skia_atlas_height, int skia_cache_size_in_bytes,
       int scratch_surface_cache_size_in_bytes,
#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
       int offscreen_target_cache_size_in_bytes,
#endif
       bool purge_skia_font_caches_on_destruction,
       bool force_deterministic_rendering);
  ~Impl();

  void Submit(const scoped_refptr<render_tree::Node>& render_tree,
              const scoped_refptr<backend::RenderTarget>& render_target);
  void RenderCobalt();
  void CopyBackbuffer(uintptr_t surface, float width_scale);
  void SwapBackbuffer();

  render_tree::ResourceProvider* GetResourceProvider();

  void MakeCurrent() { hardware_rasterizer_.MakeCurrent(); }
  void ReleaseContext() { hardware_rasterizer_.ReleaseContext(); }

  intptr_t GetMainTextureHandle();

  // Sets the target size in pixels to use for the main render target buffer.
  void SetTargetMainTextureSize(const cobalt::math::Size& target_render_size) {
    target_main_render_target_size_ = target_render_size;
  }

 private:
  void RenderOffscreenVideo(render_tree::FilterNode* map_to_mesh_filter_node);

  void SubmitWithUpdatedTextureSize(
      const cobalt::math::Size& native_render_target_size,
      const scoped_refptr<render_tree::Node>& render_tree);

  base::ThreadChecker thread_checker_;

  backend::GraphicsContextEGL* graphics_context_;

#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
  egl::HardwareRasterizer hardware_rasterizer_;
#else
  skia::HardwareRasterizer hardware_rasterizer_;
#endif
  Rasterizer::Options options_;

  // Temporary reference to the render tree and main window render target.
  //
  // Only valid inside of Submit().
  scoped_refptr<render_tree::Node> render_tree_temp_;
  backend::RenderTargetEGL* main_render_target_temp_;

  // The main offscreen render target to use when rendering UI or rectangular
  // video.
  scoped_refptr<backend::RenderTarget> main_offscreen_render_target_;
  std::unique_ptr<backend::TextureEGL> main_texture_;

  // TODO: do not actually rasterize offscreen video, but just submit it to the
  // host directly.
  scoped_refptr<backend::RenderTarget> video_offscreen_render_target_;
  std::unique_ptr<backend::TextureEGL> video_texture_;
  CbLibVideoProjectionType video_projection_type_;
  scoped_refptr<skia::HardwareMesh> left_eye_video_mesh_;
  scoped_refptr<skia::HardwareMesh> right_eye_video_mesh_;
  render_tree::StereoMode video_stereo_mode_;
  GLuint video_texture_rgb_;
  // The 'target'/'ideal' size to use for the main RenderTarget. The actual size
  // of the buffer for the main RenderTarget should aim to be within some small
  // delta of this whenever a new RenderTree is rendered.
  cobalt::math::Size target_main_render_target_size_;
  int video_width_;
  int video_height_;
};

ExternalRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context,
                               int skia_atlas_width, int skia_atlas_height,
                               int skia_cache_size_in_bytes,
                               int scratch_surface_cache_size_in_bytes,
#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
                               int offscreen_target_cache_size_in_bytes,
#endif
                               bool purge_skia_font_caches_on_destruction,
                               bool force_deterministic_rendering)
    : graphics_context_(
          base::polymorphic_downcast<backend::GraphicsContextEGL*>(
              graphics_context)),
      hardware_rasterizer_(
          graphics_context, skia_atlas_width, skia_atlas_height,
          skia_cache_size_in_bytes, scratch_surface_cache_size_in_bytes,

#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
          offscreen_target_cache_size_in_bytes,
#endif
          purge_skia_font_caches_on_destruction, force_deterministic_rendering),
      render_tree_temp_(nullptr),
      main_render_target_temp_(nullptr),
      video_projection_type_(kCbLibVideoProjectionTypeNone),
      video_stereo_mode_(render_tree::StereoMode::kMono),
      video_texture_rgb_(0),
      video_width_(-1),
      video_height_(-1),
      target_main_render_target_size_(1, 1) {
  CHECK(!g_external_rasterizer_impl);
  g_external_rasterizer_impl = this;
  options_.flags = Rasterizer::kSubmitFlags_Clear;
  graphics_context_->MakeCurrent();

  main_offscreen_render_target_ =
      graphics_context_->CreateOffscreenRenderTarget(
          target_main_render_target_size_);
  main_texture_.reset(new backend::TextureEGL(
      graphics_context_,
      base::WrapRefCounted(
          base::polymorphic_downcast<backend::RenderTargetEGL*>(
              main_offscreen_render_target_.get()))));

  g_graphics_context_created_callback.Get().Run();
}

ExternalRasterizer::Impl::~Impl() {
  graphics_context_->MakeCurrent();
  g_external_rasterizer_impl = nullptr;
}

void ExternalRasterizer::Impl::Submit(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target) {
  DCHECK(thread_checker_.CalledOnValidThread());

  backend::RenderTargetEGL* render_target_egl =
      base::polymorphic_downcast<backend::RenderTargetEGL*>(
          render_target.get());

  // When the provided RenderTarget is not a window RenderTarget, then this
  // implies the rasterized RenderTree should not be shown directly to the user
  // and thus should not be rasterized into a texture and sent through to the
  // client implementing CbLibRenderFrame.
  if (!render_target_egl->IsWindowRenderTarget()) {
    hardware_rasterizer_.Submit(render_tree, render_target, options_);
  } else {
    // Store the pointers to the render tree and target temporarily so they
    // can be used from callbacks triggered from the app's RenderFrameCallback.
    render_tree_temp_ = render_tree.get();
    main_render_target_temp_ = render_target_egl;

    // TODO: Allow clients to specify arbitrary subtrees to render into
    // different textures?
    g_render_frame_callback.Get().Run();

    render_tree_temp_ = nullptr;
    main_render_target_temp_ = nullptr;
  }
}

void ExternalRasterizer::Impl::RenderCobalt() {
  // This method must be called from the g_render_frame_callback set by the
  // host, otherwise these members will be nullptr.
  CHECK(main_render_target_temp_);
  CHECK(render_tree_temp_.get());
  DCHECK(thread_checker_.CalledOnValidThread());

  graphics_context_->MakeCurrentWithSurface(main_render_target_temp_);

  // Attempt to find map to mesh filter node, then render video subtree
  // offscreen.
  base::Optional<common::NodeReplaceFunction> replace_function2(
      base::Bind(common::ReplaceWithEmptyCompositionNode));
  common::NodeFilterFunction filter_function = base::Bind(common::HasMapToMesh);
  auto map_to_mesh_search = common::FindNode<render_tree::FilterNode>(
      render_tree_temp_, filter_function, replace_function2);

  if (map_to_mesh_search.found_node.get() != NULL) {
    base::Optional<render_tree::MapToMeshFilter> filter =
        map_to_mesh_search.found_node->data().map_to_mesh_filter;

    CbLibVideoProjectionType new_projection_type;
    switch (filter->mesh_type()) {
      case render_tree::kRectangular:
        // Video is rectangular. Mesh is provided externally (by host).
        new_projection_type = kCbLibVideoProjectionTypeRectangular;
        break;
      case render_tree::kCustomMesh:
        new_projection_type = kCbLibVideoProjectionTypeMesh;
        break;
    }

    if (video_projection_type_ != new_projection_type ||
        filter->stereo_mode() != video_stereo_mode_) {
      // Note the above condition will always be true when playback has not
      // started.
      video_projection_type_ = new_projection_type;
      video_stereo_mode_ = filter->stereo_mode();
      g_update_projection_type_and_stereo_mode_callback.Get().Run(
          video_projection_type_,
          static_cast<CbLibVideoStereoMode>(video_stereo_mode_));
    }

    const scoped_refptr<render_tree::Node>& video_render_tree =
        map_to_mesh_search.found_node->data().source;
    math::SizeF resolutionf = video_render_tree->GetBounds().size();
    int width = static_cast<int>(resolutionf.width());
    int height = static_cast<int>(resolutionf.height());

    if (video_width_ != width || video_height_ != height) {
      g_update_aspect_ratio_callback.Get().Run(
          width > 0 && height > 0 ?  // Avoid division by zero.
              resolutionf.width() / resolutionf.height()
                                  : 0.0f);
      video_width_ = width;
      video_height_ = height;
    }

    if (video_projection_type_ == kCbLibVideoProjectionTypeMesh) {
      // Use resolution to lookup custom mesh map.
      math::Size resolution(width, height);
      scoped_refptr<skia::HardwareMesh> left_eye_video_mesh(
          base::polymorphic_downcast<skia::HardwareMesh*>(
              filter->left_eye_mesh(resolution).get()));
      scoped_refptr<skia::HardwareMesh> right_eye_video_mesh(
          base::polymorphic_downcast<skia::HardwareMesh*>(
              filter->right_eye_mesh(resolution).get()));

      DCHECK(left_eye_video_mesh);

      if (left_eye_video_mesh_.get() != left_eye_video_mesh.get() ||
          right_eye_video_mesh_.get() != right_eye_video_mesh.get()) {
        left_eye_video_mesh_ = left_eye_video_mesh;
        right_eye_video_mesh_ = right_eye_video_mesh;

        CbLibVideoMesh left_mesh;
        left_mesh.vertex_count =
            static_cast<int>(left_eye_video_mesh_->GetVertexCount());
        left_mesh.draw_mode = static_cast<CbLibVideoMeshDrawMode>(
            left_eye_video_mesh_->GetDrawMode());
        left_mesh.vertices = left_eye_video_mesh_->GetVertices();

        if (right_eye_video_mesh_) {
          CbLibVideoMesh right_mesh;
          right_mesh.vertex_count =
              static_cast<int>(right_eye_video_mesh_->GetVertexCount());
          right_mesh.draw_mode = static_cast<CbLibVideoMeshDrawMode>(
              right_eye_video_mesh_->GetDrawMode());
          right_mesh.vertices = right_eye_video_mesh_->GetVertices();
          g_update_meshes_callback.Get().Run(left_mesh, right_mesh);
        } else {
          g_update_meshes_callback.Get().Run(left_mesh, left_mesh);
        }
      }
    }

    // Render video to external texture(s) and pass those to the host.
    RenderOffscreenVideo(map_to_mesh_search.found_node);
  } else {
    if (video_projection_type_ != kCbLibVideoProjectionTypeNone) {
      video_projection_type_ = kCbLibVideoProjectionTypeNone;
      g_update_projection_type_and_stereo_mode_callback.Get().Run(
          video_projection_type_, kCbLibVideoStereoModeMono);
      video_width_ = video_height_ = -1;
    }
  }

  SubmitWithUpdatedTextureSize(main_render_target_temp_->GetSize(),
                               map_to_mesh_search.replaced_tree);
}

void ExternalRasterizer::Impl::CopyBackbuffer(uintptr_t surface,
                                              float width_scale) {
  // This method must be called from the g_render_frame_callback set by the
  // host, otherwise this member will be nullptr.
  CHECK(main_render_target_temp_);
  DCHECK(thread_checker_.CalledOnValidThread());

  // If there is any host-provided surface, mirror it directly into the
  // system window with a blit.  The surface will be streched or shrunk as
  // appropriate so that it fits the system window's backbuffer.
  if (surface != 0) {
#ifdef ANGLE_ENABLE_D3D11
    EGLContext egl_context = eglGetCurrentContext();
    EGLSurface egl_mirror_surface = reinterpret_cast<EGLSurface>(surface);
    EGLSurface egl_window_surface = main_render_target_temp_->GetSurface();
    ::gl::Context* angle_context =
        reinterpret_cast<::gl::Context*>(egl_context);
    ::egl::Surface* angle_mirror_surface =
        reinterpret_cast<::egl::Surface*>(egl_mirror_surface);
    ::egl::Surface* angle_window_surface =
        reinterpret_cast<::egl::Surface*>(egl_window_surface);
    ::rx::SurfaceD3D* d3d_mirror_surface =
        ::rx::GetImplAs<rx::SurfaceD3D>(angle_mirror_surface);
    ::rx::SurfaceD3D* d3d_window_surface =
        ::rx::GetImplAs<rx::SurfaceD3D>(angle_window_surface);
    ::rx::Context11* d3d11_context =
        ::rx::GetImplAs<::rx::Context11>(angle_context);
    ::rx::Renderer11* d3d11_renderer = d3d11_context->getRenderer();
    ::rx::SwapChain11* d3d11_mirror_swapchain =
        static_cast<::rx::SwapChain11*>(d3d_mirror_surface->getSwapChain());
    ::rx::SwapChain11* d3d11_window_swapchain =
        static_cast<::rx::SwapChain11*>(d3d_window_surface->getSwapChain());
    float src_width_scale = std::min(1.0f, std::max(width_scale, 0.0f));

    d3d11_renderer->getBlitter()->copyTexture(
        d3d11_mirror_swapchain->getRenderTargetShaderResource(),
        gl::Box(0, 0, 0, d3d11_mirror_swapchain->getWidth() * src_width_scale,
                d3d11_mirror_swapchain->getHeight(), 1),
        gl::Extents(d3d11_mirror_swapchain->getWidth(),
                    d3d11_mirror_swapchain->getHeight(), 1),
        d3d11_window_swapchain->getRenderTarget(),
        gl::Box(0, 0, 0, d3d11_window_swapchain->getWidth(),
                d3d11_window_swapchain->getHeight(), 1),
        gl::Extents(d3d11_window_swapchain->getWidth(),
                    d3d11_window_swapchain->getHeight(), 1),
        nullptr, GL_RGBA_INTEGER, GL_LINEAR, false, false, false);
#else
    LOG(FATAL) << "Direct mirroring to the system window is only supported "
               << "under DirectX.";
#endif
  }
}

void ExternalRasterizer::Impl::SwapBackbuffer() {
  // This method must be called from the g_render_frame_callback set by the
  // host, otherwise this member will be nullptr.
  CHECK(main_render_target_temp_);
  DCHECK(thread_checker_.CalledOnValidThread());

  graphics_context_->SwapBuffers(main_render_target_temp_);
}

// TODO: Share this logic with the ComponentRenderer.
void ExternalRasterizer::Impl::SubmitWithUpdatedTextureSize(
    const cobalt::math::Size& native_render_target_size,
    const scoped_refptr<render_tree::Node>& render_tree) {
  // We need to make sure that our texture ID gets updated after the
  // HardwareRasterizer submits, because the render target in use might get
  // swapped during the submit.
  bool texture_id_needs_update = false;

  // Create a new offscreen render target if the exist one's size is far enough
  // off from the target/ideal size.
  if (!main_offscreen_render_target_ ||
      !ApproxEqual(main_offscreen_render_target_->GetSize(),
                   target_main_render_target_size_, kMinTextureSizeEpsilon)) {
    LOG(INFO) << "Creating a new offscreen render target of size "
              << target_main_render_target_size_;
    main_offscreen_render_target_ =
        graphics_context_->CreateOffscreenRenderTarget(
            target_main_render_target_size_);
    texture_id_needs_update = true;
  }

  DCHECK(native_render_target_size.width());
  DCHECK(native_render_target_size.height());
  // We wrap the RenderTree in a MatrixTransformNode to scale the RenderTree so
  // that its scale relative to our RenderTarget matches its original scale
  // relative to native_render_target_size. This makes the texture cropped to
  // fit our RenderTarget the same amount it would be for the original
  // RenderTarget.
  const float texture_x_scale =
      static_cast<float>(main_offscreen_render_target_->GetSize().width()) /
      native_render_target_size.width();
  const float texture_y_scale =
      static_cast<float>(main_offscreen_render_target_->GetSize().height()) /
      native_render_target_size.height();
  const glm::mat3 scale_mat(glm::scale(
      glm::mat4(1.0f), glm::vec3(texture_x_scale, texture_y_scale, 1)));
  const cobalt::math::Matrix3F root_transform_matrix =
      cobalt::math::Matrix3F::FromArray(glm::value_ptr(scale_mat));
  scoped_refptr<render_tree::MatrixTransformNode> scaled_main_node(
      new render_tree::MatrixTransformNode(render_tree, root_transform_matrix));

  hardware_rasterizer_.Submit(scaled_main_node, main_offscreen_render_target_,
                              options_);

  if (texture_id_needs_update) {
    // Note: The TextureEGL this pointer references must first be destroyed by
    // calling reset() before a new TextureEGL can be constructed.
    main_texture_.reset();
    main_texture_.reset(new backend::TextureEGL(
        graphics_context_,
        base::WrapRefCounted(
            base::polymorphic_downcast<backend::RenderTargetEGL*>(
                main_offscreen_render_target_.get()))));
  }
}

render_tree::ResourceProvider* ExternalRasterizer::Impl::GetResourceProvider() {
  return hardware_rasterizer_.GetResourceProvider();
}

intptr_t ExternalRasterizer::Impl::GetMainTextureHandle() {
  return main_texture_->GetPlatformHandle();
}

void ExternalRasterizer::Impl::RenderOffscreenVideo(
    render_tree::FilterNode* map_to_mesh_filter_node) {
  DCHECK(map_to_mesh_filter_node);
  if (!map_to_mesh_filter_node) {
    return;
  }

  // Render the mesh-video into a texture to render into 3D space.
  const scoped_refptr<render_tree::Node>& video_render_tree =
      map_to_mesh_filter_node->data().source;
  // Search the video_render_tree for the video frame ImageNode.
  auto image_node =
      common::FindNode<render_tree::ImageNode>(video_render_tree).found_node;

  math::SizeF video_size_float = video_render_tree->GetBounds().size();
  if (image_node.get() && image_node->data().source) {
    video_size_float = image_node->data().source.get()->GetSize();
  }

  // Width and height of the video render target are based on the size of the
  // video clamped to the valid range for creating an offscreen render target.
  const float target_width = math::Clamp(std::floor(video_size_float.width()),
                                         1.0f, kMaxRenderTargetSize);
  const float target_height = math::Clamp(std::floor(video_size_float.height()),
                                          1.0f, kMaxRenderTargetSize);
  const math::Size video_size(target_width, target_height);

  // We need to make sure that our texture ID gets updated after the
  // HardwareRasterizer submits, because the render target in use might get
  // swapped during the submit.
  bool texture_id_needs_update = false;

  if (!video_offscreen_render_target_ ||
      video_offscreen_render_target_->GetSize() != video_size) {
    video_offscreen_render_target_ =
        graphics_context_->CreateOffscreenRenderTarget(video_size);
    DLOG(INFO) << "Created new video_offscreen_render_target_: "
               << video_offscreen_render_target_->GetSize();
    texture_id_needs_update = true;
  }

  if (image_node.get()) {
    // Create a new ImageNode around the raw image data which will
    // automatically scale it to the right size.
    backend::RenderTargetEGL* video_offscreen_render_target_egl =
        base::polymorphic_downcast<backend::RenderTargetEGL*>(
            video_offscreen_render_target_.get());

    const scoped_refptr<render_tree::ImageNode> correctly_scaled_image_node(
        new render_tree::ImageNode(image_node->data().source));

    // TODO: Instead of submitting the image for rendering and producing an
    // RGB texture, try to cast to HardwareMultiPlaneImage to use the YUV
    // textures already produced by decode-to-texture.
    hardware_rasterizer_.Submit(correctly_scaled_image_node,
                                video_offscreen_render_target_, options_);

    if (texture_id_needs_update) {
      // Note: The TextureEGL this pointer references must first be destroyed by
      // calling reset() before a new TextureEGL can be constructed.
      video_texture_.reset();
      video_texture_.reset(new backend::TextureEGL(
          graphics_context_,
          base::WrapRefCounted(
              base::polymorphic_downcast<backend::RenderTargetEGL*>(
                  video_offscreen_render_target_.get()))));
    }

    const intptr_t video_texture_handle = video_texture_->GetPlatformHandle();
    if (video_texture_rgb_ != video_texture_handle) {
      video_texture_rgb_ = video_texture_handle;
      g_update_rgb_texture_id_callback.Get().Run(video_texture_handle);
    }
  }
}

ExternalRasterizer::ExternalRasterizer(
    backend::GraphicsContext* graphics_context, int skia_atlas_width,
    int skia_atlas_height, int skia_cache_size_in_bytes,
    int scratch_surface_cache_size_in_bytes,
#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
    int offscreen_target_cache_size_in_bytes,
#endif
    bool purge_skia_font_caches_on_destruction,
    bool force_deterministic_rendering)
    : impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
                     skia_cache_size_in_bytes,
                     scratch_surface_cache_size_in_bytes,
#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
                     offscreen_target_cache_size_in_bytes,
#endif
                     purge_skia_font_caches_on_destruction,
                     force_deterministic_rendering)) {
}

ExternalRasterizer::~ExternalRasterizer() {}

void ExternalRasterizer::Submit(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target,
    const Options& options) {
  impl_->Submit(render_tree, render_target);
}

render_tree::ResourceProvider* ExternalRasterizer::GetResourceProvider() {
  return impl_->GetResourceProvider();
}

void ExternalRasterizer::MakeCurrent() { return impl_->MakeCurrent(); }

void ExternalRasterizer::ReleaseContext() { return impl_->ReleaseContext(); }

}  // namespace lib
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

void CbLibVideoSetOnUpdateMeshes(void* context,
                                 CbLibVideoUpdateMeshesCallback callback) {
  g_update_meshes_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(&UpdateMeshes::DefaultImplementation);
}

void CbLibVideoSetOnUpdateRgbTextureId(
    void* context, CbLibVideoUpdateRgbTextureIdCallback callback) {
  g_update_rgb_texture_id_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(&UpdateRgbTextureId::DefaultImplementation);
}

void CbLibVideoSetOnUpdateProjectionTypeAndStereoMode(
    void* context,
    CbLibVideoUpdateProjectionTypeAndStereoModeCallback callback) {
  g_update_projection_type_and_stereo_mode_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(
                     &UpdateProjectionTypeAndStereoMode::DefaultImplementation);
}

void CbLibVideoSetOnUpdateAspectRatio(
    void* context, CbLibVideoUpdateAspectRatioCallback callback) {
  g_update_aspect_ratio_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(&UpdateAspectRatio::DefaultImplementation);
}

void CbLibGraphicsSetContextCreatedCallback(
    void* context, CbLibGraphicsContextCreatedCallback callback) {
  g_graphics_context_created_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(&GraphicsContextCreated::DefaultImplementation);
}

void CbLibGraphicsSetRenderFrameCallback(
    void* context, CbLibGraphicsRenderFrameCallback callback) {
  g_render_frame_callback.Get() =
      callback ? base::Bind(callback, context)
               : base::Bind(&RenderFrame::DefaultImplementation);
}

intptr_t CbLibGrapicsGetMainTextureHandle() {
  DCHECK(g_external_rasterizer_impl);
  if (!g_external_rasterizer_impl) {
    LOG(WARNING) << __FUNCTION__
                 << "ExternalRasterizer not yet created; unable to progress.";
    return 0;
  }

  return g_external_rasterizer_impl->GetMainTextureHandle();
}

void CbLibGraphicsSetTargetMainTextureSize(
    const CbLibSize& target_render_size) {
  DCHECK(g_external_rasterizer_impl);
  if (!g_external_rasterizer_impl) {
    LOG(WARNING) << __FUNCTION__
                 << "ExternalRasterizer not yet created; unable to progress.";
    return;
  }
  const cobalt::math::Size size = CobaltSizeFromCbLibSize(target_render_size);
  g_external_rasterizer_impl->SetTargetMainTextureSize(size);
}

void CbLibGraphicsRenderCobalt() {
  DCHECK(g_external_rasterizer_impl);
  if (!g_external_rasterizer_impl) {
    LOG(WARNING) << __FUNCTION__
                 << "ExternalRasterizer not yet created; unable to progress.";
    return;
  }
  g_external_rasterizer_impl->RenderCobalt();
}

void CbLibGraphicsCopyBackbuffer(uintptr_t surface, float width_scale) {
  DCHECK(g_external_rasterizer_impl);
  if (!g_external_rasterizer_impl) {
    LOG(WARNING) << __FUNCTION__
                 << "ExternalRasterizer not yet created; unable to progress.";
    return;
  }
  g_external_rasterizer_impl->CopyBackbuffer(surface, width_scale);
}

void CbLibGraphicsSwapBackbuffer() {
  DCHECK(g_external_rasterizer_impl);
  if (!g_external_rasterizer_impl) {
    LOG(WARNING) << __FUNCTION__
                 << "ExternalRasterizer not yet created; unable to progress.";
    return;
  }
  g_external_rasterizer_impl->SwapBackbuffer();
}
