// 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 "starboard/blitter.h"
#include "starboard/event.h"
#include "starboard/log.h"
#include "starboard/system.h"
#include "starboard/thread.h"
#include "starboard/time.h"
#include "starboard/window.h"

#if SB_HAS(BLITTER)

class Application {
 public:
  Application();
  ~Application();

 private:
  // The callback function passed to SbEventSchedule().  Its purpose is to
  // forward to the non-static RenderScene() method.
  static void RenderSceneEventCallback(void* param);

  // Renders one frame of the animated scene, incrementing |frame_| each time
  // it is called.
  void RenderScene();

  static Application* application_;

  // The current frame we are rendering, initialized to 0 and incremented after
  // each frame.
  int frame_;

  // The SbWindow within which we will perform our rendering.
  SbWindow window_;

  // The blitting device we will be targeting.
  SbBlitterDevice device_;

  // The swap chain that represents |window_|'s display.
  SbBlitterSwapChain swap_chain_;
  static const int kOutputWidth = 1920;
  static const int kOutputHeight = 1080;

  // The surface of a simple unchanging RGBA bitmap image we will use while
  // rendering.
  SbBlitterSurface rgba_image_surface_;
  // The surface of a simple unchanging alpha-only bitmap image we will use
  // while rendering.
  SbBlitterSurface alpha_image_surface_;
  static const int kImageWidth = 100;
  static const int kImageHeight = 100;

  // An offscreen surface that we will render to and render from each frame.
  SbBlitterSurface offscreen_surface_;
  static const int kOffscreenWidth = 400;
  static const int kOffscreenHeight = 400;

  // The context within which we will issue all our draw commands.
  SbBlitterContext context_;
};

namespace {
// Populates a region of memory designated as pixel data with a gradient texture
// that includes transparent alpha.
void FillGradientImageData(int width,
                           int height,
                           int pitch_in_bytes,
                           void* pixel_data) {
  uint8_t* pixels = static_cast<uint8_t*>(pixel_data);

  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
      // Setup a vertical gradient in the alpha color channel.
      float alpha = static_cast<float>(y) / height;
      uint8_t alpha_byte = static_cast<uint8_t>(alpha) * 255;

      // Setup a horizontal gradient in the green color channel.
      uint8_t green_byte =
          static_cast<uint8_t>((alpha * static_cast<float>(x) / width) * 255);

      // Assuming BGRA color format.
      pixels[x * 4 + 0] = 0;
      pixels[x * 4 + 1] = green_byte;
      pixels[x * 4 + 0] = 0;
      pixels[x * 4 + 3] = alpha_byte;
    }

    pixels += pitch_in_bytes;
  }
}

// Populates a region of memory designated as pixel data with a checker texture
// using an alpha-only pixel format.
void FillAlphaCheckerImageData(int width,
                               int height,
                               int pitch,
                               void* pixel_data) {
  uint8_t* pixels = static_cast<uint8_t*>(pixel_data);

  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
      bool is_first_vertical_half = y <= height / 2;
      bool is_first_horizontal_half = x <= width / 2;

      uint8_t color =
          is_first_horizontal_half ^ is_first_vertical_half ? 255 : 0;

      pixels[x + y * pitch] = color;
    }
  }
}
}  // namespace

Application::Application() {
  frame_ = 0;
  // In order to access most of the Blitter API, we'll need to create a SbWindow
  // object whose display we can have the Blitter API target.
  SbWindowOptions options;
  SbWindowSetDefaultOptions(&options);
  options.size.width = 1920;
  options.size.height = 1080;
  window_ = SbWindowCreate(NULL);
  SB_CHECK(SbWindowIsValid(window_));

  // We start by constructing a SbBlitterDevice which represents the connection
  // to the hardware blitting device (e.g. a GPU).
  device_ = SbBlitterCreateDefaultDevice();

  // Creating the swap chain associates our blitting device to the target
  // window's output display.
  swap_chain_ = SbBlitterCreateSwapChainFromWindow(device_, window_);

  // Let's setup a texture.  We start by creating a SbBlitterPixelData object
  // which can be populated with pixel data by the CPU and then passed on to
  // the device for reference within blit calls.
  SbBlitterPixelData image_data = SbBlitterCreatePixelData(
      device_, kImageWidth, kImageHeight, kSbBlitterPixelDataFormatBGRA8);

  // Once our pixel data object is created, we can extract from it the image
  // data pitch as well as a CPU-accessible pointer to the pixel data.  We
  // pass this information into a function to populate the image.
  int image_data_pitch = SbBlitterGetPixelDataPitchInBytes(image_data);
  FillGradientImageData(kImageHeight, kImageHeight, image_data_pitch,
                        SbBlitterGetPixelDataPointer(image_data));

  // Now that our pixel data is finalized, we create a surface from it.  After
  // this call, our SbBlitterPixelData object is invalid (i.e. it is transformed
  // into a SbBlitterSurface object).
  rgba_image_surface_ =
      SbBlitterCreateSurfaceFromPixelData(device_, image_data);

  // Now setup our alpha-only image.
  SbBlitterPixelData alpha_image_data = SbBlitterCreatePixelData(
      device_, kImageWidth, kImageHeight, kSbBlitterPixelDataFormatA8);
  int alpha_image_data_pitch =
      SbBlitterGetPixelDataPitchInBytes(alpha_image_data);
  FillAlphaCheckerImageData(kImageHeight, kImageHeight, alpha_image_data_pitch,
                            SbBlitterGetPixelDataPointer(alpha_image_data));
  alpha_image_surface_ =
      SbBlitterCreateSurfaceFromPixelData(device_, alpha_image_data);

  // We will also create a (initially blank) surface for use as an offscreen
  // render target.
  offscreen_surface_ = SbBlitterCreateRenderTargetSurface(
      device_, kOffscreenWidth, kOffscreenHeight, kSbBlitterSurfaceFormatRGBA8);

  // Finally, in order to issue draw calls, we need a context that maintains
  // draw state for us.
  context_ = SbBlitterCreateContext(device_);

  RenderScene();
}

Application::~Application() {
  // Cleanup all used resources.
  SbBlitterDestroyContext(context_);
  SbBlitterDestroySurface(offscreen_surface_);
  SbBlitterDestroySurface(alpha_image_surface_);
  SbBlitterDestroySurface(rgba_image_surface_);
  SbBlitterDestroySwapChain(swap_chain_);
  SbBlitterDestroyDevice(device_);
  SbWindowDestroy(window_);
}

void Application::RenderSceneEventCallback(void* param) {
  // Forward the call to the application instance specified as the parameter.
  Application* application = static_cast<Application*>(param);
  application->RenderScene();
}

void Application::RenderScene() {
  // Setup our animation parameter that follows a sawtooth pattern.
  int frame_mod_255 = frame_ % 255;

  // We can get a render target from a swap chain, so that we can target the
  // display with draw calls.
  SbBlitterRenderTarget primary_render_target =
      SbBlitterGetRenderTargetFromSwapChain(swap_chain_);

  // Surfaces created for use as a render target provide both a
  // SbBlitterRenderTarget and SbBlitterTexture objects, for use as target and
  // source in draw calls, respectively.
  SbBlitterRenderTarget offscreen_render_target =
      SbBlitterGetRenderTargetFromSurface(offscreen_surface_);

  // First we set the render target to our offscreen surface.
  SbBlitterSetRenderTarget(context_, offscreen_render_target);

  // And enable alpha blending.
  SbBlitterSetBlending(context_, true);

  // We start by clearing our entire surface to a animating shade of red.
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(frame_mod_255, 0, 0, 255));
  SbBlitterFillRect(context_,
                    SbBlitterMakeRect(0, 0, kOffscreenWidth, kOffscreenHeight));
  // We then draw a green rectangle in the top left corner.
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 255, 0, 32));
  SbBlitterFillRect(context_, SbBlitterMakeRect(50, 50, 100, 100));

  // Now we disable blending for the next few draw calls, resulting in their
  // alpha channels replacing the alpha channels that already exist in the
  // render target.
  SbBlitterSetBlending(context_, false);

  // Punch a blue half-transparent rectangle out in the top right corner.
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 255, 128));
  SbBlitterFillRect(context_, SbBlitterMakeRect(250, 50, 100, 100));

  // Render our surface to the offscreen surface as well, stretched
  // horizontally, in two different locations.
  SbBlitterSetBlending(context_, true);
  SbBlitterSetModulateBlitsWithColor(context_, false);
  SbBlitterBlitRectToRect(context_, rgba_image_surface_,
                          SbBlitterMakeRect(0, 0, kImageWidth, kImageHeight),
                          SbBlitterMakeRect(frame_mod_255, frame_mod_255,
                                            kImageWidth * 2, kImageHeight));

  SbBlitterSetModulateBlitsWithColor(context_, true);
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(255, 255, 255, 128));
  SbBlitterBlitRectToRect(context_, rgba_image_surface_,
                          SbBlitterMakeRect(0, 0, kImageWidth, kImageHeight),
                          SbBlitterMakeRect(frame_mod_255, frame_mod_255 + 100,
                                            kImageWidth * 2, kImageHeight));

  // Blit out our alpha checker surface in the color blue.
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 255, 255));
  SbBlitterBlitRectToRect(
      context_, alpha_image_surface_,
      SbBlitterMakeRect(0, 0, kImageWidth, kImageHeight),
      SbBlitterMakeRect(50, 200, kImageWidth, kImageHeight));

  // Now switch to the primary display render target.
  SbBlitterSetRenderTarget(context_, primary_render_target);

  // Clear the display to an animating shade of green.
  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, frame_mod_255, 0, 255));
  SbBlitterFillRect(context_,
                    SbBlitterMakeRect(0, 0, kOutputWidth, kOutputHeight));

  // Render our offscreen surface to the display in three different places
  // and sizes.
  SbBlitterSetColor(context_,
                    SbBlitterColorFromRGBA(255, 255, 255, frame_mod_255));
  SbBlitterSetModulateBlitsWithColor(context_, true);
  SbBlitterBlitRectToRect(
      context_, offscreen_surface_,
      SbBlitterMakeRect(0, 0, kOffscreenWidth, kOffscreenHeight),
      SbBlitterMakeRect(10, 10, 200, 200));
  SbBlitterBlitRectToRect(
      context_, offscreen_surface_,
      SbBlitterMakeRect(0, 0, kOffscreenWidth, kOffscreenHeight),
      SbBlitterMakeRect(300, 10, 400, 400));
  SbBlitterBlitRectToRect(
      context_, offscreen_surface_,
      SbBlitterMakeRect(0, 0, kOffscreenWidth, kOffscreenHeight),
      SbBlitterMakeRect(10, 500, 800, 200));

  SbBlitterSetModulateBlitsWithColor(context_, false);

  // Blit an animated tiling of the offscreen surface.
  SbBlitterBlitRectToRectTiled(
      context_, offscreen_surface_,
      SbBlitterMakeRect(
          frame_mod_255 * 3, frame_mod_255 * 5,
          1 + static_cast<int>(kOffscreenWidth * (frame_mod_255 / 31.0f)),
          1 + static_cast<int>(kOffscreenWidth * (frame_mod_255 / 63.0f))),
      SbBlitterMakeRect(900, 100, 400, 400));

  // Blit a batch of 4 instances of the offscreen surface in one draw call.
  const int kNumBatchRects = 4;
  SbBlitterRect src_rects[kNumBatchRects];
  SbBlitterRect dst_rects[kNumBatchRects];
  for (int j = 0; j < kNumBatchRects; ++j) {
    src_rects[j].x = 0;
    src_rects[j].y = 0;
    src_rects[j].width = kOffscreenWidth;
    src_rects[j].height = kOffscreenHeight;

    dst_rects[j].x = 900 + j * 220;
    dst_rects[j].y = 600;
    dst_rects[j].width = 200;
    dst_rects[j].height = 300;
  }
  SbBlitterBlitRectsToRects(context_, offscreen_surface_, src_rects, dst_rects,
                            kNumBatchRects);

  // Ensure that all draw commands issued to the context are flushed to
  // the device and guaranteed to eventually be processed.
  SbBlitterFlushContext(context_);

  // Flip the swap chain to reveal our masterpiece to the user.
  SbBlitterFlipSwapChain(swap_chain_);
  ++frame_;

  // Schedule another frame render ASAP.
  SbEventSchedule(&Application::RenderSceneEventCallback, this, 0);
}

Application* s_application = NULL;

// Simple Starboard window event handling to kick off our blitter application.
void SbEventHandle(const SbEvent* event) {
  switch (event->type) {
    case kSbEventTypeStart: {
      // Create the application, after which it will use SbEventSchedule()
      // on itself to trigger a frame update until the application is
      // terminated.
      s_application = new Application();
    } break;

    case kSbEventTypeStop: {
      // Shutdown the application.
      delete s_application;
    } break;

    default: {}
  }
}

#else  // SB_HAS(BLITTER)

void SbEventHandle(const SbEvent* event) {
  switch (event->type) {
    case kSbEventTypeStart: {
      SB_LOG(ERROR)
          << "Starboard Blitter API is not available on this platform.";

      SbSystemRequestStop(0);
    } break;

    default: {}
  }
}

#endif  // SB_HAS(BLITTER)
