/* * 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; }