1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include <cstring> 9 10 #include "SkBitmap.h" 11 #include "SkStream.h" 12 13 #include "SkCLImageDiffer.h" 14 #include "skpdiff_util.h" 15 16 SkCLImageDiffer::SkCLImageDiffer() { 17 fIsGood = false; 18 } 19 20 bool SkCLImageDiffer::init(cl_device_id device, cl_context context) { 21 fContext = context; 22 fDevice = device; 23 24 cl_int queueErr; 25 fCommandQueue = clCreateCommandQueue(fContext, fDevice, 0, &queueErr); 26 if (CL_SUCCESS != queueErr) { 27 SkDebugf("Command queue creation failed: %s\n", cl_error_to_string(queueErr)); 28 fIsGood = false; 29 return false; 30 } 31 32 fIsGood = this->onInit(); 33 return fIsGood; 34 } 35 36 bool SkCLImageDiffer::loadKernelFile(const char file[], const char name[], cl_kernel* kernel) { 37 // Open the kernel source file 38 SkFILEStream sourceStream(file); 39 if (!sourceStream.isValid()) { 40 SkDebugf("Failed to open kernel source file"); 41 return false; 42 } 43 44 return loadKernelStream(&sourceStream, name, kernel); 45 } 46 47 bool SkCLImageDiffer::loadKernelStream(SkStream* stream, const char name[], cl_kernel* kernel) { 48 // Read the kernel source into memory 49 SkString sourceString; 50 sourceString.resize(stream->getLength()); 51 size_t bytesRead = stream->read(sourceString.writable_str(), sourceString.size()); 52 if (bytesRead != sourceString.size()) { 53 SkDebugf("Failed to read kernel source file"); 54 return false; 55 } 56 57 return loadKernelSource(sourceString.c_str(), name, kernel); 58 } 59 60 bool SkCLImageDiffer::loadKernelSource(const char source[], const char name[], cl_kernel* kernel) { 61 // Build the kernel source 62 size_t sourceLen = strlen(source); 63 cl_program program = clCreateProgramWithSource(fContext, 1, &source, &sourceLen, NULL); 64 cl_int programErr = clBuildProgram(program, 1, &fDevice, "", NULL, NULL); 65 if (CL_SUCCESS != programErr) { 66 SkDebugf("Program creation failed: %s\n", cl_error_to_string(programErr)); 67 68 // Attempt to get information about why the build failed 69 char buildLog[4096]; 70 clGetProgramBuildInfo(program, fDevice, CL_PROGRAM_BUILD_LOG, sizeof(buildLog), 71 buildLog, NULL); 72 SkDebugf("Build log: %s\n", buildLog); 73 74 return false; 75 } 76 77 cl_int kernelErr; 78 *kernel = clCreateKernel(program, name, &kernelErr); 79 if (CL_SUCCESS != kernelErr) { 80 SkDebugf("Kernel creation failed: %s\n", cl_error_to_string(kernelErr)); 81 return false; 82 } 83 84 return true; 85 } 86 87 bool SkCLImageDiffer::makeImage2D(SkBitmap* bitmap, cl_mem* image) const { 88 cl_int imageErr; 89 cl_image_format bitmapFormat; 90 switch (bitmap->config()) { 91 case SkBitmap::kA8_Config: 92 bitmapFormat.image_channel_order = CL_A; 93 bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8; 94 break; 95 case SkBitmap::kRGB_565_Config: 96 bitmapFormat.image_channel_order = CL_RGB; 97 bitmapFormat.image_channel_data_type = CL_UNORM_SHORT_565; 98 break; 99 case SkBitmap::kARGB_8888_Config: 100 bitmapFormat.image_channel_order = CL_RGBA; 101 bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8; 102 break; 103 default: 104 SkDebugf("Image format is unsupported\n"); 105 return false; 106 } 107 108 // Upload the bitmap data to OpenCL 109 bitmap->lockPixels(); 110 *image = clCreateImage2D(fContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, 111 &bitmapFormat, bitmap->width(), bitmap->height(), 112 bitmap->rowBytes(), bitmap->getPixels(), 113 &imageErr); 114 bitmap->unlockPixels(); 115 116 if (CL_SUCCESS != imageErr) { 117 SkDebugf("Input image creation failed: %s\n", cl_error_to_string(imageErr)); 118 return false; 119 } 120 121 return true; 122 } 123