// Copyright 2016 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/backend/blitter/graphics_context.h"

#include <algorithm>
#include <memory>

#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/renderer/backend/blitter/graphics_system.h"
#include "cobalt/renderer/backend/blitter/surface_render_target.h"
#include "starboard/blitter.h"

#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)

namespace cobalt {
namespace renderer {
namespace backend {

GraphicsContextBlitter::GraphicsContextBlitter(GraphicsSystem* system)
    : GraphicsContext(system) {
  TRACE_EVENT0("cobalt::renderer",
               "GraphicsContextBlitter::GraphicsContextBlitter");

  device_ = base::polymorphic_downcast<GraphicsSystemBlitter*>(system)
                ->GetSbBlitterDevice();
  context_ = SbBlitterCreateContext(device_);
  CHECK(SbBlitterIsContextValid(context_));
}

GraphicsContextBlitter::~GraphicsContextBlitter() {
  TRACE_EVENT0("cobalt::renderer",
               "GraphicsContextBlitter::~GraphicsContextBlitter");
  SbBlitterDestroyContext(context_);
}

scoped_refptr<RenderTarget> GraphicsContextBlitter::CreateOffscreenRenderTarget(
    const math::Size& dimensions) {
  TRACE_EVENT0("cobalt::renderer",
               "GraphicsContextBlitter::CreateOffscreenRenderTarget");

  scoped_refptr<RenderTarget> render_target(
      new SurfaceRenderTargetBlitter(device_, dimensions));
  if (render_target->CreationError()) {
    return scoped_refptr<RenderTarget>();
  } else {
    return render_target;
  }
}

std::unique_ptr<uint8_t[]> GraphicsContextBlitter::DownloadPixelDataAsRGBA(
    const scoped_refptr<RenderTarget>& render_target) {
  TRACE_EVENT0("cobalt::renderer",
               "GraphicsContextBlitter::DownloadPixelDataAsRGBA");
  SurfaceRenderTargetBlitter* render_target_blitter =
      base::polymorphic_downcast<SurfaceRenderTargetBlitter*>(
          render_target.get());

  SbBlitterSurface surface = render_target_blitter->GetSbSurface();

  const math::Size& size = render_target_blitter->GetSize();
  std::unique_ptr<uint8_t[]> pixels(new uint8_t[size.GetArea() * 4]);

  SbBlitterFlushContext(context_);
  SbBlitterDownloadSurfacePixels(surface, kSbBlitterPixelDataFormatRGBA8,
                                 size.width() * 4, pixels.get());

  return std::move(pixels);
}

void GraphicsContextBlitter::Finish() {
  // Note: flushing the context doesn't actually guarantee that drawing has
  // finished.
  SbBlitterFlushContext(context_);
}

}  // namespace backend
}  // namespace renderer
}  // namespace cobalt

#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
