blob: 66b5e7467165c4d00497b8f7a82031eaeb8c2e8e [file] [log] [blame]
//TODO: copyrights
#include "context.h"
#include "device_interface.h"
#include "propertylist.h"
#include "platform.h"
#include <cstring>
#include <cstdlib>
//#include <llvm/Support/TargetSelect.h>
using namespace Devices;
static void __stdcall default_pfn_notify(const char *, const void *, size_t, void *)
{
return;
}
Context::Context(const cl_context_properties *properties,
cl_uint num_devices,
const cl_device_id *devices,
void (CL_CALLBACK *pfn_notify)(const char *, const void *,
size_t, void *),
void *user_data,
cl_int *errcode_ret)
: Object(Object::T_Context, 0), p_properties(0), p_pfn_notify(pfn_notify),
p_user_data(user_data), p_devices(0), p_num_devices(0), p_props_len(0),
p_platform(0), wgl_handle(0), opengl_context_handle(0)
{
if(!p_pfn_notify)
p_pfn_notify = &default_pfn_notify;
// Intialize LLVM, this can be done more than one time per program
/*llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();*/
// Explore the properties
if(properties)
{
const unsigned char *props = (const unsigned char *)properties;
cl_context_properties prop;
size_t props_len = 0;
#define GET_PROP(type, var) \
var = *(const type *)props; \
props += sizeof(type); \
props_len += sizeof(type);
while(true)
{
GET_PROP(cl_context_properties, prop)
if(!prop)
break;
switch(prop)
{
case CL_CONTEXT_PLATFORM:
GET_PROP(cl_platform_id, p_platform);
break;
case CL_WGL_HDC_KHR:
GET_PROP(cl_context_properties, wgl_handle);
break;
case CL_GL_CONTEXT_KHR:
GET_PROP(cl_context_properties, opengl_context_handle);
break;
default:
*errcode_ret = CL_INVALID_PROPERTY;
return;
}
}
// properties may be allocated on the stack of the client application
// copy it into a real buffer
p_properties = (cl_context_properties *)std::malloc(props_len);
p_props_len = props_len;
if(!p_properties)
{
*errcode_ret = CL_OUT_OF_HOST_MEMORY;
return;
}
std::memcpy((void *)p_properties, (const void *)properties, props_len);
}
// Verify that the platform is good
if(p_platform != DEFAULT_PLATFORM)
{
*errcode_ret = CL_INVALID_PLATFORM;
return;
}
// Explore the devices
p_devices = (DeviceInterface **)std::malloc(num_devices * sizeof(DeviceInterface *));
p_num_devices = num_devices;
if(!p_devices)
{
*errcode_ret = CL_OUT_OF_HOST_MEMORY;
return;
}
for(cl_uint i = 0; i<num_devices; ++i)
{
cl_device_id device = devices[i];
if(device == 0)
{
*errcode_ret = CL_INVALID_DEVICE;
return;
}
// Verify that the device is available
cl_bool device_available;
*errcode_ret = device->info(CL_DEVICE_AVAILABLE,
sizeof(device_available),
&device_available,
0);
if(*errcode_ret != CL_SUCCESS)
return;
if(!device_available)
{
*errcode_ret = CL_DEVICE_NOT_AVAILABLE;
return;
}
// Add the device to the list
p_devices[i] = (DeviceInterface *)device;
}
}
Context::~Context()
{
if(p_properties)
std::free((void *)p_properties);
if(p_devices)
std::free((void *)p_devices);
}
cl_int Context::info(cl_context_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) const
{
void *value = 0;
size_t value_length = 0;
union {
cl_uint cl_uint_var;
};
switch(param_name)
{
case CL_CONTEXT_REFERENCE_COUNT:
SIMPLE_ASSIGN(cl_uint, references());
break;
case CL_CONTEXT_NUM_DEVICES:
SIMPLE_ASSIGN(cl_uint, p_num_devices);
break;
case CL_CONTEXT_DEVICES:
MEM_ASSIGN(p_num_devices * sizeof(DeviceInterface *), p_devices);
break;
case CL_CONTEXT_PROPERTIES:
MEM_ASSIGN(p_props_len, p_properties);
break;
default:
return CL_INVALID_VALUE;
}
if(param_value && param_value_size < value_length)
return CL_INVALID_VALUE;
if(param_value_size_ret)
*param_value_size_ret = value_length;
if(param_value && value_length /* CONTEXT_PROPERTIES can be of length 0 */)
std::memcpy(param_value, value, value_length);
return CL_SUCCESS;
}
bool Context::hasDevice(DeviceInterface *device) const
{
for(unsigned int i = 0; i<p_num_devices; ++i)
if(p_devices[i] == device)
return true;
return false;
}