Home | History | Annotate | Download | only in skpdiff
      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