Skip to content

Commit

Permalink
ocl: init version for opencl abstract
Browse files Browse the repository at this point in the history
libva's alpha blending have limited support,
it only supports src&dest have same size.
It's inconvenience for real word application.
We'd better enable opencl based vpp functions.
It also a step stone for other vpp operation.
such as rotation,flips...etc
  • Loading branch information
xuguangxin committed Jan 10, 2016
1 parent 0f7cad9 commit 8bedf1f
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 0 deletions.
209 changes: 209 additions & 0 deletions ocl/oclcontext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
* oclcontext.cpp - abstract for opencl.
*
* Copyright (C) 2015 Intel Corporation
* Author: XuGuangxin<[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "common/log.h"
#include "oclcontext.h"

#include <stdio.h>
#include <iterator>
#include <vector>

using namespace std;

namespace YamiMediaCodec{

///internal class hold device id and make sure *.cl compile in serial
class OclDevice {

public:
static SharedPtr<OclDevice> getInstance();
bool createKernel(cl_context context, const char* name, cl_kernel& kernel);

private:
OclDevice();
bool init();
bool loadKernel_l(cl_context context, const char* name, cl_kernel& kernel);
bool loadFile(const char* path, vector<char>& dest);

static WeakPtr<OclDevice> m_instance;
static Lock m_lock;

//all operations need procted by m_lock
cl_platform_id m_platform;
cl_device_id m_device;
friend OclContext;

DISALLOW_COPY_AND_ASSIGN(OclDevice)

};

Lock OclDevice::m_lock;
WeakPtr<OclDevice> OclDevice::m_instance;

SharedPtr<OclContext> OclContext::create()
{
SharedPtr<OclContext> context(new OclContext);
if (!context->init())
context.reset();
return context;
}

OclContext::OclContext()
:m_context(0), m_queue(0)
{
}

OclContext::~OclContext()
{
clReleaseCommandQueue(m_queue);
clReleaseContext(m_context);
}

bool OclContext::init()
{
SharedPtr<OclDevice> device = OclDevice::getInstance();
if (!device)
return false;
m_device= device;
cl_int status;
AutoLock lock(device->m_lock);
m_context = clCreateContext(NULL, 1, &m_device->m_device, NULL,NULL,&status);
if (!checkOclStatus(status, "clCreateContext"))
return false;

m_queue = clCreateCommandQueue(m_context, m_device->m_device, 0, &status);
if (!checkOclStatus(status, "clCreateContext"))
return false;
return true;
}

bool OclContext::createKernel(const char* name, cl_kernel& kernel)
{
return m_device->createKernel(m_context, name, kernel);
}

OclDevice::OclDevice()
:m_platform(0), m_device(0)
{
}

SharedPtr<OclDevice> OclDevice::getInstance()
{
AutoLock lock(m_lock);
SharedPtr<OclDevice> device = m_instance.lock();
if (device)
return device;
device.reset(new OclDevice);
if (!device->init()) {
device.reset();
}
return device;
}

bool OclDevice::init()
{
cl_int status;
status = clGetPlatformIDs(1, &m_platform, NULL);
if (!checkOclStatus(status, "clGetPlatformIDs"))
return false;

status = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_GPU, 1, &m_device, NULL);
if (!checkOclStatus(status, "clGetDeviceIDs"))
return false;
return true;
}

bool OclDevice::loadFile(const char* path, vector<char>& dest)
{
FILE* fp = fopen(path, "rb");
if (!fp)
return false;
fseek(fp,0L,SEEK_END);
long len = ftell(fp);
if (len > 0) {
dest.resize(len + 1);
fseek(fp,0L,SEEK_SET);
if (len == fread(&dest[0], 1, len, fp)) {
dest.back() = '\0';
} else {
dest.clear();
}
}
fclose(fp);
return !dest.empty();
}

bool OclDevice::loadKernel_l(cl_context context, const char* name, cl_kernel& kernel)
{
kernel = 0;
string path = name;
path += ".cl";

vector<char> text;
if (!loadFile(path.c_str(), text)) {
ERROR("Can't open %s", path.c_str());
return false;
}
cl_int status;
const char* source = &text[0];
cl_program prog = clCreateProgramWithSource(context, 1, &source, NULL, &status);
if (!checkOclStatus(status, "clCreateProgramWithSource"))
return false;
status = clBuildProgram(prog, 1, &m_device, NULL, NULL, NULL);
if (!checkOclStatus(status, "clBuildProgram"))
{
char log[1024];
status = clGetProgramBuildInfo(prog, m_device, CL_PROGRAM_BUILD_LOG, sizeof(log), log, NULL);
if (checkOclStatus(status, "clCreateProgramWithSource")) {
//make sure null terminate
log[sizeof(log) - 1] = '\0';
ERROR("build cl kernel failed: %s", log);
}
} else {
kernel = clCreateKernel(prog, name, &status);
checkOclStatus(status, "clCreateKernel");
}
clReleaseProgram(prog);
return kernel != 0;
}

bool OclDevice::createKernel(cl_context context, const char* name, cl_kernel& kernel)
{
AutoLock lock(m_lock);
return loadKernel_l(context, name, kernel);
}

bool checkOclStatus(cl_int status, const char* msg)
{
/* todo add more description error here*/
if (status != CL_SUCCESS) {
ERROR("%s: failed, status = %d", msg, status);
return false;
}
return true;
}

}
55 changes: 55 additions & 0 deletions ocl/oclcontext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* oclcontext.h - abstract for opencl.
*
* Copyright (C) 2015 Intel Corporation
* Author: XuGuangxin<[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef oclcontext_h
#define oclcontext_h


#include "interface/VideoCommonDefs.h"
#include "common/lock.h"
#include <CL/opencl.h>
#include <CL/cl_intel.h>

namespace YamiMediaCodec{

class OclDevice;

class OclContext
{
public:
static SharedPtr<OclContext> create();
bool createKernel(const char* name, cl_kernel& kernel);
~OclContext();

cl_context m_context;
cl_command_queue m_queue;
private:
OclContext();
bool init();
SharedPtr<OclDevice> m_device;
DISALLOW_COPY_AND_ASSIGN(OclContext)
};

bool checkOclStatus(cl_int status, const char* err);

}

#endif //oclcontext_h

0 comments on commit 8bedf1f

Please sign in to comment.