blob: d1e6958ab9f77cb1324ab545d19bc3699f87fe85 [file] [log] [blame]
commit-bot@chromium.orgbe19b9e2013-06-14 17:26:54 +00001/*
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
16SkCLImageDiffer::SkCLImageDiffer() {
17 fIsGood = false;
18}
19
commit-bot@chromium.orgbe19b9e2013-06-14 17:26:54 +000020bool 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
36bool 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
47bool 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
60bool 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];
zachr@google.com572b54d2013-06-28 16:27:33 +000070 clGetProgramBuildInfo(program, fDevice, CL_PROGRAM_BUILD_LOG, sizeof(buildLog),
71 buildLog, NULL);
commit-bot@chromium.orgbe19b9e2013-06-14 17:26:54 +000072 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
87bool SkCLImageDiffer::makeImage2D(SkBitmap* bitmap, cl_mem* image) {
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}