/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <cstring>

#include "SkBitmap.h"
#include "SkStream.h"

#include "SkCLImageDiffer.h"
#include "skpdiff_util.h"

SkCLImageDiffer::SkCLImageDiffer() {
    fIsGood = false;
}

bool SkCLImageDiffer::init(cl_device_id device, cl_context context) {
    fContext = context;
    fDevice = device;

    cl_int queueErr;
    fCommandQueue = clCreateCommandQueue(fContext, fDevice, 0, &queueErr);
    if (CL_SUCCESS != queueErr) {
        SkDebugf("Command queue creation failed: %s\n", cl_error_to_string(queueErr));
        fIsGood = false;
        return false;
    }

    fIsGood = this->onInit();
    return fIsGood;
}

bool SkCLImageDiffer::loadKernelFile(const char file[], const char name[], cl_kernel* kernel) {
    // Open the kernel source file
    SkFILEStream sourceStream(file);
    if (!sourceStream.isValid()) {
        SkDebugf("Failed to open kernel source file");
        return false;
    }

    return loadKernelStream(&sourceStream, name, kernel);
}

bool SkCLImageDiffer::loadKernelStream(SkStream* stream, const char name[], cl_kernel* kernel) {
    // Read the kernel source into memory
    SkString sourceString;
    sourceString.resize(stream->getLength());
    size_t bytesRead = stream->read(sourceString.writable_str(), sourceString.size());
    if (bytesRead != sourceString.size()) {
        SkDebugf("Failed to read kernel source file");
        return false;
    }

    return loadKernelSource(sourceString.c_str(), name, kernel);
}

bool SkCLImageDiffer::loadKernelSource(const char source[], const char name[], cl_kernel* kernel) {
    // Build the kernel source
    size_t sourceLen = strlen(source);
    cl_program program = clCreateProgramWithSource(fContext, 1, &source, &sourceLen, NULL);
    cl_int programErr = clBuildProgram(program, 1, &fDevice, "", NULL, NULL);
    if (CL_SUCCESS != programErr) {
        SkDebugf("Program creation failed: %s\n", cl_error_to_string(programErr));

        // Attempt to get information about why the build failed
        char buildLog[4096];
        clGetProgramBuildInfo(program, fDevice, CL_PROGRAM_BUILD_LOG, sizeof(buildLog),
                              buildLog, NULL);
        SkDebugf("Build log: %s\n", buildLog);

        return false;
    }

    cl_int kernelErr;
    *kernel = clCreateKernel(program, name, &kernelErr);
    if (CL_SUCCESS != kernelErr) {
        SkDebugf("Kernel creation failed: %s\n", cl_error_to_string(kernelErr));
        return false;
    }

    return true;
}

bool SkCLImageDiffer::makeImage2D(SkBitmap* bitmap, cl_mem* image) {
    cl_int imageErr;
    cl_image_format bitmapFormat;
    switch (bitmap->config()) {
        case SkBitmap::kA8_Config:
            bitmapFormat.image_channel_order = CL_A;
            bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
            break;
        case SkBitmap::kRGB_565_Config:
            bitmapFormat.image_channel_order = CL_RGB;
            bitmapFormat.image_channel_data_type = CL_UNORM_SHORT_565;
            break;
        case SkBitmap::kARGB_8888_Config:
            bitmapFormat.image_channel_order = CL_RGBA;
            bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
            break;
        default:
            SkDebugf("Image format is unsupported\n");
            return false;
    }

    // Upload the bitmap data to OpenCL
    bitmap->lockPixels();
    *image = clCreateImage2D(fContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
                             &bitmapFormat, bitmap->width(), bitmap->height(),
                             bitmap->rowBytes(), bitmap->getPixels(),
                             &imageErr);
    bitmap->unlockPixels();

    if (CL_SUCCESS != imageErr) {
        SkDebugf("Input image creation failed: %s\n", cl_error_to_string(imageErr));
        return false;
    }

    return true;
}
