/*
 * Copyright 2015 Google Inc. 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/render_tree_pixel_tester.h"

#include <algorithm>
#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "cobalt/renderer/backend/default_graphics_system.h"
#include "cobalt/renderer/backend/graphics_context.h"
#include "cobalt/renderer/backend/graphics_system.h"
#include "cobalt/renderer/backend/render_target.h"
#include "cobalt/renderer/rasterizer/rasterizer.h"
#include "cobalt/renderer/renderer_module.h"
#include "cobalt/renderer/test/png_utils/png_decode.h"
#include "cobalt/renderer/test/png_utils/png_encode.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"

// Avoid overriding of Windows' CreateDirectory macro.
#undef CreateDirectory

using cobalt::render_tree::ResourceProvider;
using cobalt::renderer::backend::GraphicsContext;
using cobalt::renderer::backend::GraphicsSystem;
using cobalt::renderer::backend::RenderTarget;
using cobalt::renderer::test::png_utils::DecodePNGToRGBA;
using cobalt::renderer::test::png_utils::EncodeRGBAToPNG;

namespace cobalt {
namespace renderer {

RenderTreePixelTester::Options::Options()
    : gaussian_blur_sigma(6.2f),
      acceptable_channel_range(0.08f),
      output_failed_test_details(false),
      output_all_test_details(false) {}

RenderTreePixelTester::RenderTreePixelTester(
    const math::Size& test_surface_dimensions,
    const FilePath& expected_results_directory,
    const FilePath& output_directory, const Options& options)
    : expected_results_directory_(expected_results_directory),
      output_directory_(output_directory),
      options_(options) {
  graphics_system_ = cobalt::renderer::backend::CreateDefaultGraphicsSystem();
  graphics_context_ = graphics_system_->CreateGraphicsContext();

  // Create our offscreen surface that will be the target of our test
  // rasterizations.
  test_surface_ =
      graphics_context_->CreateOffscreenRenderTarget(test_surface_dimensions);

  // Create the rasterizer using the platform default RenderModule options.
  RendererModule::Options render_module_options;
  rasterizer_ = render_module_options.create_rasterizer_function.Run(
      graphics_context_.get(), render_module_options);
}

RenderTreePixelTester::~RenderTreePixelTester() {}

ResourceProvider* RenderTreePixelTester::GetResourceProvider() const {
  return rasterizer_->GetResourceProvider();
}

namespace {

// Convenience function that will modify a base file path (without an
// extension) to include a postfix and an extension.
// e.g. ModifyBaseFileName("output/tests/my_test", "-expected", "png")
//      will return "output/tests/my_test-expected.png".
FilePath ModifyBaseFileName(const FilePath& base_file_name,
                            const std::string& postfix,
                            const std::string& extension) {
  return base_file_name.InsertBeforeExtension(postfix).AddExtension(extension);
}

// This utility function will take a SkBitmap and perform a Gaussian blur on
// it, returning a new, blurred SkBitmap.  The sigma parameter defines how
// strong the blur should be.
SkBitmap BlurBitmap(const SkBitmap& bitmap, float sigma) {
  SkBitmap premul_alpha_bitmap;
  if (bitmap.info().colorType() == kN32_SkColorType &&
      bitmap.info().alphaType() == kPremul_SkAlphaType) {
    premul_alpha_bitmap = bitmap;
  } else {
    // We need to convert our image to premultiplied alpha and N32 color
    // before proceeding to blur them, as Skia is designed to primarily deal
    // only with images in this format.
    SkImageInfo premul_alpha_image_info = SkImageInfo::Make(
        bitmap.width(), bitmap.height(), kN32_SkColorType, kPremul_SkAlphaType);
    premul_alpha_bitmap.allocPixels(premul_alpha_image_info);
    bitmap.readPixels(premul_alpha_image_info, premul_alpha_bitmap.getPixels(),
                      premul_alpha_bitmap.rowBytes(), 0, 0);
  }
  SkBitmap blurred_bitmap;
  blurred_bitmap.allocPixels(SkImageInfo::Make(
      bitmap.width(), bitmap.height(), kN32_SkColorType, kPremul_SkAlphaType));

  SkPaint paint;
  SkAutoTUnref<SkBlurImageFilter> blur_filter(
      SkBlurImageFilter::Create(sigma, sigma));
  paint.setImageFilter(blur_filter);

  SkCanvas canvas(blurred_bitmap);
  canvas.clear(SkColorSetARGB(0, 0, 0, 0));
  canvas.drawBitmap(premul_alpha_bitmap, 0, 0, &paint);

  return blurred_bitmap;
}

bool BitmapsAreEqual(const SkBitmap& bitmap_a, const SkBitmap& bitmap_b) {
  if (bitmap_a.height() != bitmap_b.height() ||
      bitmap_a.rowBytes() != bitmap_b.rowBytes()) {
    return false;
  }

  SkAutoLockPixels lock_a(bitmap_a);
  SkAutoLockPixels lock_b(bitmap_b);
  void* pixels_a = reinterpret_cast<void*>(bitmap_a.getPixels());
  void* pixels_b = reinterpret_cast<void*>(bitmap_b.getPixels());
  size_t byte_count = bitmap_a.rowBytes() * bitmap_a.height();
  return memcmp(pixels_a, pixels_b, byte_count) == 0;
}

// Compares bitmap_a with bitmap_b, where the comparison is done by checking
// each pixel to see if any one of its color channel values differ between
// bitmap_a to bitmap_b by more than acceptable_channel_range.  If so,
// number_of_diff_pixels is incremented and the corresponding pixel in the
// returned diff SkBitmap is set to white with full alpha.  If the pixel color
// channel values are not found to differ significantly, the corresponding
// pixel in the returned diff SkBitmap is set to black with no alpha.
SkBitmap DiffBitmaps(const SkBitmap& bitmap_a, const SkBitmap& bitmap_b,
                     int acceptable_channel_range, int* number_of_diff_pixels) {
  // Construct a diff bitmap where we can place the results of our diff,
  // allowing us to mark which pixels differ between bitmap_a and bitmap_b.
  SkBitmap bitmap_diff;
  bitmap_diff.allocPixels(SkImageInfo::Make(bitmap_a.width(), bitmap_a.height(),
                                            kRGBA_8888_SkColorType,
                                            kUnpremul_SkAlphaType));

  // Initialize the number of pixels that we have found to differ significantly
  // from bitmap_a to bitmap_b to 0.
  *number_of_diff_pixels = 0;
  // Start checking for pixel differences row by row.
  for (int r = 0; r < bitmap_a.height(); ++r) {
    const uint8_t* pixels_a =
        static_cast<uint8_t*>(bitmap_a.pixelRef()->pixels()) +
        bitmap_a.rowBytes() * r;
    const uint8_t* pixels_b =
        static_cast<uint8_t*>(bitmap_b.pixelRef()->pixels()) +
        bitmap_b.rowBytes() * r;
    // Since the diff image will be set to either all black or all white, we
    // reference its pixels with a uint32_t since it simplifies writing to it.
    uint32_t* pixels_diff =
        static_cast<uint32_t*>(bitmap_diff.pixelRef()->pixels()) +
        bitmap_diff.rowBytes() * r / sizeof(uint32_t);
    for (int c = 0; c < bitmap_a.width(); ++c) {
      // Check each pixel in the current row for differences.  We do this by
      // looking at each color channel seperately and taking the max of the
      // differences we see in each channel.
      int max_diff = 0;
      for (int i = 0; i < 4; ++i) {
        max_diff = std::max(max_diff, std::abs(pixels_a[i] - pixels_b[i]));
      }

      // If the maximum color channel difference is larger than the acceptable
      // error range, we count one diff pixel and adjust the diff SkBitmap
      // accordingly.
      if (max_diff > acceptable_channel_range) {
        ++*number_of_diff_pixels;
        // Set the diff image pixel to all white with full alpha.
        *pixels_diff = 0xFF0000FF;
      } else {
        // Set the diff image pixel to all black with no alpha.
        *pixels_diff = 0x00000000;
      }

      // Get ready for the next pixel in the row.
      pixels_a += 4;
      pixels_b += 4;
      pixels_diff += 1;
    }
  }

  return bitmap_diff;
}

// Helper function to simplify the process of encoding a Skia RGBA8 SkBitmap
// object to a PNG file.
void EncodeSkBitmapToPNG(const FilePath& output_file, const SkBitmap& bitmap) {
  if (bitmap.info().alphaType() == kUnpremul_SkAlphaType &&
      bitmap.info().colorType() == kRGBA_8888_SkColorType) {
    // No conversion needed here, simply write out the pixels as is.
    EncodeRGBAToPNG(output_file,
                    static_cast<uint8_t*>(bitmap.pixelRef()->pixels()),
                    bitmap.width(), bitmap.height(), bitmap.rowBytes());
  } else {
    // First convert the pixels to the proper format and then output them.
    SkImageInfo output_image_info =
        SkImageInfo::Make(bitmap.width(), bitmap.height(),
                          kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
    scoped_array<uint8_t> pixels(
        new uint8_t[output_image_info.minRowBytes() * bitmap.height()]);

    // Reformat and copy the pixel data into our fresh pixel buffer.
    bitmap.readPixels(output_image_info, pixels.get(),
                      output_image_info.minRowBytes(), 0, 0);

    // Write the pixels out to disk.
    EncodeRGBAToPNG(output_file, pixels.get(), bitmap.width(), bitmap.height(),
                    output_image_info.minRowBytes());
  }
}

// Given a chunk of memory formatted as RGBA8 with pitch = width * 4, this
// function will wrap that memory in a SkBitmap that does *not* own the
// pixels and return that.
const SkBitmap CreateBitmapFromRGBAPixels(const math::SizeF& dimensions,
                                          const uint8_t* pixels) {
  const int kRGBABytesPerPixel = 4;
  SkBitmap bitmap;
  bitmap.installPixels(
      SkImageInfo::Make(dimensions.width(), dimensions.height(),
                        kRGBA_8888_SkColorType, kUnpremul_SkAlphaType),
      const_cast<uint8_t*>(pixels), dimensions.width() * kRGBABytesPerPixel);
  return bitmap;
}

bool TestActualAgainstExpectedBitmap(float gaussian_blur_sigma,
                                     float acceptable_channel_range,
                                     const SkBitmap& expected_bitmap,
                                     const SkBitmap& actual_bitmap,
                                     const FilePath& output_base_filename,
                                     bool output_failed_test_details,
                                     bool output_all_test_details) {
  DCHECK_EQ(kRGBA_8888_SkColorType, expected_bitmap.colorType());
  DCHECK_EQ(kRGBA_8888_SkColorType, actual_bitmap.colorType());

  // We can try an exact comparison if we don't need to dump out the
  // diff and blur images.
  bool quick_test_ok = !output_failed_test_details && !output_all_test_details;

  if (quick_test_ok && BitmapsAreEqual(expected_bitmap, actual_bitmap)) {
    return true;
  }

  // We first blur both the actual and expected bitmaps before testing them.
  // This is done to permit small 1 or 2 pixel translation differences in the
  // images.  If these small differences are not acceptable, the blur amount
  // specified by gaussian_blur_sigma should be lowered to make the tests
  // stricter.
  SkBitmap blurred_actual_bitmap =
      BlurBitmap(actual_bitmap, gaussian_blur_sigma);
  SkBitmap blurred_expected_bitmap =
      BlurBitmap(expected_bitmap, gaussian_blur_sigma);

  // Diff the blurred actual image with the blurred expected image and
  // count how many pixels are out of range.
  int number_of_diff_pixels = 0;
  SkBitmap diff_image =
      DiffBitmaps(blurred_expected_bitmap, blurred_actual_bitmap,
                  acceptable_channel_range * 255, &number_of_diff_pixels);

  // If the user has requested it via command-line flags, we can also output
  // the images that were used by this test to help debug any problems.
  if (output_all_test_details ||
      (number_of_diff_pixels > 0 && output_failed_test_details)) {
    file_util::CreateDirectory(output_base_filename.DirName());

    EncodeSkBitmapToPNG(
        ModifyBaseFileName(output_base_filename, "-actual", "png"),
        actual_bitmap);
    EncodeSkBitmapToPNG(
        ModifyBaseFileName(output_base_filename, "-expected", "png"),
        expected_bitmap);
    EncodeSkBitmapToPNG(
        ModifyBaseFileName(output_base_filename, "-actual-blurred", "png"),
        blurred_actual_bitmap);
    EncodeSkBitmapToPNG(
        ModifyBaseFileName(output_base_filename, "-expected-blurred", "png"),
        blurred_expected_bitmap);
    EncodeSkBitmapToPNG(
        ModifyBaseFileName(output_base_filename, "-diff", "png"), diff_image);
  }

  // Execute the main check for this rasterizer test:  Are all pixels
  // in the generated image in the given range of the expected image
  // pixels.
  return number_of_diff_pixels == 0;
}
}  // namespace

scoped_array<uint8_t> RenderTreePixelTester::RasterizeRenderTree(
    const scoped_refptr<cobalt::render_tree::Node>& tree) const {
  // Rasterize the test render tree to the rasterizer's offscreen render target.
  rasterizer_->Submit(tree, test_surface_,
                      rasterizer::Rasterizer::kSubmitOptions_Clear);

  // Load the texture's pixel data into a CPU memory buffer and return it.
  return graphics_context_->DownloadPixelDataAsRGBA(test_surface_);
}

void RenderTreePixelTester::Rebaseline(
    const scoped_refptr<cobalt::render_tree::Node>& test_tree,
    const FilePath& expected_base_filename) const {
  scoped_array<uint8_t> test_image_pixels = RasterizeRenderTree(test_tree);

  // Wrap the generated image's raw RGBA8 pixel data in a SkBitmap so that
  // we can manipulate it using Skia.
  const SkBitmap actual_bitmap = CreateBitmapFromRGBAPixels(
      test_surface_->GetSize(), test_image_pixels.get());

  FilePath output_base_filename(
      output_directory_.Append(expected_base_filename));

  // Create the output directory if it doesn't already exist.
  file_util::CreateDirectory(output_base_filename.DirName());

  // If the 'rebase' flag is set, we should not run any actual tests but
  // instead output the results of our tests so that they can be used as
  // expected output for subsequent tests.
  EncodeSkBitmapToPNG(
      ModifyBaseFileName(output_base_filename, "-expected", "png"),
      actual_bitmap);
}

bool RenderTreePixelTester::TestTree(
    const scoped_refptr<cobalt::render_tree::Node>& test_tree,
    const FilePath& expected_base_filename) const {
  scoped_array<uint8_t> test_image_pixels = RasterizeRenderTree(test_tree);

  // Wrap the generated image's raw RGBA8 pixel data in a SkBitmap so that
  // we can manipulate it using Skia.
  const SkBitmap actual_bitmap = CreateBitmapFromRGBAPixels(
      test_surface_->GetSize(), test_image_pixels.get());

  // Here we proceed with the the pixel tests.  We must first load the
  // expected output image from disk and use that to compare against
  // the synthesized image.
  int expected_width;
  int expected_height;
  FilePath expected_output_file = expected_results_directory_.Append(
      ModifyBaseFileName(expected_base_filename, "-expected", "png"));
  if (!file_util::PathExists(expected_output_file)) {
    DLOG(WARNING) << "Expected pixel test output file \""
                  << expected_output_file.value() << "\" cannot be found.";
    // If the expected output file does not exist, we cannot continue, so
    // return in failure.
    return false;
  }
  scoped_array<uint8_t> expected_image_pixels =
      DecodePNGToRGBA(expected_output_file, &expected_width, &expected_height);

  DCHECK_EQ(test_surface_->GetSize().width(), expected_width);
  DCHECK_EQ(test_surface_->GetSize().height(), expected_height);

  // We then wrap the expected image in a SkBitmap so that we can manipulate
  // it with Skia.
  const SkBitmap expected_bitmap = CreateBitmapFromRGBAPixels(
      test_surface_->GetSize(), expected_image_pixels.get());

  // Finally we perform the actual pixel tests on the bitmap given the
  // actual and expected bitmaps.  If it is requested that test details
  // be output, then this function call may have the side effect of generating
  // these details as output files.
  return TestActualAgainstExpectedBitmap(
      options_.gaussian_blur_sigma, options_.acceptable_channel_range,
      expected_bitmap, actual_bitmap,
      output_directory_.Append(expected_base_filename),
      options_.output_failed_test_details, options_.output_all_test_details);
}

}  // namespace renderer
}  // namespace cobalt
