/*
 * 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) const {
    cl_int imageErr;
    cl_image_format bitmapFormat;
    switch (bitmap->colorType()) {
        case kAlpha_8_SkColorType:
            bitmapFormat.image_channel_order = CL_A;
            bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
            break;
        case kRGB_565_SkColorType:
            bitmapFormat.image_channel_order = CL_RGB;
            bitmapFormat.image_channel_data_type = CL_UNORM_SHORT_565;
            break;
        case kN32_SkColorType:
            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;
}
