/* * Copyright (c) 2002-2010 LWJGL Project * 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 'LWJGL' 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 org.lwjgl.opencl; import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLUtil; import org.lwjgl.PointerBuffer; import java.nio.Buffer; import java.nio.ByteBuffer; import static org.lwjgl.opencl.CL10.*; import static org.lwjgl.opencl.CL11.*; /** * Utility class that provides runtime checks for OpenCL method calls. * TODO: Revisit this when Java 7.0 is released, there will be new Buffer API with 64bit indices/sizes. * * @author Spasi */ final class CLChecks { private CLChecks() { } /** * Calculates the number of bytes in the specified cl_mem buffer rectangle region. * * @param offset the host offset * @param region the rectangle region * @param row_pitch the host row pitch * @param slice_pitch the host slice pitch * * @return the region size in bytes */ static int calculateBufferRectSize(final PointerBuffer offset, final PointerBuffer region, long row_pitch, long slice_pitch) { if ( !LWJGLUtil.CHECKS ) return 0; final long x = offset.get(0); final long y = offset.get(1); final long z = offset.get(2); if ( LWJGLUtil.DEBUG && (x < 0 || y < 0 || z < 0) ) throw new IllegalArgumentException("Invalid cl_mem host offset: " + x + ", " + y + ", " + z); final long w = region.get(0); final long h = region.get(1); final long d = region.get(2); if ( LWJGLUtil.DEBUG && (w < 1 || h < 1 || d < 1) ) throw new IllegalArgumentException("Invalid cl_mem rectangle region dimensions: " + w + " x " + h + " x " + d); if ( row_pitch == 0 ) row_pitch = w; else if ( LWJGLUtil.DEBUG && row_pitch < w ) throw new IllegalArgumentException("Invalid host row pitch specified: " + row_pitch); if ( slice_pitch == 0 ) slice_pitch = row_pitch * h; else if ( LWJGLUtil.DEBUG && slice_pitch < (row_pitch * h) ) throw new IllegalArgumentException("Invalid host slice pitch specified: " + slice_pitch); return (int)((z * slice_pitch + y * row_pitch + x) + (w * h * d)); } /** * Calculates the number of bytes in the specified cl_mem image region. * This implementation assumes 1 byte per element, because we cannot the * image type. * * @param region the image region * @param row_pitch the row pitch * @param slice_pitch the slice pitch * * @return the region size in bytes */ static int calculateImageSize(final PointerBuffer region, long row_pitch, long slice_pitch) { if ( !LWJGLUtil.CHECKS ) return 0; final long w = region.get(0); final long h = region.get(1); final long d = region.get(2); if ( LWJGLUtil.DEBUG && (w < 1 || h < 1 || d < 1) ) throw new IllegalArgumentException("Invalid cl_mem image region dimensions: " + w + " x " + h + " x " + d); if ( row_pitch == 0 ) row_pitch = w; else if ( LWJGLUtil.DEBUG && row_pitch < w ) throw new IllegalArgumentException("Invalid row pitch specified: " + row_pitch); if ( slice_pitch == 0 ) slice_pitch = row_pitch * h; else if ( LWJGLUtil.DEBUG && slice_pitch < (row_pitch * h) ) throw new IllegalArgumentException("Invalid slice pitch specified: " + slice_pitch); return (int)(slice_pitch * d); } /** * Calculates the number of bytes in the specified 2D image. * * @param format the cl_image_format struct * @param w the image width * @param h the image height * @param row_pitch the image row pitch * * @return the 2D image size in bytes */ static int calculateImage2DSize(final Buffer host_ptr, final ByteBuffer format, final long w, final long h, long row_pitch) { if ( !LWJGLUtil.CHECKS ) return 0; if ( LWJGLUtil.DEBUG && (w < 1 || h < 1) ) throw new IllegalArgumentException("Invalid 2D image dimensions: " + w + " x " + h); final int elementSize = getElementSize(format); if ( row_pitch == 0 ) row_pitch = w * elementSize; else if ( LWJGLUtil.DEBUG && ((row_pitch < w * elementSize) || (row_pitch % elementSize != 0)) ) throw new IllegalArgumentException("Invalid image_row_pitch specified: " + row_pitch); return (int)(row_pitch * h) >> BufferUtils.getElementSizeExponent(host_ptr); } /** * Calculates the number of bytes in the specified 3D image. * * @param format the cl_image_format struct * @param w the image width * @param h the image height * @param d the image depth * @param row_pitch the image row pitch * @param slice_pitch the image slice pitch * * @return the 3D image size in bytes */ static int calculateImage3DSize(final Buffer host_ptr, final ByteBuffer format, final long w, final long h, final long d, long row_pitch, long slice_pitch) { if ( !LWJGLUtil.CHECKS ) return 0; if ( LWJGLUtil.DEBUG && (w < 1 || h < 1 || d < 2) ) throw new IllegalArgumentException("Invalid 3D image dimensions: " + w + " x " + h + " x " + d); final int elementSize = getElementSize(format); if ( row_pitch == 0 ) row_pitch = w * elementSize; else if ( LWJGLUtil.DEBUG && ((row_pitch < w * elementSize) || (row_pitch % elementSize != 0)) ) throw new IllegalArgumentException("Invalid image_row_pitch specified: " + row_pitch); if ( slice_pitch == 0 ) slice_pitch = row_pitch * h; else if ( LWJGLUtil.DEBUG && ((row_pitch < row_pitch * h) || (slice_pitch % row_pitch != 0)) ) throw new IllegalArgumentException("Invalid image_slice_pitch specified: " + row_pitch); return (int)(slice_pitch * d) >> BufferUtils.getElementSizeExponent(host_ptr); } /** * Returns the number of bytes per element for the specified image format. * * @param format a cl_image_format struct. * * @return the number of bytes per image element */ private static int getElementSize(final ByteBuffer format) { final int channelOrder = format.getInt(format.position() + 0); final int channelType = format.getInt(format.position() + 4); return getChannelCount(channelOrder) * getChannelSize(channelType); } /** * Returns the number of channels in the specified cl_channel_order. * * @param channelOrder the cl_channel_order * * @return the number of channels */ private static int getChannelCount(final int channelOrder) { switch ( channelOrder ) { case CL_R: case CL_A: case CL_INTENSITY: case CL_LUMINANCE: case CL_Rx: return 1; case CL_RG: case CL_RA: case CL_RGx: return 2; case CL_RGB: case CL_RGBx: return 3; case CL_RGBA: case CL_BGRA: case CL_ARGB: return 4; default: throw new IllegalArgumentException("Invalid cl_channel_order specified: " + LWJGLUtil.toHexString(channelOrder)); } } /** * Returns the number of bytes in the specified cl_channel_type. * * @param channelType the cl_channel_type * * @return the number of bytes */ private static int getChannelSize(final int channelType) { switch ( channelType ) { case CL_SNORM_INT8: case CL_UNORM_INT8: case CL_SIGNED_INT8: case CL_UNSIGNED_INT8: return 1; case CL_SNORM_INT16: case CL_UNORM_INT16: case CL_UNORM_SHORT_565: case CL_UNORM_SHORT_555: case CL_SIGNED_INT16: case CL_UNSIGNED_INT16: case CL_HALF_FLOAT: return 2; case CL_UNORM_INT_101010: case CL_SIGNED_INT32: case CL_UNSIGNED_INT32: case CL_FLOAT: return 4; default: throw new IllegalArgumentException("Invalid cl_channel_type specified: " + LWJGLUtil.toHexString(channelType)); } } }