/*
 * Copyright 2010 JogAmp Community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 * 
 *    1. Redistributions of source code must retain the above copyright notice, this list of
 *       conditions and the following disclaimer.
 * 
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
 *       of conditions and the following disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of JogAmp Community.
 */

package com.jogamp.opencl;

import com.jogamp.opencl.util.CLUtil;
import java.nio.ByteBuffer;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import java.nio.IntBuffer;
import org.junit.BeforeClass;
import org.junit.Test;

import static java.lang.System.*;

public class Bug458 {

    @BeforeClass
    public static void setUpClass() throws Exception {
        out.println("OS: " + System.getProperty("os.name"));
        out.println("ARCH: " + System.getProperty("os.arch"));
        out.println("VM: " + System.getProperty("java.vm.name"));
        out.println("lib path: " + System.getProperty("java.library.path"));
    }
    
    private final static String programSource =""
//             + " #pragma OPENCL EXTENSION cl_khr_fp64: enable   \n"
             +"   __kernel void sobel( __global float* input, __global float* output, int width,  int height ) {     \n"
             +"       int x = get_global_id(0);   \n"
             +"       int y = get_global_id(1);   \n"
             +"       int offset = y * width + x;   \n"
             +"                                                               \n"
             +"         float p0, p1, p2, p3, p5, p6, p7, p8 = 0;            \n"
             +"                                                               \n"
             +"                                                               \n"
             +"              if( x < 1 || y < 1 || x > width - 2 || y > height - 2 )   \n"
             +"              {   \n"
             +"                 output[offset] = 0;   \n"
             +"              }   \n"
             +"              else   \n"
             +"              {   \n"
             +"                  p0 = input[offset - width - 1] ;   \n"
             +"                  p1 = input[offset - width] ;   \n"
             +"                  p2 = input[offset - width + 1] ;   \n"
             +"                  p3 = input[offset - 1] ;   \n"
             +"                  p5 = input[offset + 1] ;   \n"
             +"                  p6 = input[offset + width - 1] ;   \n" 
             +"                  p7 = input[offset + width] ;   \n"
             +"                  p8 = input[offset + width + 1] ;   \n" 
             +"   \n"
             +"                  float sum1 = p0 + 2*p1 + p2 - p6 - 2*p7 - p8;  //GY   \n"
             +"                  float sum2 = p0 + 2*p3 + p6 - p2 - 2*p5 - p8;  //GX   \n"
             +"   \n"
             +"                  output[offset] = sqrt(  sum1*sum1 + sum2*sum2 );   \n"
             +"              }   \n"
             +"      }  "; 

    @Test
    public void buildProgramTest() {
        
        CLContext context = CLContext.create();
        
        try {
            System.out.println(context);
            System.out.println(context.getPlatform().getVersion());

            long contextID = context.ID;
            CL cl = CLPlatform.getLowLevelCLInterface();

            PointerBuffer buffer = (PointerBuffer) PointerBuffer.allocateDirect(1).put(programSource.length()).rewind();
            String[] srcArray = new String[]{programSource};

            IntBuffer uploadStatus = Buffers.newDirectIntBuffer(1);
            final long programID = cl.clCreateProgramWithSource(contextID, 1, srcArray, buffer, uploadStatus);
            checkError("on clCreateProgramWithSource", uploadStatus.get(0));

            // Build the program
            int buildStatus = cl.clBuildProgram(programID, 0, null, null, null);

            System.out.println("buffercontent: "+buffer.get(0));
            
            System.out.println("src: " + getProgramInfoString(cl, programID, CL.CL_PROGRAM_SOURCE));
            
            checkError("on clBuildProgram", buildStatus);
            System.out.println("-> success");
        } finally {
            context.release();
        }
    }
    
    private String getProgramInfoString(CL cl, long program, int flag) {

        PointerBuffer size = PointerBuffer.allocateDirect(1);

        int ret = cl.clGetProgramInfo(program, flag, 0, null, size);
        checkError("on clGetProgramInfo", ret);

        ByteBuffer buffer = Buffers.newDirectByteBuffer((int)size.get(0));

        ret = cl.clGetProgramInfo(program, flag, buffer.capacity(), buffer, null);
        checkError("on clGetProgramInfo", ret);

        return CLUtil.clString2JavaString(buffer, (int)size.get(0));
    }

    private void checkError(String msg, int ret) {
        if(ret != CL.CL_SUCCESS)
            throw CLException.newException(ret, msg);
    }
}
