ソースを参照

added customizability of the platforms and devices by PlatformChooser

shamanDevel 9 年 前
コミット
e02eec0abd

+ 26 - 80
jme3-core/src/main/java/com/jme3/opencl/Buffer.java

@@ -37,94 +37,40 @@ import java.nio.ByteBuffer;
  *
  * @author Sebastian Weiss
  */
-public class Buffer {
+public interface Buffer {
 
-	private final long buffer;
-
-	public Buffer(long buffer) {
-		this.buffer = buffer;
-	}
-	
-	public int getSize() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	int getSize();
 	
-	public MemoryAccess getMemoryAccessFlags() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	MemoryAccess getMemoryAccessFlags();
 	
-	public void read(CommandQueue queue, Buffer src, ByteBuffer dest, int size, int offset) {
-		queue.read(src, dest, size, offset);
-	}
-	public void read(CommandQueue queue, Buffer src, ByteBuffer dest, int size) {
-		queue.read(src, dest, size);
-	}
-	public void read(CommandQueue queue, Buffer src, ByteBuffer dest) {
-		queue.read(src, dest);
-	}
+	void read(CommandQueue queue, ByteBuffer dest, int size, int offset);
+	void read(CommandQueue queue, ByteBuffer dest, int size);
+    void read(CommandQueue queue, ByteBuffer dest);
 	
-	public Event readAsync(CommandQueue queue, Buffer src, ByteBuffer dest, int size, int offset) {
-		return queue.readAsync(src, dest, size, offset);
-	}
-	public Event readAsync(CommandQueue queue, Buffer src, ByteBuffer dest, int size) {
-		return queue.readAsync(src, dest, size);
-	}
-	public Event readAsync(CommandQueue queue, Buffer src, ByteBuffer dest) {
-		return queue.readAsync(src, dest);
-	}
+	Event readAsync(CommandQueue queue, ByteBuffer dest, int size, int offset);
+	Event readAsync(CommandQueue queue, ByteBuffer dest, int size);
+    Event readAsync(CommandQueue queue, ByteBuffer dest);
 	
-	public void write(CommandQueue queue, ByteBuffer src, Buffer dest, int size, int offset) {
-		queue.write(src, dest, size, offset);
-	}
-	public void write(CommandQueue queue, ByteBuffer src, Buffer dest, int size) {
-		queue.write(src, dest, size);
-	}
-	public void write(CommandQueue queue, ByteBuffer src, Buffer dest) {
-		queue.write(src, dest);
-	}
+	void write(CommandQueue queue, ByteBuffer src, int size, int offset);
+	void write(CommandQueue queue, ByteBuffer src, int size);
+    void write(CommandQueue queue, ByteBuffer src);
 	
-	public Event writeAsync(CommandQueue queue, ByteBuffer src, Buffer dest, int size, int offset) {
-		return queue.writeAsync(src, dest, size, offset);
-	}
-	public Event writeAsync(CommandQueue queue, ByteBuffer src, Buffer dest, int size) {
-		return queue.writeAsync(src, dest, size);
-	}
-	public Event writeAsync(CommandQueue queue, ByteBuffer src, Buffer dest) {
-		return queue.writeAsync(src, dest);
-	}
+	Event writeAsync(CommandQueue queue, ByteBuffer src, int size, int offset);
+	Event writeAsync(CommandQueue queue, ByteBuffer src, int size);
+    Event writeAsync(CommandQueue queue, ByteBuffer src);
 	
-	public void copyTo(CommandQueue queue, Buffer src, Buffer dest, int size, int srcOffset, int destOffset) {
-		queue.copyTo(src, dest, size, srcOffset, destOffset);
-	}
-	public void copyTo(CommandQueue queue, Buffer src, Buffer dest, int size) {
-		queue.copyTo(src, dest, size);
-	}
-	public void copyTo(CommandQueue queue, Buffer src, Buffer dest) {
-		queue.copyTo(src, dest);
-	}
-	
-	public Event copyToAsync(CommandQueue queue, Buffer src, Buffer dest, int size, int srcOffset, int destOffset) {
-		return queue.copyToAsync(src, dest, size, srcOffset, destOffset);
-	}
-	public Event copyToAsync(CommandQueue queue, Buffer src, Buffer dest, int size) {
-		return queue.copyToAsync(src, dest, size);
-	}
-	public Event copyToAsync(CommandQueue queue, Buffer src, Buffer dest) {
-		return queue.copyToAsync(src, dest);
-	}
+	void copyTo(CommandQueue queue, Buffer dest, int size, int srcOffset, int destOffset);
+    void copyTo(CommandQueue queue, Buffer dest, int size);
+    void copyTo(CommandQueue queue, Buffer dest);
+
+	Event copyToAsync(CommandQueue queue, Buffer dest, int size, int srcOffset, int destOffset);
+    Event copyToAsync(CommandQueue queue, Buffer dest, int size);
+    Event copyToAsync(CommandQueue queue, Buffer dest);
 	
-	public ByteBuffer map(CommandQueue queue, Buffer src, int size, int offset, MappingAccess access) {
-		return queue.map(src, size, offset, access);
-	}
-	public ByteBuffer map(CommandQueue queue, Buffer src, int size, MappingAccess access) {
-		return queue.map(src, size, access);
-	}
-	public ByteBuffer map(CommandQueue queue, Buffer src, MappingAccess access) {
-		return queue.map(src, access);
-	}
-	public void unmap(CommandQueue queue, Buffer src, ByteBuffer ptr) {
-		queue.unmap(src, ptr);
-	}
+	ByteBuffer map(CommandQueue queue, int size, int offset, MappingAccess access);
+	ByteBuffer map(CommandQueue queue, int size, MappingAccess access);
+    ByteBuffer map(CommandQueue queue, MappingAccess access);
+	void unmap(CommandQueue queue, ByteBuffer ptr);
 	
 	//TODO: async mapping
 	

+ 1 - 0
jme3-core/src/main/java/com/jme3/opencl/CL.java

@@ -38,6 +38,7 @@ import java.nio.*;
  *
  * @author Sebastian Weiss
  */
+@Deprecated
 public interface CL {
 
     //temp buffers for argument passing

+ 3 - 109
jme3-core/src/main/java/com/jme3/opencl/CommandQueue.java

@@ -37,116 +37,10 @@ import java.nio.ByteBuffer;
  *
  * @author Sebastian Weiss
  */
-public final class CommandQueue extends NativeCLObject {
+public interface CommandQueue {
 
-    private final long queue;
+    void flush();
 
-    public CommandQueue(long queue) {
-        this.queue = queue;
-    }
-
-    public void read(Buffer src, ByteBuffer dest, int size, int offset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public void read(Buffer src, ByteBuffer dest, int size) {
-        read(src, dest, size, 0);
-    }
-
-    public void read(Buffer src, ByteBuffer dest) {
-        read(src, dest, src.getSize(), 0);
-    }
-
-    public Event readAsync(Buffer src, ByteBuffer dest, int size, int offset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Event readAsync(Buffer src, ByteBuffer dest, int size) {
-        return readAsync(src, dest, size, 0);
-    }
-
-    public Event readAsync(Buffer src, ByteBuffer dest) {
-        return readAsync(src, dest, src.getSize());
-    }
-
-    public void write(ByteBuffer src, Buffer dest, int size, int offset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public void write(ByteBuffer src, Buffer dest, int size) {
-        write(src, dest, size, 0);
-    }
-
-    public void write(ByteBuffer src, Buffer dest) {
-        write(src, dest, dest.getSize());
-    }
-
-    public Event writeAsync(ByteBuffer src, Buffer dest, int size, int offset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Event writeAsync(ByteBuffer src, Buffer dest, int size) {
-        return writeAsync(src, dest, size, 0);
-    }
-
-    public Event writeAsync(ByteBuffer src, Buffer dest) {
-        return writeAsync(src, dest, dest.getSize());
-    }
-
-    public void copyTo(Buffer src, Buffer dest, int size, int srcOffset, int destOffset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public void copyTo(Buffer src, Buffer dest, int size) {
-        copyTo(src, dest, size, 0, 0);
-    }
-
-    public void copyTo(Buffer src, Buffer dest) {
-        copyTo(src, dest, src.getSize());
-    }
-
-    public Event copyToAsync(Buffer src, Buffer dest, int size, int srcOffset, int destOffset) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Event copyToAsync(Buffer src, Buffer dest, int size) {
-        return copyToAsync(src, dest, size, 0, 0);
-    }
-
-    public Event copyToAsync(Buffer src, Buffer dest) {
-        return copyToAsync(src, dest, src.getSize());
-    }
-
-    public ByteBuffer map(Buffer src, int size, int offset, MappingAccess access) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public ByteBuffer map(Buffer src, int size, MappingAccess access) {
-        return map(src, size, 0, access);
-    }
-
-    public ByteBuffer map(Buffer src, MappingAccess access) {
-        return map(src, src.getSize(), access);
-    }
-
-    public void unmap(Buffer src, ByteBuffer ptr) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-	//TODO: async mapping
-	//TODO: clEnqueueFillBuffer
-	//TODO: image read/write
-    public void flush() {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public void finish() {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    @Override
-    public void deleteObject() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
+    void finish();
 
 }

+ 18 - 78
jme3-core/src/main/java/com/jme3/opencl/Context.java

@@ -33,10 +33,6 @@ package com.jme3.opencl;
 
 import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.mesh.IndexBuffer;
-import com.jme3.scene.mesh.IndexByteBuffer;
-import com.jme3.scene.mesh.IndexIntBuffer;
-import com.jme3.scene.mesh.IndexShortBuffer;
-import com.jme3.texture.Image;
 import java.nio.ByteBuffer;
 import java.util.List;
 
@@ -45,43 +41,18 @@ import java.util.List;
  *
  * @author Sebastian Weiss
  */
-public final class Context extends NativeCLObject {
+public interface Context {
 
-    private final long context;
+    List<? extends Device> getDevices();
 
-    public Context(long context) {
-        this.context = context;
-    }
-
-    public List<? extends Device> getDevices() {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public CommandQueue createQueue() {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-	//TODO: constructor with specific device and properties
+    CommandQueue createQueue();
+	CommandQueue createQueue(Device device);
 
-    public Buffer createBuffer(int size, MemoryAccess access) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
+    Buffer createBuffer(int size, MemoryAccess access);
+    Buffer createBuffer(int size);
 
-    public Buffer createBuffer(int size) {
-        return createBuffer(size, MemoryAccess.READ_WRITE);
-    }
-
-    public Buffer useHostBuffer(ByteBuffer data, int size, MemoryAccess access) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Buffer useHostBuffer(ByteBuffer data, int size) {
-        return useHostBuffer(data, size, MemoryAccess.READ_WRITE);
-    }
-
-    @Override
-    public void deleteObject() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
+    Buffer useHostBuffer(ByteBuffer data, int size, MemoryAccess access);
+    Buffer useHostBuffer(ByteBuffer data, int size);
 
     public static enum ImageChannelOrder {
 
@@ -143,49 +114,18 @@ public final class Context extends NativeCLObject {
         public Buffer buffer;
     }
 
-    public Buffer createImage(MemoryAccess access, ImageFormat format, ImageDescriptor descr, ByteBuffer hostPtr) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
+    Image createImage(MemoryAccess access, ImageFormat format, ImageDescriptor descr, ByteBuffer hostPtr);
 	//TODO: add simplified methods for 1D, 2D, 3D textures
 
 	//Interop
-    public Buffer bindVertexBuffer(VertexBuffer vb) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Buffer bindIndexBuffer(IndexBuffer ib) {
-        if (!(ib instanceof IndexByteBuffer)
-                && !(ib instanceof IndexShortBuffer)
-                && !(ib instanceof IndexIntBuffer)) {
-            throw new IllegalArgumentException("Index buffer must be an IndexByteBuffer, IndexShortBuffer or IndexIntBuffer");
-        }
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Buffer bindImage(Image image) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Program createProgramFromSourceCode(String sourceCode) {
-        throw new UnsupportedOperationException("not supported yet");
-    }
-
-    public Program createProgramFromSourceFilesWithInclude(
-            String include, String... resources) {
-        //TODO: load resources
-        throw new UnsupportedOperationException("not implemented yet");
-    }
-
-    public Program createProgramFormSourcesWithInclude(String include, List<String> resources) {
-        return createProgramFromSourceFilesWithInclude(include, resources.toArray(new String[resources.size()]));
-    }
-
-    public Program createProgramFromSources(String... resources) {
-        return createProgramFromSourceFilesWithInclude(null, resources);
-    }
-
-    public Program createProgramFromSources(List<String> resources) {
-        return createProgramFormSourcesWithInclude(null, resources);
-    }
+    Buffer bindVertexBuffer(VertexBuffer vb);
+    Buffer bindIndexBuffer(IndexBuffer ib);
+    Image bindImage(com.jme3.texture.Image image);
+
+    Program createProgramFromSourceCode(String sourceCode);
+    Program createProgramFromSourceFilesWithInclude(String include, String... resources);
+    Program createProgramFormSourcesWithInclude(String include, List<String> resources);
+    Program createProgramFromSources(String... resources);
+    Program createProgramFromSources(List<String> resources);
 
 }

+ 46 - 118
jme3-core/src/main/java/com/jme3/opencl/Device.java

@@ -37,13 +37,10 @@ import java.util.Collection;
  *
  * @author Sebastian Weiss
  */
-public final class Device {
-	private final long device;
-
-	public Device(long device) {
-		this.device = device;
-	}
+public interface Device {
 	
+    Platform getPlatform();
+    
 	public static enum DeviceType {
 		DEFAULT,
 		CPU,
@@ -51,124 +48,55 @@ public final class Device {
 		ACCELEARTOR,
 		ALL
 	}
-	public DeviceType getDeviceType() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getVendorId() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean isAvailable() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getPCIeBus() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	DeviceType getDeviceType();
+	int getVendorId();
+	boolean isAvailable();
 	
-	public boolean hasCompiler() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasDouble() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasHalfFloat() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasErrorCorrectingMemory() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasUnifiedMemory() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasImageSupport() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean hasExtension(String extension) {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public Collection<? extends String> getExtensions() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	boolean hasCompiler();
+	boolean hasDouble();
+	boolean hasHalfFloat();
+	boolean hasErrorCorrectingMemory();
+	boolean hasUnifiedMemory();
+	boolean hasImageSupport();
+    boolean hasWritableImage3D();
+    boolean hasOpenGLInterop();
+	boolean hasExtension(String extension);
+	Collection<? extends String> getExtensions();
 	
-	public int getComputeUnits() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getClockFrequency() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getAddressBits() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public boolean isLittleEndian() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	int getComputeUnits();
+	int getClockFrequency();
+	int getAddressBits();
+	boolean isLittleEndian();
 	
-	public int getMaximumWorkItemDimensions() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int[] getMaximumWorkItemSizes() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getMaxiumWorkItemsPerGroup() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	long getMaximumWorkItemDimensions();
+	long[] getMaximumWorkItemSizes();
+	long getMaxiumWorkItemsPerGroup();
 	
-	public int getMaximumSamplers() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getMaximumReadImages() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getMaximumWriteImages() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int[] getMaximumImage2DSize() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int[] getMaximumImage3DSize() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	int getMaximumSamplers();
+	int getMaximumReadImages();
+	int getMaximumWriteImages();
+	long[] getMaximumImage2DSize();
+	long[] getMaximumImage3DSize();
 	
+    long getMaximumAllocationSize();
+    long getGlobalMemorySize();
+    long getLocalMemorySize();
+    long getMaximumConstantBufferSize();
+    int getMaximumConstantArguments();
+    
 	//TODO: cache, prefered sizes properties
 	
-	public String getProfile() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public String getVersion() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getVersionMajor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getVersionMinor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public String getCompilerVersion() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getCompilerVersionMajor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getCompilerVersionMinor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public String getDriverVersion() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getDriverVersionMajor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public int getDriverVersionMinor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public String getName() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
-	public String getVendor() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
+	String getProfile();
+	String getVersion();
+	int getVersionMajor();
+	int getVersionMinor();
+	String getCompilerVersion();
+	int getCompilerVersionMajor();
+	int getCompilerVersionMinor();
+	String getDriverVersion();
+	int getDriverVersionMajor();
+	int getDriverVersionMinor();
+	String getName();
+	String getVendor();
 
-	@Override
-	public String toString() {
-		throw new UnsupportedOperationException("not supported yet");
-	}
 }

+ 2 - 12
jme3-core/src/main/java/com/jme3/opencl/NativeCLObject.java → jme3-core/src/main/java/com/jme3/opencl/Image.java

@@ -35,16 +35,6 @@ package com.jme3.opencl;
  *
  * @author Sebastian Weiss
  */
-public abstract class NativeCLObject {
-	protected CL cl;
-
-	public CL getCl() {
-		return cl;
-	}
-
-	public void setCl(CL cl) {
-		this.cl = cl;
-	}
-	
-	public abstract void deleteObject();
+public interface Image {
+    
 }

+ 3 - 2
jme3-core/src/main/java/com/jme3/opencl/Kernel.java

@@ -39,8 +39,8 @@ import com.jme3.math.Vector4f;
  *
  * @author Sebastian Weiss
  */
-public final class Kernel extends NativeCLObject {
-
+public final class Kernel {
+/*
     private final WorkSize globalWorkSize;
     private final WorkSize workGroupSize;
     private final long kernel;
@@ -212,4 +212,5 @@ public final class Kernel extends NativeCLObject {
     public void deleteObject() {
         throw new UnsupportedOperationException("Not supported yet.");
     }
+*/
 }

+ 60 - 0
jme3-core/src/main/java/com/jme3/opencl/Platform.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public interface Platform {
+
+    List<? extends Device> getDevices();
+    
+    String getProfile();
+    boolean isFullProfile();
+    boolean isEmbeddedProfile();
+    
+    String getVersion();
+    int getVersionMajor();
+    int getVersionMinor();
+    
+    String getName();
+    String getVendor();
+    boolean hasOpenGLInterop();
+    boolean hasExtension(String extension);
+    Collection<? extends String> getExtensions();
+    
+    
+}

+ 54 - 0
jme3-core/src/main/java/com/jme3/opencl/PlatformChooser.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl;
+
+import com.jme3.system.AppSettings;
+import java.util.List;
+
+/**
+ * This SPI is called on startup to specify which platform and which devices
+ * are used for context creation.
+ * @author Sebastian Weiss
+ * @see AppSettings#setOpenCLPlatformChooser(java.lang.Class) 
+ */
+public interface PlatformChooser {
+    
+    /**
+     * Chooses one or more devices for the opencl context.
+     * All returned devices must belong to the same platform.
+     * If the returned list is empty, no context will be created.
+     * @param platforms the available platforms
+     * @return the list of devices
+     */
+    List<? extends Device> chooseDevices(List<? extends Platform> platforms);
+    
+}

+ 17 - 0
jme3-core/src/main/java/com/jme3/system/AppSettings.java

@@ -31,6 +31,7 @@
  */
 package com.jme3.system;
 
+import com.jme3.opencl.PlatformChooser;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -1033,4 +1034,20 @@ public final class AppSettings extends HashMap<String, Object> {
     public boolean isOpenCLSupport() {
         return getBoolean("OpenCL");
     }
+    
+    /**
+     * Sets a custom platform chooser. This chooser specifies which platform and
+     * which devices are used for the OpenCL context.
+     * 
+     * Default: not set, an implementation defined one is used.
+     * 
+     * @param chooser the class of the chooser, must have a default constructor
+     */
+    public void setOpenCLPlatformChooser(Class<? extends PlatformChooser> chooser) {
+        putString("OpenCLPlatformChooser", chooser.getName());
+    }
+    
+    public String getOpenCLPlatformChooser() {
+        return getString("OpenCLPlatformChooser");
+    }
 }

+ 136 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java

@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl.lwjgl;
+
+import com.jme3.opencl.*;
+import com.jme3.scene.VertexBuffer;
+import com.jme3.scene.mesh.IndexBuffer;
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.lwjgl.opencl.CLContext;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public class LwjglContext implements Context {
+    private final CLContext context;
+
+    public LwjglContext(CLContext context) {
+        this.context = context;
+    }
+
+    public CLContext getContext() {
+        return context;
+    }
+
+    @Override
+    public List<? extends Device> getDevices() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CommandQueue createQueue() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CommandQueue createQueue(Device device) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer createBuffer(int size, MemoryAccess access) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer createBuffer(int size) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer useHostBuffer(ByteBuffer data, int size, MemoryAccess access) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer useHostBuffer(ByteBuffer data, int size) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Image createImage(MemoryAccess access, ImageFormat format, ImageDescriptor descr, ByteBuffer hostPtr) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer bindVertexBuffer(VertexBuffer vb) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Buffer bindIndexBuffer(IndexBuffer ib) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Image bindImage(com.jme3.texture.Image image) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Program createProgramFromSourceCode(String sourceCode) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Program createProgramFromSourceFilesWithInclude(String include, String... resources) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Program createProgramFormSourcesWithInclude(String include, List<String> resources) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Program createProgramFromSources(String... resources) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Program createProgramFromSources(List<String> resources) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+    
+}

+ 293 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglDevice.java

@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl.lwjgl;
+
+import com.jme3.opencl.Device;
+import com.jme3.opencl.Platform;
+import java.util.Arrays;
+import java.util.Collection;
+import org.lwjgl.opencl.CL10;
+import org.lwjgl.opencl.CL11;
+import org.lwjgl.opencl.CLDevice;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public final class LwjglDevice implements Device {
+
+    final CLDevice device;
+    final LwjglPlatform platform;
+
+    public LwjglDevice(CLDevice device, LwjglPlatform platform) {
+        this.device = device;
+        this.platform = platform;
+    }
+    
+    public CLDevice getDevice() {
+        return device;
+    }
+    
+    @Override
+    public LwjglPlatform getPlatform() {
+        return platform;
+    }
+
+    @Override
+    public DeviceType getDeviceType() {
+        int type = device.getInfoInt(CL10.CL_DEVICE_TYPE);
+        switch (type) {
+            case CL10.CL_DEVICE_TYPE_ACCELERATOR: return DeviceType.ACCELEARTOR;
+            case CL10.CL_DEVICE_TYPE_CPU: return DeviceType.CPU;
+            case CL10.CL_DEVICE_TYPE_GPU: return DeviceType.GPU;
+            default: return DeviceType.DEFAULT;
+        }
+    }
+
+    @Override
+    public int getVendorId() {
+        return device.getInfoInt(CL10.CL_DEVICE_VENDOR_ID);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return device.getInfoBoolean(CL10.CL_DEVICE_AVAILABLE);
+    }
+
+    @Override
+    public boolean hasCompiler() {
+        return device.getInfoBoolean(CL10.CL_DEVICE_COMPILER_AVAILABLE);
+    }
+
+    @Override
+    public boolean hasDouble() {
+        return hasExtension("cl_khr_fp64");
+    }
+
+    @Override
+    public boolean hasHalfFloat() {
+        return hasExtension("cl_khr_fp16");
+    }
+
+    @Override
+    public boolean hasErrorCorrectingMemory() {
+        return device.getInfoBoolean(CL10.CL_DEVICE_ERROR_CORRECTION_SUPPORT);
+    }
+
+    @Override
+    public boolean hasUnifiedMemory() {
+        return device.getInfoBoolean(CL11.CL_DEVICE_HOST_UNIFIED_MEMORY);
+    }
+
+    @Override
+    public boolean hasImageSupport() {
+        return device.getInfoBoolean(CL10.CL_DEVICE_IMAGE_SUPPORT);
+    }
+    
+    @Override
+    public boolean hasWritableImage3D() {
+        return hasExtension("cl_khr_3d_image_writes");
+    }
+
+    @Override
+    public boolean hasOpenGLInterop() {
+        return hasExtension("cl_khr_gl_sharing");
+    }
+    
+    @Override
+    public boolean hasExtension(String extension) {
+        return getExtensions().contains(extension);
+    }
+
+    @Override
+    public Collection<? extends String> getExtensions() {
+        return Arrays.asList(device.getInfoString(CL10.CL_DEVICE_EXTENSIONS).split(" "));
+    }
+
+    @Override
+    public int getComputeUnits() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_COMPUTE_UNITS);
+    }
+
+    @Override
+    public int getClockFrequency() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_CLOCK_FREQUENCY);
+    }
+
+    @Override
+    public int getAddressBits() {
+        return device.getInfoInt(CL10.CL_DEVICE_ADDRESS_BITS);
+    }
+
+    @Override
+    public boolean isLittleEndian() {
+        return device.getInfoBoolean(CL10.CL_DEVICE_ENDIAN_LITTLE);
+    }
+
+    @Override
+    public long getMaximumWorkItemDimensions() {
+        return device.getInfoSize(CL10.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
+    }
+
+    @Override
+    public long[] getMaximumWorkItemSizes() {
+        return device.getInfoSizeArray(CL10.CL_DEVICE_MAX_WORK_ITEM_SIZES);
+    }
+
+    @Override
+    public long getMaxiumWorkItemsPerGroup() {
+        return device.getInfoSize(CL10.CL_DEVICE_MAX_WORK_GROUP_SIZE);
+    }
+
+    @Override
+    public int getMaximumSamplers() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_SAMPLERS);
+    }
+
+    @Override
+    public int getMaximumReadImages() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_READ_IMAGE_ARGS);
+    }
+
+    @Override
+    public int getMaximumWriteImages() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_WRITE_IMAGE_ARGS);
+    }
+
+    @Override
+    public long[] getMaximumImage2DSize() {
+        return new long[] {
+            device.getInfoSize(CL10.CL_DEVICE_IMAGE2D_MAX_WIDTH),
+            device.getInfoSize(CL10.CL_DEVICE_IMAGE2D_MAX_HEIGHT)
+        };
+    }
+
+    @Override
+    public long[] getMaximumImage3DSize() {
+        return new long[] {
+            device.getInfoSize(CL10.CL_DEVICE_IMAGE3D_MAX_WIDTH),
+            device.getInfoSize(CL10.CL_DEVICE_IMAGE3D_MAX_HEIGHT),
+            device.getInfoSize(CL10.CL_DEVICE_IMAGE3D_MAX_DEPTH)
+        };
+    }
+    
+    @Override
+    public long getMaximumAllocationSize() {
+        return device.getInfoLong(CL10.CL_DEVICE_MAX_MEM_ALLOC_SIZE);
+    }
+    
+    @Override
+    public long getGlobalMemorySize() {
+        return device.getInfoLong(CL10.CL_DEVICE_GLOBAL_MEM_SIZE);
+    }
+    
+    @Override
+    public long getLocalMemorySize() {
+        return device.getInfoLong(CL10.CL_DEVICE_LOCAL_MEM_SIZE);
+    }
+    
+    @Override
+    public long getMaximumConstantBufferSize() {
+        return device.getInfoLong(CL10.CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE);
+    }
+    
+    @Override
+    public int getMaximumConstantArguments() {
+        return device.getInfoInt(CL10.CL_DEVICE_MAX_CONSTANT_ARGS);
+    }
+
+    @Override
+    public String getProfile() {
+        return device.getInfoString(CL10.CL_DEVICE_PROFILE);
+    }
+
+    @Override
+    public String getVersion() {
+        return device.getInfoString(CL10.CL_DEVICE_VERSION);
+    }
+
+    @Override
+    public int getVersionMajor() {
+        return Utils.getMajorVersion(getVersion(), "OpenCL ");
+    }
+
+    @Override
+    public int getVersionMinor() {
+        return Utils.getMinorVersion(getVersion(), "OpenCL ");
+    }
+
+    @Override
+    public String getCompilerVersion() {
+        return device.getInfoString(CL11.CL_DEVICE_OPENCL_C_VERSION);
+    }
+
+    @Override
+    public int getCompilerVersionMajor() {
+        return Utils.getMajorVersion(getCompilerVersion(), "OpenCL C ");
+    }
+
+    @Override
+    public int getCompilerVersionMinor() {
+        return Utils.getMinorVersion(getCompilerVersion(), "OpenCL C ");
+    }
+
+    @Override
+    public String getDriverVersion() {
+        return device.getInfoString(CL10.CL_DRIVER_VERSION);
+    }
+
+    @Override
+    public int getDriverVersionMajor() {
+        return Utils.getMajorVersion(getDriverVersion(), "");
+    }
+
+    @Override
+    public int getDriverVersionMinor() {
+        return Utils.getMinorVersion(getDriverVersion(), "");
+    }
+
+    @Override
+    public String getName() {
+        return device.getInfoString(CL10.CL_DEVICE_NAME);
+    }
+
+    @Override
+    public String getVendor() {
+        return device.getInfoString(CL10.CL_DEVICE_VENDOR);
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+    
+}

+ 127 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglPlatform.java

@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl.lwjgl;
+
+import com.jme3.opencl.Device;
+import com.jme3.opencl.Platform;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import org.lwjgl.opencl.CL10;
+import org.lwjgl.opencl.CLDevice;
+import org.lwjgl.opencl.CLPlatform;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public final class LwjglPlatform implements Platform {
+    
+    final CLPlatform platform;
+    List<LwjglDevice> devices;
+    
+    public LwjglPlatform(CLPlatform platform) {
+        this.platform = platform;
+    }
+
+    public CLPlatform getPlatform() {
+        return platform;
+    }
+    
+    @Override
+    public List<LwjglDevice> getDevices() {
+        if (devices == null) {
+            devices = new ArrayList<>();
+            for (CLDevice d : platform.getDevices(CL10.CL_DEVICE_TYPE_ALL)) {
+                devices.add(new LwjglDevice(d, this));
+            }
+        }
+        return devices;
+    }
+
+    @Override
+    public String getProfile() {
+        return platform.getInfoString(CL10.CL_PLATFORM_PROFILE);
+    }
+
+    @Override
+    public boolean isFullProfile() {
+        return getProfile().contains("FULL_PROFILE");
+    }
+
+    @Override
+    public boolean isEmbeddedProfile() {
+        return getProfile().contains("EMBEDDED_PROFILE");
+    }
+
+    @Override
+    public String getVersion() {
+        return platform.getInfoString(CL10.CL_PLATFORM_VERSION);
+    }
+
+    @Override
+    public int getVersionMajor() {
+        return Utils.getMajorVersion(getVersion(), "OpenCL ");
+    }
+
+    @Override
+    public int getVersionMinor() {
+        return Utils.getMinorVersion(getVersion(), "OpenCL ");
+    }
+
+    @Override
+    public String getName() {
+        return platform.getInfoString(CL10.CL_PLATFORM_NAME);
+    }
+
+    @Override
+    public String getVendor() {
+        return platform.getInfoString(CL10.CL_PLATFORM_VENDOR);
+    }
+
+    @Override
+    public boolean hasExtension(String extension) {
+        return getExtensions().contains(extension);
+    }
+
+    @Override
+    public boolean hasOpenGLInterop() {
+        return hasExtension("cl_khr_gl_sharing");
+    }
+
+    @Override
+    public Collection<? extends String> getExtensions() {
+        return Arrays.asList(platform.getInfoString(CL10.CL_PLATFORM_EXTENSIONS).split(" "));
+    }
+    
+}

+ 92 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/PlatformChooserImpl.java

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl.lwjgl;
+
+import com.jme3.opencl.Device;
+import com.jme3.opencl.Platform;
+import com.jme3.opencl.PlatformChooser;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public class PlatformChooserImpl implements PlatformChooser {
+    private static final Logger LOG = Logger.getLogger(PlatformChooserImpl.class.getName());
+
+    @Override
+    public List<? extends Device> chooseDevices(List<? extends Platform> platforms) {
+        ArrayList<Device> result = new ArrayList<Device>();
+        for (Platform p : platforms) {
+            if (!p.hasOpenGLInterop()) {
+                continue; //must support interop
+            }
+            for (Device d : p.getDevices()) {
+                if (d.hasOpenGLInterop() && d.getDeviceType()==Device.DeviceType.GPU) {
+                    result.add(d); //GPU prefered
+                }
+            }
+            if (!result.isEmpty()) {
+                return result;
+            }
+        }
+        //no GPU devices found, try all
+        for (Platform p : platforms) {
+            if (!p.hasOpenGLInterop()) {
+                continue; //must support interop
+            }
+            for (Device d : p.getDevices()) {
+                if (d.hasOpenGLInterop()) {
+                    result.add(d); //just interop needed
+                }
+            }
+            if (!result.isEmpty()) {
+                return result;
+            }
+        }
+        //still no one found, try without interop
+        LOG.warning("No device with OpenCL-OpenGL-interop found, try without");
+        for (Platform p : platforms) {
+            for (Device d : p.getDevices()) {
+                result.add(d);
+            }
+            if (!result.isEmpty()) {
+                return result;
+            }
+        }
+        //no devices available at all!
+        return result; //result is empty
+    }
+    
+}

+ 51 - 0
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/Utils.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009-2016 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.opencl.lwjgl;
+
+/**
+ *
+ * @author Sebastian Weiss
+ */
+public class Utils {
+    
+    public static int getMajorVersion(String version, String prefix) {
+        String s = version.substring(prefix.length());
+        return Integer.parseInt(s);
+    }
+    
+    public static int getMinorVersion(String version, String prefix) {
+        String s = version.substring(prefix.length());
+        int major = Integer.parseInt(s);
+        s = s.substring((int) (Math.log10(major) + 2));
+        return Integer.parseInt(s);
+    }
+}

+ 76 - 53
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java

@@ -36,7 +36,12 @@ import com.jme3.input.lwjgl.JInputJoyInput;
 import com.jme3.input.lwjgl.LwjglKeyInput;
 import com.jme3.input.lwjgl.LwjglMouseInput;
 import com.jme3.opencl.Context;
+import com.jme3.opencl.Device;
+import com.jme3.opencl.PlatformChooser;
 import com.jme3.opencl.lwjgl.LwjglCL;
+import com.jme3.opencl.lwjgl.LwjglDevice;
+import com.jme3.opencl.lwjgl.LwjglPlatform;
+import com.jme3.opencl.lwjgl.PlatformChooserImpl;
 import com.jme3.renderer.Renderer;
 import com.jme3.renderer.RendererException;
 import com.jme3.renderer.lwjgl.LwjglGL;
@@ -87,9 +92,8 @@ public abstract class LwjglContext implements JmeContext {
     protected Timer timer;
     protected SystemListener listener;
     
-    protected LwjglCL clImpl;
-    protected CLPlatform clPlatform;
-    protected com.jme3.opencl.Context clContext;
+    protected LwjglPlatform clPlatform;
+    protected com.jme3.opencl.lwjgl.LwjglContext clContext;
 
     public void setSystemListener(SystemListener listener) {
         this.listener = listener;
@@ -267,70 +271,89 @@ public abstract class LwjglContext implements JmeContext {
             return;
         }
         
-        //load platforms
-        List<CLPlatform> platforms = CLPlatform.getPlatforms();
+        //load platforms and devices
         StringBuilder platformInfos = new StringBuilder();
-        platformInfos.append("Available OpenCL platforms:\n");
-        ArrayList<Integer> possiblePlatforms = new ArrayList<Integer>();
+        ArrayList<LwjglPlatform> platforms = new ArrayList<>();
+        for (CLPlatform p : CLPlatform.getPlatforms()) {
+            platforms.add(new LwjglPlatform(p));
+        }
+        platformInfos.append("Available OpenCL platforms:");
         for (int i=0; i<platforms.size(); ++i) {
-            CLPlatform platform = platforms.get(i);
-            platformInfos.append(" * Platform ").append(i+1).append("\n");
-            platformInfos.append(" *   Name: ").append(platform.getInfoString(CL10.CL_PLATFORM_NAME)).append("\n");
-            platformInfos.append(" *   Vendor: ").append(platform.getInfoString(CL10.CL_PLATFORM_VENDOR)).append("\n");
-            platformInfos.append(" *   Version: ").append(platform.getInfoString(CL10.CL_PLATFORM_VERSION)).append("\n");
-            platformInfos.append(" *   Profile: ").append(platform.getInfoString(CL10.CL_PLATFORM_PROFILE)).append("\n");
-            boolean supportsInterop = platform.getInfoString(CL10.CL_PLATFORM_EXTENSIONS).contains("cl_khr_gl_sharing");
-            platformInfos.append(" *   Supports Interop: ").append(supportsInterop).append("\n");
-            if (supportsInterop) {
-                
-                possiblePlatforms.add(i);
+            LwjglPlatform platform = platforms.get(i);
+            platformInfos.append("\n * Platform ").append(i+1);
+            platformInfos.append("\n *   Name: ").append(platform.getName());
+            platformInfos.append("\n *   Vendor: ").append(platform.getVendor());
+            platformInfos.append("\n *   Version: ").append(platform.getVersion());
+            platformInfos.append("\n *   Profile: ").append(platform.getProfile());
+            platformInfos.append("\n *   Supports interop: ").append(platform.hasOpenGLInterop());
+            List<LwjglDevice> devices = platform.getDevices();
+            platformInfos.append("\n *   Available devices:");
+            for (int j=0; j<devices.size(); ++j) {
+                LwjglDevice device = devices.get(j);
+                platformInfos.append("\n *    * Device ").append(j+1);
+                platformInfos.append("\n *    *   Name: ").append(device.getName());
+                platformInfos.append("\n *    *   Vendor: ").append(device.getVendor());
+                platformInfos.append("\n *    *   Version: ").append(device.getVersion());
+                platformInfos.append("\n *    *   Profile: ").append(device.getProfile());
+                platformInfos.append("\n *    *   Compiler version: ").append(device.getCompilerVersion());
+                platformInfos.append("\n *    *   Device type: ").append(device.getDeviceType());
+                platformInfos.append("\n *    *   Compute units: ").append(device.getComputeUnits());
+                platformInfos.append("\n *    *   Work group size: ").append(device.getMaxiumWorkItemsPerGroup());
+                platformInfos.append("\n *    *   Global memory: ").append(device.getGlobalMemorySize()).append("B");
+                platformInfos.append("\n *    *   Local memory: ").append(device.getLocalMemorySize()).append("B");
+                platformInfos.append("\n *    *   Constant memory: ").append(device.getMaximumConstantBufferSize()).append("B");
+                platformInfos.append("\n *    *   Supports double: ").append(device.hasDouble());
+                platformInfos.append("\n *    *   Supports half floats: ").append(device.hasHalfFloat());
+                platformInfos.append("\n *    *   Supports writable 3d images: ").append(device.hasWritableImage3D());
+                platformInfos.append("\n *    *   Supports interop: ").append(device.hasOpenGLInterop());
             }
         }
-        logger.info(platformInfos.toString().trim());
-        if (possiblePlatforms.isEmpty()) {
-            logger.warning("No OpenCL platform with the extension 'cl_khr_gl_sharing' found!");
-            return;
-        }
-        int platformIndex = possiblePlatforms.get(0);
-        //TODO: add API to choose the platform
-        logger.info("Choose platform with index "+(platformIndex+1));
-        clPlatform = platforms.get(platformIndex);
+        logger.info(platformInfos.toString());
         
-        //load devices
-        List<CLDevice> devices = clPlatform.getDevices(CL10.CL_DEVICE_TYPE_GPU);
-        StringBuilder deviceInfos = new StringBuilder();
-        deviceInfos.append("Available OpenCL devices:\n");
-        ArrayList<CLDevice> possibleDevices = new ArrayList<CLDevice>();
-        for (int i=0; i<devices.size(); ++i) {
-            CLDevice device = devices.get(i);
-            deviceInfos.append(" * Device ").append(i+1).append("\n");
-            deviceInfos.append(" *   Name: ").append(device.getInfoString(CL10.CL_DEVICE_NAME)).append("\n");
-            deviceInfos.append(" *   Vendor: ").append(device.getInfoString(CL10.CL_DEVICE_VENDOR)).append("\n");
-            deviceInfos.append(" *   Version: ").append(device.getInfoString(CL10.CL_DEVICE_VERSION)).append("\n");
-            deviceInfos.append(" *   Profile: ").append(device.getInfoString(CL10.CL_DEVICE_PROFILE)).append("\n");
-            deviceInfos.append(" *   Global memory: ").append(device.getInfoLong(CL10.CL_DEVICE_GLOBAL_MEM_SIZE)).append("\n");
-            deviceInfos.append(" *   Compute units: ").append(device.getInfoInt(CL10.CL_DEVICE_MAX_COMPUTE_UNITS)).append("\n");
-            deviceInfos.append(" *   Work group size: ").append(device.getInfoSize(CL10.CL_DEVICE_MAX_WORK_GROUP_SIZE)).append("\n");
-            boolean supportsInterop = device.getInfoString(CL10.CL_DEVICE_EXTENSIONS).contains("cl_khr_gl_sharing");
-            platformInfos.append(" *   Supports Interop: ").append(supportsInterop).append("\n");
-            if (supportsInterop) {
-                possibleDevices.add(device);
+        //choose devices
+        PlatformChooser chooser = null;
+        if (settings.getOpenCLPlatformChooser() != null) {
+            try {
+                chooser = (PlatformChooser) Class.forName(settings.getOpenCLPlatformChooser()).newInstance();
+            } catch (Exception ex) {
+                logger.log(Level.WARNING, "unable to instantiate custom PlatformChooser", ex);
             }
         }
+        if (chooser == null) {
+            chooser = new PlatformChooserImpl();
+        }
+        List<? extends Device> choosenDevices = chooser.chooseDevices(platforms);
+        List<CLDevice> devices = new ArrayList<>(choosenDevices.size());
+        LwjglPlatform platform = null;
+        for (Device d : choosenDevices) {
+            if (!(d instanceof LwjglDevice)) {
+                logger.log(Level.SEVERE, "attempt to return a custom Device implementation from PlatformChooser: {0}", d);
+                return;
+            }
+            LwjglDevice ld = (LwjglDevice) d;
+            if (platform == null) {
+                platform = ld.getPlatform();
+            } else if (platform != ld.getPlatform()) {
+                logger.severe("attempt to use devices from different platforms");
+                return;
+            }
+            devices.add(ld.getDevice());
+        }
+        if (devices.isEmpty()) {
+            logger.warning("no devices specified, no OpenCL context created");
+            return;
+        }
+        clPlatform = platform;
+        logger.log(Level.INFO, "chosen platform: {0}", platform.getName());
+        logger.log(Level.INFO, "chosen devices: {0}", choosenDevices);
         
         //create context
-        CLContext context;
         try {
-            context = CLContext.create(clPlatform, possibleDevices, null, Display.getDrawable(), null);
+            clContext = new com.jme3.opencl.lwjgl.LwjglContext(CLContext.create(platform.getPlatform(), devices, null, Display.getDrawable(), null));
         } catch (LWJGLException ex) {
             logger.log(Level.SEVERE, "Unable to create OpenCL context", ex);
             return;
         }
-        clContext = new Context(context.getPointer());
-        
-        //create cl implementation
-        clImpl = new LwjglCL();
-        clContext.setCl(clImpl);
         
         logger.info("OpenCL context created");
     }