#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <CL/cl.h>
#include <string.h>
#include "info.h"


struct screen {

        unsigned char red;
        unsigned char green;
        unsigned char blue;
        unsigned char alpha;
};

struct screen ***world;



//unsigned char global_array[1000][1000][300];

int main(int argc, const char** argv)
{

        char                  Buffer[1024];
        char                  Temp[2];
	cl_uint               intbuffer;
        cl_uint               num_devices;
        cl_device_id          *devices;
	cl_device_id          device_id;
	cl_device_type        device_type;

        cl_uint               i, j, k;
	cl_int                Error;
        
	cl_uint               num_entries;
	cl_platform_id        *platforms;
	cl_uint               num_platforms;
	cl_platform_id        platform;
	cl_platform_id        SelectedPlatformID = NULL;
	cl_platform_info      param_name;
	cl_uint                param_value_size;
	char                  *param_value;
	cl_uint                *param_value_size_ret;

	cl_context            context;
	cl_context            context_r;
	cl_command_queue      command;
	cl_mem                gpu_buffer1;
	void                  *buffer_ptr;

	int X = 2048;
	int Y = 1536;

    world= (struct screen ***)malloc(10*sizeof(struct screen *) );
    for( i=0; i<10 ; i++ )
    {
        world[ i ] = ( struct screen **)malloc(X* sizeof(struct screen **) );   
        for( j=0; j<X; j++)
        {
            world[ i ][ j ] = ( struct screen *)malloc(Y* sizeof(struct screen ***) );
        }               
    }



	//const char device_info[] = "CL_DEVICE_TYPE";
	//cl_device_info device_info = CL_DEVICE_TYPE;
//cl_device_info device_info = 3000;
//CL_DEVICE_MAX_COMPUTE_UNITS
//";



	Error = clGetPlatformIDs(1, &platform, &num_platforms);
	if(Error != CL_SUCCESS) {
		printf("Error: clGetPlatformIDs - %u\n", Error);
		exit(1);
	}
	printf("number of platforms: %d\n", num_platforms);

	//param_value = Buffer;
	param_value_size = sizeof(Buffer);
	for(i=1; i <= num_platforms; i++) {
		printf("\tPlatform: %u\n", i);
		//platforms=&i;
		//param_name = "CL_PLATFORM_VERSION";
		Error = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, param_value_size, &Buffer, NULL);
        	if(Error != CL_SUCCESS) {
                	printf("Error: clGetPlatformInfo - %u\n", Error);
			exit(1);
        	}
        	printf("\t\tCL_PLATFORM_VERSION: %s\n", Buffer);

		//param_name = "CL_PLATFORM_NAME";
		Error = clGetPlatformInfo(platform, CL_PLATFORM_NAME, param_value_size, &Buffer, NULL);
                if(Error != CL_SUCCESS) {
                        printf("Error: clGetPlatformInfo - %u\n", Error);
			exit(1);
                }
                printf("\t\tCL_PLATFORM_NAME: %s\n", Buffer);  

		//param_name = "CL_PLATFORM_VENDOR";
		Error = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, param_value_size, &Buffer, NULL);
                if(Error != CL_SUCCESS) {
                        printf("Error: clGetPlatformInfo - %u\n", Error);
			exit(1);
                }
                printf("\t\tCL_PLATFORM_VENDOR: %s\n", Buffer);  

		//param_name = "CL_PLATFORM_EXTENSIONS";
		Error = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, param_value_size, &Buffer, NULL);
                if(Error != CL_SUCCESS) {
                        printf("Error: clGetPlatformInfo - %u\n", Error);
			exit(1);
                }
                printf("\t\tCL_PLATFORM_EXTENSIONS: %s\n", Buffer);

                Error = clGetPlatformInfo(platform, CL_PLATFORM_PROFILE, param_value_size, &Buffer, NULL);
                if(Error != CL_SUCCESS) {
                        printf("Error: clGetPlatformInfo - %u\n", Error);
                        exit(1);
                }
                printf("\t\tCL_PLATFORM_PROFILE: %s\n", Buffer);     
	


		Error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);

		if (num_devices == 0) {
			printf("Error: no opencl devices found!\n");
                }else if(Error != CL_SUCCESS) {
                        printf("Error: clGetDeviceIDs3 - %u\n", Error);
                        exit(1);
                }else if ( ( devices = (cl_device_id*)malloc(sizeof(cl_device_id) * num_devices) )  != NULL ) {
			printf("\t\tNumer Of Devices: %u\n", num_devices);
			Error = clGetDeviceIDs (platform, CL_DEVICE_TYPE_ALL, num_devices, devices, &num_devices);
			if(Error == CL_SUCCESS) {
				for(j=0; j < num_devices; j++) {
					printf("\t\t\tDevice %d:\n", j+1);	
					DeviceInfo(devices[j]);

					context = clCreateContext(NULL , 1, &devices[j], NULL, NULL, &Error);
					if(Error != CL_SUCCESS) {
						printf("Error: clCreateContext - %u\n", Error);
						exit(1);
					}
printf("here: %d\n", context);
					Error = clGetContextInfo(context,CL_CONTEXT_REFERENCE_COUNT , sizeof(intbuffer), &intbuffer, 
						NULL); 
					if(Error != CL_SUCCESS) {
						printf("Error: clGetContextInfo - %u\n", Error);
						exit(1);
					}
printf("here: %d\n", context);
					printf("Device_id: %d\n", intbuffer);

					command = clCreateCommandQueue(context, devices[j], CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
							&Error);
					if(Error != CL_SUCCESS) {
						printf("Error: clCreateCommandQueue - %u\n", Error);
						exit(1);
					}
					printf("command queue created\n");
					
					Error = clGetCommandQueueInfo(command,CL_QUEUE_DEVICE , sizeof(device_id), &device_id,
						NULL);
					if(Error != CL_SUCCESS) {
						printf("Error: clGetCommandQueueInfo - %u\n", Error);
						exit(1);
					}
					printf("Queue_Device: %d\n", device_id);

					Error = clGetCommandQueueInfo(command,CL_QUEUE_CONTEXT, sizeof(context_r), &context_r,NULL);
					if(Error != CL_SUCCESS) {
						printf("Error: clGetCommandQueueInfo - %u\n", Error);
						exit(1);
					}
					printf("Queue_Context: %d\n", context_r);

					intbuffer = sizeof(struct screen ***)*10*2048*1536;
					gpu_buffer1 = clCreateBuffer(context, CL_MEM_READ_WRITE,intbuffer,&world ,&Error);
					if(Error != CL_SUCCESS) {
						printf("Error: clCreateBuffer - %u\n", Error);
						exit(1);
					}
					printf("buffer object created\n");


buffer_ptr = clEnqueueMapBuffer(command, gpu_buffer1, 1, CL_MAP_READ, 0, intbuffer, 0, NULL, NULL, &Error); 
					if(Error != CL_SUCCESS) {
						printf("Error: clCreateBuffer - %u\n", Error);
						exit(1);
					}
					printf("%u MB of object mapped\n", intbuffer/1024/1024);

					sleep(30);

/*					Error = clGetDeviceInfo(devices[j], CL_DEVICE_NAME, param_value_size, &Buffer, NULL);
					if(Error != CL_SUCCESS) {
						printf("Error: clGetDeviceInfo - %u\n", Error);
						exit(1);
					}
					printf("\t\t\t\tCL_DEVICE_NAME: %s\n", Buffer);
					//for(k=4100; k <= 4200; k++) {
                                       		Error = clGetDeviceInfo(devices[j],CL_DEVICE_ADDRESS_BITS , param_value_size, &intbuffer, NULL);
                                        	//if(Error != CL_SUCCESS) {
                                                //	printf("Error: clGetDeviceInfo - %u\n", Error);
                                                //	exit(1);
                                        	//}
						if(Buffer[0] != '\01'){
                                        		printf("\t\t\t\t%d: %d\n",CL_DEVICE_MAX_CLOCK_FREQUENCY , intbuffer);
						}
					//}
				*/

				}
			}

		}
/*
CL_DEVICE_TYPE
CL_DEVICE_VENDOR_ID
CL_DEVICE_MAX_COMPUTE_UNITS
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
CL_DEVICE_MAX_WORK_ITEM_SIZES
CL_DEVICE_MAX_WORK_GROUP_SIZE
CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
CL_DEVICE_MAX_CLOCK_FREQUENCY
CL_DEVICE_ADDRESS_BITS
CL_DEVICE_GLOBAL_MEM_SIZE
CL_DEVICE_MAX_MEM_ALLOC_SIZE
CL_DEVICE_IMAGE_SUPPORT
CL_DEVICE_MAX_READ_IMAGE_ARGS
CL_DEVICE_MAX_WRITE_IMAGE_ARGS
CL_DEVICE_IMAGE2D_MAX_WIDTH
CL_DEVICE_IMAGE2D_MAX_HEIGHT
CL_DEVICE_IMAGE3D_MAX_WIDTH
CL_DEVICE_IMAGE3D_MAX_HEIGHT
CL_DEVICE_IMAGE3D_MAX_DEPTH
CL_DEVICE_MAX_SAMPLERS
CL_DEVICE_MAX_PARAMETER_SIZE
CL_DEVICE_MEM_BASE_ADDR_ALIGN
CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
CL_DEVICE_SINGLE_FP_CONFIG
CL_DEVICE_GLOBAL_MEM_CACHE_TYPE
CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
CL_DEVICE_MAX_CONSTANT_ARGS
CL_DEVICE_LOCAL_MEM_TYPE
CL_DEVICE_LOCAL_MEM_SIZE
CL_DEVICE_ERROR_CORRECTION_SUPPORT
CL_DEVICE_PROFILING_TIMER_RESOLUTION
CL_DEVICE_ENDIAN_LITTLE
CL_DEVICE_AVAILABLE
CL_DEVICE_COMPILER_AVAILABLE
CL_DEVICE_EXECUTION_CAPABILITIES
CL_DEVICE_QUEUE_PROPERTIES
CL_DEVICE_PLATFORM
CL_DEVICE_NAME
CL_DEVICE_VENDOR
CL_DRIVER_VERSION
CL_DEVICE_PROFILE
CL_DEVICE_VERSION
CL_DEVICE_EXTENSIONS
*/



	}

	return 0;
}

