| // |
| // Copyright (c) 2017 The Khronos Group Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| #include "helpers.h" |
| #include "../harness/imageHelpers.h" |
| |
| // convert_float_to_half and convert_half_to_float may be found in test_conformance/images/image_helpers.cpp |
| cl_ushort convert_float_to_half( cl_float f ); |
| cl_float convert_half_to_float( cl_ushort h ); |
| |
| #if defined( __APPLE__ ) |
| #include <OpenGL/glu.h> |
| #else |
| #include <GL/glu.h> |
| #endif |
| |
| #if defined(__linux__) |
| // On linux we dont link to GLU library to avoid comaptibility issues with |
| // libstdc++ |
| // FIXME: Implement this |
| const GLubyte* gluErrorString (GLenum error) |
| { |
| const char* gl_Error = "OpenGL Error"; |
| return (const GLubyte*)gl_Error; |
| } |
| #endif |
| |
| void * CreateGLTexture1DArray(size_t width, size_t length, |
| GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, int *outError, |
| bool allocateMem, MTdata d) |
| { |
| *outError = 0; |
| GLenum err = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| // width_in_pixels * pixel_width * number_of_images: |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width * length; |
| } |
| else |
| { |
| size = width * length * 4; |
| } |
| |
| buffer = (char *)CreateRandomData(type, size, d); |
| |
| glGenTextures( 1, outTextureID ); |
| glBindTexture( get_base_gl_target( target ), *outTextureID ); |
| glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) { |
| log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); |
| *outError = -1; |
| free( buffer ); |
| return NULL; |
| } |
| |
| // use TexImage2D to pump the 1D array fill of bits: |
| glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, |
| (GLsizei)length, 0, glFormat, glType, buffer ); |
| |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) { |
| if (err != GL_OUT_OF_MEMORY) { |
| log_error( "ERROR: Unable to load data using glTexImage2D for " |
| "TEXTURE_1D_ARRAY : %s : %s : %d : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), (int)(length), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| |
| *outError = -1; |
| } else { |
| log_info( "WARNING: Unable to load data using glTexImage2D for " |
| "TEXTURE_1D_ARRAY : %s : %s : %d : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), (int)(length), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| |
| *outError = -2; |
| } |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( !allocateMem ) { |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * length; i++ ) { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * length; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * CreateGLTexture2DArray(size_t width, size_t height, size_t length, |
| GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, int *outError, |
| bool allocateMem, MTdata d) |
| { |
| *outError = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width * height * length; |
| } |
| else |
| { |
| size = width * height * length * 4; |
| } |
| |
| buffer = (char *)CreateRandomData(type, size, d); |
| |
| if( type == kFloat && allocateMem ) |
| { |
| // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect |
| cl_float *p = (cl_float *)buffer; |
| for( size_t i = 0; i < size; i++ ) |
| { |
| p[ i ] = (float) genrand_real1( d ); |
| } |
| } |
| else if( !allocateMem ) |
| memset( buffer, 0, size * get_explicit_type_size( type ) ); |
| |
| glGenTextures( 1, outTextureID ); |
| |
| glBindTexture( target, *outTextureID ); |
| glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
| glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| |
| glGetError(); |
| //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes |
| if (internalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_UNPACK_ALIGNMENT, get_explicit_type_size( type )); |
| |
| glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, |
| (GLsizei)length, 0, glFormat, glType, buffer ); |
| |
| if (internalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); |
| |
| GLenum err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| if (err != GL_OUT_OF_MEMORY) { |
| log_error( "ERROR: Unable to load data into GL texture (%s) format %s " |
| "type %s internal format %s\n", gluErrorString( err ), |
| GetGLFormatName( glFormat ), get_explicit_type_name( type ), |
| GetGLFormatName( internalFormat ) ); |
| *outError = -1; |
| } else { |
| log_info( "WARNING: Unable to load data into GL texture (%s) format %s " |
| "type %s internal format %s\n", gluErrorString( err ), |
| GetGLFormatName( glFormat ), get_explicit_type_name( type ), |
| GetGLFormatName( internalFormat ) ); |
| *outError = -2; |
| } |
| delete [] buffer; |
| return NULL; |
| } |
| |
| if( !allocateMem ) |
| { |
| delete [] buffer; |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height * length; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * length; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * CreateGLTextureBuffer(size_t width, GLenum target, |
| GLenum glFormat, GLenum internalFormat, GLenum glType, ExplicitType type, |
| GLuint *outTex, GLuint *outBuf, int *outError, bool allocateMem, MTdata d) |
| { |
| // First, generate a regular GL Buffer from random data. |
| *outError = 0; |
| GLenum err = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| // The buffer should be the array width * number of elements * element pitch |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width; |
| } |
| else |
| { |
| size = width * 4; |
| } |
| |
| buffer = (char*)CreateRandomData(type, size, d); |
| |
| err = glGetError(); |
| |
| glGenBuffers(1, outBuf); |
| glBindBuffer(GL_TEXTURE_BUFFER, *outBuf); |
| |
| // Need to multiply by the type size: |
| size *= ( GetGLTypeSize( GetGLTypeForExplicitType(type) ) ); |
| |
| glBufferData(GL_TEXTURE_BUFFER, size, buffer, GL_DYNAMIC_DRAW); |
| |
| // Now make a Texture out of this Buffer: |
| |
| glGenTextures(1, outTex); |
| glBindTexture(GL_TEXTURE_BUFFER, *outTex); |
| glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, *outBuf); |
| |
| if ((err = glGetError())) { |
| log_error( "ERROR: Unable to load data into glTexBuffer : %s : %s : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(size), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -1; |
| delete [] buffer; |
| return NULL; |
| } |
| |
| if( !allocateMem ) { |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width; i++ ) { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void* CreateGLTexture1D( size_t width, GLenum target, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, ExplicitType type, |
| GLuint *outTextureID, int *outError, bool allocateMem, MTdata d ) |
| { |
| *outError = 0; |
| GLenum err = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| // The buffer should be the array width * number of elements * element pitch |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width; |
| } |
| else |
| { |
| size = width * 4; |
| } |
| |
| buffer = (char*)CreateRandomData(type, size, d); |
| |
| glGenTextures( 1, outTextureID ); |
| glBindTexture( get_base_gl_target( target ), *outTextureID ); |
| glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); |
| *outError = -1; |
| free( buffer ); |
| return NULL; |
| } |
| |
| glTexImage1D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, |
| 0, glFormat, glType, buffer ); |
| |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| if (err != GL_OUT_OF_MEMORY) { |
| log_error( "ERROR: Unable to load data into glTexImage1D : %s : %s : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -1; |
| } else { |
| log_info( "WARNING: Unable to load data into glTexImage1D : %s : %s : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -2; |
| } |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( !allocateMem ) { |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width; i++ ) { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * CreateGLTexture2D( size_t width, size_t height, |
| GLenum target, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, |
| int *outError, bool allocateMem, MTdata d ) |
| { |
| *outError = 0; |
| GLenum err = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width * height; |
| } |
| else |
| { |
| size = width * height * 4; |
| } |
| |
| buffer = (char *)CreateRandomData(type, size, d); |
| |
| glGenTextures( 1, outTextureID ); |
| glBindTexture( get_base_gl_target( target ), *outTextureID ); |
| glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); |
| *outError = -1; |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( get_base_gl_target( target ) == GL_TEXTURE_CUBE_MAP ) |
| { |
| char * temp = (char *)malloc(size * get_explicit_type_size( type ) * sizeof(cl_char)); |
| if(allocateMem) |
| memcpy( temp, buffer, size * get_explicit_type_size( type ) ); |
| else |
| memset( temp, 0, size * get_explicit_type_size( type ) ); |
| |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); |
| free(temp); |
| } |
| else |
| { |
| #ifdef DEBUG |
| log_info("- glTexImage2D : %s : %s : %d : %d : %s : %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| width, height, |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType)); |
| |
| DumpGLBuffer(glType, width, height, buffer); |
| #endif |
| |
| //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes |
| if (internalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_UNPACK_ALIGNMENT, get_explicit_type_size( type )); |
| |
| glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, buffer ); |
| |
| if (internalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); |
| } |
| |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| if (err != GL_OUT_OF_MEMORY) { |
| log_error( "ERROR: Unable to load data into glTexImage2D : %s : %s : %d : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), (int)(height), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -1; |
| } else { |
| log_info( "WARNING: Unable to load data into glTexImage2D : %s : %s : %d : %d : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(internalFormat), |
| (int)(width), (int)(height), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -2; |
| } |
| free( buffer ); |
| return NULL; |
| } |
| |
| #ifdef DEBUG |
| char * test = (char *)malloc(width * height * 4 * get_explicit_type_size( type )); |
| memset(test, 0, width * height * 4 * get_explicit_type_size( type )); |
| |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| glFormat = GL_RGBA; |
| glType = GL_FLOAT; |
| } |
| |
| log_info("- glGetTexImage : %s : %s : %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType)); |
| |
| glGetTexImage(target, 0, glFormat, glType, test); |
| |
| DumpGLBuffer(glType, width, height, test); |
| |
| free(test); |
| |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Unable to read data from glGetTexImage : %s : %s : %s : Error %s\n", |
| GetGLTargetName(target), |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| return NULL; |
| } |
| #endif |
| |
| if( !allocateMem ) |
| { |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * CreateGLTexture3D( size_t width, size_t height, size_t depth, |
| GLenum target, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, |
| int *outError, MTdata d, bool allocateMem) |
| { |
| *outError = 0; |
| |
| char * buffer; |
| unsigned int size = 0; |
| |
| if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) |
| { |
| size = width * height * depth; |
| } |
| else |
| { |
| size = width * height * depth * 4; |
| } |
| |
| buffer = (char *)create_random_data( type, d, size ); |
| |
| if( type == kFloat && allocateMem ) |
| { |
| // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect |
| cl_float *p = (cl_float *)buffer; |
| for( size_t i = 0; i < size; i++ ) |
| { |
| p[ i ] = (float) genrand_real1( d ); |
| } |
| } |
| else if( !allocateMem ) |
| memset( buffer, 0, size * get_explicit_type_size( type ) ); |
| |
| glGenTextures( 1, outTextureID ); |
| |
| glBindTexture( target, *outTextureID ); |
| glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
| glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| |
| glGetError(); |
| glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, (GLsizei)depth, 0, glFormat, glType, buffer ); |
| GLenum err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| if (err != GL_OUT_OF_MEMORY) { |
| log_error( "ERROR: Unable to load data into GL texture (%s) format %s type %s internal format %s\n", gluErrorString( err ), GetGLFormatName( glFormat ), get_explicit_type_name( type ), GetGLFormatName( internalFormat ) ); |
| *outError = -1; |
| } else { |
| log_info( "WARNING: Unable to load data into GL texture (%s) format %s type %s internal format %s\n", gluErrorString( err ), GetGLFormatName( glFormat ), get_explicit_type_name( type ), GetGLFormatName( internalFormat ) ); |
| *outError = -2; |
| } |
| delete [] buffer; |
| return NULL; |
| } |
| |
| if( !allocateMem ) |
| { |
| delete [] buffer; |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height * depth; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height * depth; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * ReadGLTexture( GLenum glTarget, GLuint glTexture, GLuint glBuf, GLint width, |
| GLenum glFormat, GLenum glInternalFormat, |
| GLenum glType, ExplicitType typeToReadAs, |
| size_t outWidth, size_t outHeight ) |
| { |
| // Read results from the GL texture |
| glBindTexture(get_base_gl_target(glTarget), glTexture); |
| |
| GLint realWidth, realHeight, realDepth; |
| glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_WIDTH, &realWidth ); |
| glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_HEIGHT, &realHeight ); |
| glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_DEPTH, &realDepth ); |
| |
| realDepth = (realDepth) ? realDepth : 1; |
| |
| GLint realInternalFormat; |
| glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat ); |
| |
| #ifdef DEBUG |
| log_info( "- Reading back from GL: %d x %d : %s : %s : %s : %s (stored as %s)\n", |
| realWidth, realHeight, |
| GetGLTargetName( glTarget), |
| GetGLFormatName( glInternalFormat ), |
| GetGLFormatName( glFormat ), |
| GetGLTypeName( glType ), |
| GetGLFormatName( realInternalFormat )); |
| #endif |
| |
| GLenum readBackFormat; |
| switch(glFormat) |
| { |
| case GL_RGBA_INTEGER_EXT: |
| readBackFormat = GL_RGBA_INTEGER_EXT; |
| break; |
| case GL_DEPTH_COMPONENT: |
| readBackFormat = GL_DEPTH_COMPONENT; |
| break; |
| case GL_DEPTH_STENCIL: |
| readBackFormat = GL_DEPTH_STENCIL; |
| break; |
| default: |
| readBackFormat = GL_RGBA; |
| break; |
| } |
| |
| GLenum readBackType; |
| switch (glType) { |
| #ifdef __APPLE__ |
| case GL_UNSIGNED_INT_8_8_8_8: |
| case GL_UNSIGNED_INT_8_8_8_8_REV: |
| readBackType = GL_UNSIGNED_BYTE; |
| break; |
| #endif |
| case GL_HALF_FLOAT: |
| case GL_UNSIGNED_BYTE: |
| case GL_UNSIGNED_SHORT: |
| case GL_UNSIGNED_INT: |
| case GL_BYTE: |
| case GL_SHORT: |
| case GL_INT: |
| case GL_FLOAT: |
| default: |
| readBackType = glType; |
| } |
| |
| size_t outBytes; |
| if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { |
| outBytes = realWidth * realHeight * realDepth * 4 |
| * GetGLTypeSize(readBackType); |
| } |
| else { |
| outBytes = width * 4; |
| |
| outBytes *= ( GetGLTypeSize( GetGLTypeForExplicitType(typeToReadAs) ) ); |
| } |
| |
| cl_char *outBuffer = (cl_char *)malloc( outBytes ); |
| memset(outBuffer, 0, outBytes); |
| |
| if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { |
| //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes |
| if (realInternalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_PACK_ALIGNMENT, 2); |
| |
| glGetTexImage( glTarget, 0, readBackFormat, readBackType, outBuffer ); |
| |
| if (realInternalFormat == GL_DEPTH_COMPONENT16) |
| glPixelStorei(GL_PACK_ALIGNMENT, 4); |
| } |
| else { |
| glBindBuffer(GL_ARRAY_BUFFER, glBuf); |
| glGetBufferSubData(GL_ARRAY_BUFFER, 0, outBytes, outBuffer); |
| } |
| |
| #ifdef DEBUG |
| |
| log_info( "- glGetTexImage: %s : %s : %s \n", |
| GetGLTargetName( glTarget), |
| GetGLFormatName(readBackFormat), |
| GetGLTypeName(readBackType)); |
| |
| DumpGLBuffer(readBackType, realWidth, realHeight, (void*)outBuffer); |
| |
| #endif |
| |
| return (void *)outBuffer; |
| } |
| |
| int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, |
| GLenum attachment, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, |
| GLuint *outFramebuffer, |
| GLuint *outRenderbuffer ) |
| { |
| GLenum err = 0; |
| |
| // Generate a renderbuffer and bind |
| glGenRenderbuffersEXT( 1, outRenderbuffer ); |
| glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); |
| |
| // Allocate storage to the renderbuffer |
| glGetError(); |
| glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, internalFormat, (GLsizei)width, (GLsizei)height ); |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error("Failed to allocate render buffer storage!\n"); |
| return 1701; |
| } |
| |
| GLint realInternalFormat; |
| glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); |
| internalFormat = realInternalFormat; |
| |
| #ifdef DEBUG |
| GLint rsize, gsize, bsize, asize; |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); |
| |
| log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", |
| GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), |
| rsize, gsize, bsize, asize ); |
| #endif |
| |
| // Create and bind a framebuffer to render with |
| glGenFramebuffersEXT( 1, outFramebuffer ); |
| glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Unable to bind framebuffer : Error %s\n", |
| gluErrorString( err )); |
| |
| return -1; |
| } |
| |
| // Attach to the framebuffer |
| glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); |
| err = glGetError(); |
| GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); |
| if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) |
| { |
| log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| void reorder_verification_buffer(GLenum glFormat, GLenum glType, char* buffer, size_t num_pixels) |
| { |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < num_pixels; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < num_pixels; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| } |
| |
| |
| #ifdef GL_VERSION_3_2 |
| |
| #define check_gl_error() \ |
| { \ |
| GLenum errnom = GL_NO_ERROR;\ |
| if ((errnom = glGetError()) != GL_NO_ERROR)\ |
| log_error("GL Error: 0x%04X at %s:%d\n", errnom, __FILE__, __LINE__);\ |
| } |
| |
| const char *get_gl_vector_type( GLenum internalformat ) |
| { |
| switch (internalformat) { |
| case GL_RGBA8: |
| case GL_RGBA16: |
| case GL_RGBA32F_ARB: |
| case GL_RGBA16F_ARB: |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT32F: |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| return "vec4"; |
| break; |
| case GL_RGBA8I_EXT: |
| case GL_RGBA16I_EXT: |
| case GL_RGBA32I_EXT: |
| return "ivec4"; |
| break; |
| case GL_RGBA8UI_EXT: |
| case GL_RGBA16UI_EXT: |
| case GL_RGBA32UI_EXT: |
| return "uvec4"; |
| break; |
| default: |
| log_error("Test error: unsupported data type\n"); |
| return ""; |
| break; |
| } |
| } |
| |
| const char *get_gl_data_type( GLenum internalformat ) |
| { |
| switch (internalformat) { |
| case GL_RGBA8: |
| case GL_RGBA16: |
| case GL_RGBA32F_ARB: |
| case GL_RGBA16F_ARB: |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT32F: |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| return "float"; |
| break; |
| case GL_RGBA8I_EXT: |
| case GL_RGBA16I_EXT: |
| case GL_RGBA32I_EXT: |
| return "int"; |
| break; |
| case GL_RGBA8UI_EXT: |
| case GL_RGBA16UI_EXT: |
| case GL_RGBA32UI_EXT: |
| return "uint"; |
| break; |
| default: |
| log_error("Test error: unsupported data type\n"); |
| return ""; |
| break; |
| } |
| } |
| |
| |
| void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples, |
| GLenum target, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, |
| int *outError, bool allocateMem, MTdata d , bool fixedSampleLocations) |
| { |
| // This function creates a multisample texture and renders into each sample |
| // using a GLSL shader |
| |
| // Check if the renderer supports enough samples |
| GLint max_samples = get_gl_max_samples(target, internalFormat); |
| check_gl_error() |
| |
| if (max_samples < (GLint)samples) |
| log_error("GL error: requested samples (%d) exceeds renderer max samples (%d)\n", samples, max_samples); |
| |
| // Setup the GLSL program |
| const GLchar *vertex_source = |
| "#version 140\n" |
| "in vec4 att0;\n" |
| "void main (void) {\n" |
| " gl_Position = vec4(att0.xy,0.0,1.0);\n" |
| "}\n"; |
| |
| const GLchar *fragmentSource = |
| "#version 140\n" |
| "out %s out0;\n" |
| "uniform %s colorVal;\n" |
| "uniform float depthVal;\n" |
| "void main (void) {\n" |
| " out0 = %s(colorVal);\n" |
| " gl_FragDepth = depthVal;\n" |
| "}\n"; |
| |
| GLchar fragmentShader[256]; |
| sprintf(fragmentShader, fragmentSource, get_gl_vector_type(internalFormat), get_gl_data_type(internalFormat), get_gl_vector_type(internalFormat)); |
| const GLchar *fragment_source = &fragmentShader[0]; |
| |
| glShaderWrapper vertex_shader = glCreateShader(GL_VERTEX_SHADER); |
| glShaderSource(vertex_shader, 1, &vertex_source, NULL); |
| glCompileShader(vertex_shader); |
| check_gl_error() |
| |
| glShaderWrapper fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); |
| glShaderSource(fragment_shader, 1, &fragment_source, NULL); |
| glCompileShader(fragment_shader); |
| check_gl_error() |
| |
| GLuint prog = glCreateProgram(); |
| glAttachShader(prog, vertex_shader); |
| glAttachShader(prog, fragment_shader); |
| check_gl_error() |
| |
| glBindAttribLocation(prog, 0, "att0"); |
| glLinkProgram(prog); |
| check_gl_error() |
| |
| // Setup the FBO and texture |
| glFramebufferWrapper fbo; |
| glGenFramebuffers(1, &fbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| check_gl_error() |
| |
| glViewport(0, 0, width, height); |
| check_gl_error() |
| |
| GLuint tex = 0; |
| glGenTextures(1, &tex); |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); |
| glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, fixedSampleLocations); |
| check_gl_error() |
| |
| GLint attachment; |
| switch (internalFormat) { |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT32F: |
| attachment = GL_DEPTH_ATTACHMENT; |
| break; |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| attachment = GL_DEPTH_STENCIL_ATTACHMENT; |
| break; |
| default: |
| attachment = GL_COLOR_ATTACHMENT0; |
| break; |
| } |
| |
| glFramebufferTexture(GL_FRAMEBUFFER, attachment, tex, 0); |
| check_gl_error() |
| |
| GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
| if (status == GL_FRAMEBUFFER_UNSUPPORTED) { |
| log_info("GL status: GL_FRAMEBUFFER_UNSUPPORTED format %s multisample is not supported\n", GetGLFormatName(internalFormat)); |
| *outTextureID = 0; |
| *outError = GL_FRAMEBUFFER_UNSUPPORTED; |
| return NULL; |
| } |
| |
| if (status != GL_FRAMEBUFFER_COMPLETE) { |
| log_error("GL error: framebuffer incomplete status 0x%04X\n",status); |
| *outTextureID = 0; |
| *outError = status; |
| return NULL; |
| } |
| |
| // Check if the framebuffer supports enough samples |
| GLint fbo_samples = 0; |
| glGetIntegerv(GL_SAMPLES, &fbo_samples); |
| check_gl_error(); |
| |
| if (fbo_samples < (GLint)samples) |
| log_error("GL Error: requested samples (%d) exceeds FBO capability (%d)\n", samples, fbo_samples); |
| |
| glUseProgram(prog); |
| check_gl_error() |
| |
| if (attachment != GL_DEPTH_ATTACHMENT && attachment != GL_DEPTH_STENCIL_ATTACHMENT) { |
| glDisable(GL_DEPTH_TEST); |
| check_gl_error() |
| } |
| else { |
| glEnable(GL_DEPTH_TEST); |
| glDepthFunc(GL_ALWAYS); |
| check_gl_error() |
| } |
| |
| // Setup the VBO for rendering a quad |
| GLfloat quad[] = { |
| -1.0f, -1.0f, |
| 1.0f, -1.0f, |
| 1.0f, 1.0f, |
| -1.0f, 1.0f |
| }; |
| |
| glBufferWrapper vbo; |
| glGenBuffers(1, &vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, vbo); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW); |
| check_gl_error() |
| |
| glVertexArraysWrapper vao; |
| glGenVertexArrays(1, &vao); |
| glBindVertexArray(vao); |
| glEnableVertexAttribArray(0); |
| glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, 0); |
| check_gl_error() |
| |
| //clearing color and depth buffer |
| glClearColor(0, 0, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glClearDepth(1.0); |
| glClear(GL_DEPTH_BUFFER_BIT); |
| |
| //calculating colors |
| double color_delta = 1.0 / samples; |
| double color = color_delta; |
| |
| glEnable(GL_SAMPLE_MASK); |
| for (size_t i=0;i!=samples;++i) { |
| glSampleMaski(0, 1<<i); |
| GLint colorUniformLocation = glGetUniformLocation(prog, "colorVal"); |
| switch (internalFormat) { |
| case GL_RGBA8I_EXT: |
| glUniform1i(colorUniformLocation, color * 0x7f); |
| break; |
| case GL_RGBA16I_EXT: |
| glUniform1i(colorUniformLocation, color * 0x7fff); |
| break; |
| case GL_RGBA32I_EXT: |
| glUniform1i(colorUniformLocation, color * 0x7fffffff); |
| break; |
| case GL_RGBA8UI_EXT: |
| glUniform1ui(colorUniformLocation, color * 0xff); |
| break; |
| case GL_RGBA16UI_EXT: |
| glUniform1ui(colorUniformLocation, color * 0xffff); |
| break; |
| case GL_RGBA32UI_EXT: |
| glUniform1ui(colorUniformLocation, color * 0xffffffff); |
| break; |
| default: |
| glUniform1f(colorUniformLocation, color); |
| break; |
| } |
| |
| glUniform1f(glGetUniformLocation(prog, "depthVal"), color); |
| color += color_delta; |
| |
| glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
| check_gl_error(); |
| |
| glFlush(); |
| } |
| |
| glDisable(GL_SAMPLE_MASK); |
| check_gl_error(); |
| |
| *outTextureID = tex; |
| |
| // Create an output buffer containing the expected results. |
| unsigned int size = 0; |
| if ( glType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV ) |
| { |
| size = width * height * 2; |
| } |
| else if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) || (attachment == GL_DEPTH_ATTACHMENT) || (attachment == GL_DEPTH_STENCIL_ATTACHMENT)) |
| { |
| size = width * height; |
| } |
| else |
| { |
| size = width * height * 4; |
| } |
| |
| char *data = (char *)malloc(get_explicit_type_size(type) * size * samples); |
| char *p = data; |
| size_t stride = get_explicit_type_size(type); |
| |
| for (size_t s=0;s!=samples;++s) { |
| double val = color_delta + (color_delta * s); |
| for (size_t i=0;i!=size;++i) { |
| switch (type) { |
| case kChar: |
| *((char*)p) = val * 0x7f; |
| break; |
| case kUChar: |
| *((unsigned char*)p) = val * 0xff; |
| break; |
| case kFloat: |
| *((float*)p) = val; |
| break; |
| case kShort: |
| *((short*)p) = val*0x7fff; |
| break; |
| case kUShort: |
| *((unsigned short*)p) = val*0xffff; |
| break; |
| case kInt: |
| *((int*)p) = val*0x7fffffff; |
| break; |
| case kUInt: |
| *((unsigned int*)p) = val*0xffffffff; |
| break; |
| case kHalf: |
| *((cl_ushort*)p) = convert_float_to_half(val); |
| break; |
| default: |
| log_error("Test error: unexpected type enum 0x%x\n",type); |
| } |
| |
| p += stride; |
| } |
| } |
| |
| |
| if (allocateMem) |
| reorder_verification_buffer(glFormat,glType,data,width*height*samples); |
| |
| return data; |
| } |
| |
| void * CreateGLTexture2DArrayMultisample(size_t width, size_t height, |
| size_t total_layers, size_t samples, |
| GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, |
| ExplicitType type, GLuint *outTextureID, int *outError, |
| bool allocateMem, MTdata d, bool fixedSampleLocations) |
| { |
| // This function creates a multisample texture and renders into each sample |
| // using a GLSL shader |
| |
| // Check if the renderer supports enough samples |
| GLint max_samples = get_gl_max_samples(target, internalFormat); |
| |
| if (max_samples < (GLint)samples) |
| log_error("GL error: requested samples (%d) exceeds renderer max samples (%d)\n", samples, max_samples); |
| |
| // Setup the GLSL program |
| const GLchar *vertex_source = |
| "#version 140\n" |
| "in vec4 att0;\n" |
| "void main (void) {\n" |
| " gl_Position = vec4(att0.xy,0.0,1.0);\n" |
| "}\n"; |
| |
| const GLchar *fragmentSource = |
| "#version 140\n" |
| "out %s out0;\n" |
| "uniform %s colorVal;\n" |
| "uniform float depthVal;\n" |
| "void main (void) {\n" |
| " out0 = %s(colorVal);\n" |
| " gl_FragDepth = depthVal;\n" |
| "}\n"; |
| |
| GLchar fragmentShader[256]; |
| sprintf(fragmentShader, fragmentSource, get_gl_vector_type(internalFormat), get_gl_data_type(internalFormat), get_gl_vector_type(internalFormat)); |
| const GLchar *fragment_source = &fragmentShader[0]; |
| |
| glShaderWrapper vertex_shader = glCreateShader(GL_VERTEX_SHADER); |
| glShaderSource(vertex_shader, 1, &vertex_source, NULL); |
| glCompileShader(vertex_shader); |
| check_gl_error() |
| |
| glShaderWrapper fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); |
| glShaderSource(fragment_shader, 1, &fragment_source, NULL); |
| glCompileShader(fragment_shader); |
| check_gl_error() |
| |
| glProgramWrapper prog = glCreateProgram(); |
| glAttachShader(prog, vertex_shader); |
| glAttachShader(prog, fragment_shader); |
| check_gl_error() |
| |
| glBindAttribLocation(prog, 0, "att0"); |
| glLinkProgram(prog); |
| check_gl_error() |
| |
| // Setup the FBO and texture |
| glFramebufferWrapper fbo; |
| glGenFramebuffers(1, &fbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| check_gl_error() |
| |
| glViewport(0, 0, width, height); |
| check_gl_error() |
| |
| GLuint tex = 0; |
| glGenTextures(1, &tex); |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tex); |
| glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, samples, internalFormat, width, height, total_layers, fixedSampleLocations); |
| check_gl_error() |
| |
| GLint attachment; |
| switch (internalFormat) { |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT32F: |
| attachment = GL_DEPTH_ATTACHMENT; |
| break; |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| attachment = GL_DEPTH_STENCIL_ATTACHMENT; |
| break; |
| default: |
| attachment = GL_COLOR_ATTACHMENT0; |
| break; |
| } |
| |
| //calculating colors |
| double color_delta = 1.0 / (total_layers * samples); |
| double color = color_delta; |
| |
| if (attachment != GL_DEPTH_ATTACHMENT && attachment != GL_DEPTH_STENCIL_ATTACHMENT) { |
| glDisable(GL_DEPTH_TEST); |
| check_gl_error() |
| } |
| else { |
| glEnable(GL_DEPTH_TEST); |
| glDepthFunc(GL_ALWAYS); |
| check_gl_error() |
| } |
| |
| // Setup the VBO for rendering a quad |
| GLfloat quad[] = { |
| -1.0f, -1.0f, |
| 1.0f, -1.0f, |
| 1.0f, 1.0f, |
| -1.0f, 1.0f |
| }; |
| |
| glBufferWrapper vbo; |
| glGenBuffers(1, &vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, vbo); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW); |
| check_gl_error() |
| |
| glVertexArraysWrapper vao; |
| glGenVertexArrays(1, &vao); |
| glBindVertexArray(vao); |
| glEnableVertexAttribArray(0); |
| glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, 0); |
| check_gl_error() |
| |
| for (size_t l=0; l!=total_layers; ++l) { |
| glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, tex, 0, l); |
| check_gl_error() |
| |
| GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
| if (status == GL_FRAMEBUFFER_UNSUPPORTED) { |
| log_info("GL status: GL_FRAMEBUFFER_UNSUPPORTED format %s multisample array is not supported\n", GetGLFormatName(internalFormat)); |
| *outTextureID = 0; |
| *outError = GL_FRAMEBUFFER_UNSUPPORTED; |
| return NULL; |
| } |
| |
| if (status != GL_FRAMEBUFFER_COMPLETE) { |
| log_error("GL error: framebuffer incomplete status 0x%04X\n",status); |
| *outTextureID = 0; |
| *outError = status; |
| return NULL; |
| } |
| |
| // Check if the framebuffer supports enough samples |
| GLint fbo_samples = 0; |
| glGetIntegerv(GL_SAMPLES, &fbo_samples); |
| check_gl_error(); |
| |
| if (fbo_samples < (GLint)samples) |
| log_error("GL Error: requested samples (%d) exceeds FBO capability (%d)\n", samples, fbo_samples); |
| |
| glUseProgram(prog); |
| check_gl_error() |
| |
| //clearing color and depth buffer |
| glClearColor(0, 0, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glClearDepth(1.0); |
| glClear(GL_DEPTH_BUFFER_BIT); |
| |
| glEnable(GL_SAMPLE_MASK); |
| for (size_t s=0;s!=samples;++s) { |
| double val = color_delta + color_delta * (l * samples + s); |
| |
| glSampleMaski(0, 1<<s); |
| GLint colorUniformLocation = glGetUniformLocation(prog, "colorVal"); |
| switch (internalFormat) { |
| case GL_RGBA8I_EXT: |
| glUniform1i(colorUniformLocation, val * 0x7f); |
| break; |
| case GL_RGBA16I_EXT: |
| glUniform1i(colorUniformLocation, val * 0x7fff); |
| break; |
| case GL_RGBA32I_EXT: |
| glUniform1i(colorUniformLocation, val * 0x7fffffff); |
| break; |
| case GL_RGBA8UI_EXT: |
| glUniform1ui(colorUniformLocation, val * 0xff); |
| break; |
| case GL_RGBA16UI_EXT: |
| glUniform1ui(colorUniformLocation, val * 0xffff); |
| break; |
| case GL_RGBA32UI_EXT: |
| glUniform1ui(colorUniformLocation, val * 0xffffffff); |
| break; |
| default: |
| glUniform1f(colorUniformLocation, val); |
| break; |
| } |
| |
| glUniform1f(glGetUniformLocation(prog, "depthVal"), val); |
| |
| glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
| check_gl_error(); |
| |
| glFlush(); |
| } |
| |
| glDisable(GL_SAMPLE_MASK); |
| check_gl_error(); |
| } |
| |
| *outTextureID = tex; |
| |
| // Create an output buffer containing the expected results. |
| unsigned int size = 0; |
| if ( glType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV ) |
| { |
| size = width * height * 2; |
| } |
| else if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) || (attachment == GL_DEPTH_ATTACHMENT) || (attachment == GL_DEPTH_STENCIL_ATTACHMENT)) |
| { |
| size = width * height; |
| } |
| else |
| { |
| size = width * height * 4; |
| } |
| |
| char *data = (char *)malloc(get_explicit_type_size(type) * size * total_layers * samples); |
| char *p = data; |
| size_t stride = get_explicit_type_size(type); |
| |
| for (size_t s=0;s!=samples;++s) { |
| for (size_t l=0;l!=total_layers;++l) { |
| double val = color_delta + color_delta * (l * samples + s); |
| for (size_t i=0;i!=size;++i) { |
| switch (type) { |
| case kChar: |
| *((char*)p) = val * 0x7f; |
| break; |
| case kUChar: |
| *((unsigned char*)p) = val*0xff; |
| break; |
| case kFloat: |
| *((float*)p) = val; |
| break; |
| case kShort: |
| *((short*)p) = val * 0x7fff; |
| break; |
| case kUShort: |
| *((unsigned short*)p) = val * 0xffff; |
| break; |
| case kInt: |
| *((int*)p) = val * 0x7fffffff; |
| break; |
| case kUInt: |
| *((unsigned int*)p) = val*0xffffffff; |
| break; |
| case kHalf: |
| *((cl_ushort*)p) = convert_float_to_half(val); |
| break; |
| default: |
| log_error("Test error: unexpected type enum 0x%x\n",type); |
| } |
| |
| p += stride; |
| } |
| } |
| } |
| |
| if (allocateMem) |
| reorder_verification_buffer(glFormat,glType,data,width*height*samples*total_layers); |
| |
| return data; |
| } |
| |
| #endif // GL_VERSION_3_2 |
| |
| void * CreateGLRenderbuffer( GLsizei width, GLsizei height, |
| GLenum attachment, GLenum glFormat, |
| GLenum internalFormat, GLenum glType, |
| ExplicitType type, |
| GLuint *outFramebuffer, |
| GLuint *outRenderbuffer, |
| int *outError, MTdata d, bool allocateMem ) |
| { |
| *outError = CreateGLRenderbufferRaw( width, height, attachment, glFormat, internalFormat, |
| glType, outFramebuffer, outRenderbuffer ); |
| |
| if( *outError != 0 ) |
| return NULL; |
| |
| GLenum err = 0; |
| |
| // Generate a renderbuffer and bind |
| glGenRenderbuffersEXT( 1, outRenderbuffer ); |
| glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); |
| |
| // Allocate storage to the renderbuffer |
| glGetError(); |
| glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, internalFormat, (GLsizei)width, (GLsizei)height ); |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| *outError = 1701; |
| log_error("Failed to allocate render buffer storage!\n"); |
| return NULL; |
| } |
| |
| GLint realInternalFormat; |
| glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); |
| internalFormat = realInternalFormat; |
| |
| #ifdef DEBUG |
| GLint rsize, gsize, bsize, asize; |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); |
| glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); |
| |
| log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", |
| GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), |
| rsize, gsize, bsize, asize ); |
| #endif |
| |
| // Create and bind a framebuffer to render with |
| glGenFramebuffersEXT( 1, outFramebuffer ); |
| glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Unable to bind framebuffer : Error %s\n", |
| gluErrorString( err )); |
| |
| *outError = -1; |
| return NULL; |
| } |
| |
| // Attach to the framebuffer |
| glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); |
| err = glGetError(); |
| GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); |
| if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) |
| { |
| *outError = -1; |
| log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); |
| return NULL; |
| } |
| |
| void* buffer = CreateRandomData(type, width * height * 4, d); |
| |
| #ifdef DEBUG |
| log_info( "- Fillling renderbuffer: %d : %d : %s : %s \n", |
| (int)width, (int)height, |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType)); |
| |
| DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); |
| #endif |
| |
| // Fill a texture with our input data |
| glTextureWrapper texture; |
| glGenTextures( 1, &texture ); |
| glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); |
| glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); |
| glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); |
| glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, internalFormat, width, height, 0, glFormat, glType, buffer ); |
| glEnable( GL_TEXTURE_RECTANGLE_ARB ); |
| |
| // Render fullscreen textured quad |
| glDisable( GL_LIGHTING ); |
| glViewport(0, 0, width, height); |
| glMatrixMode(GL_MODELVIEW); |
| glLoadIdentity(); |
| glMatrixMode( GL_TEXTURE ); |
| glLoadIdentity(); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glClear(GL_COLOR_BUFFER_BIT); |
| gluOrtho2D( -1.0, 1.0, -1.0, 1.0 ); |
| glMatrixMode( GL_MODELVIEW ); |
| glBegin( GL_QUADS ); |
| { |
| glColor3f(1.0f, 1.0f, 1.0f); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( -1.0f, -1.0f, 0.0f ); |
| glTexCoord2f( 0.0f, height ); |
| glVertex3f( -1.0f, 1.0f, 0.0f ); |
| glTexCoord2f( width, height ); |
| glVertex3f( 1.0f, 1.0f, 0.0f ); |
| glTexCoord2f( width, 0.0f ); |
| glVertex3f( 1.0f, -1.0f, 0.0f ); |
| } |
| glEnd(); |
| glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 ); |
| glDisable( GL_TEXTURE_RECTANGLE_ARB ); |
| |
| glFlush(); |
| |
| // Read back the data in the renderbuffer |
| memset(buffer, 0, width * height * 4 * get_explicit_type_size( type )); |
| glReadBuffer( attachment ); |
| |
| glReadPixels( 0, 0, (GLsizei)width, (GLsizei)height, glFormat, glType, buffer ); |
| |
| err = glGetError(); |
| if( err != GL_NO_ERROR ) |
| { |
| log_error( "ERROR: Unable to read data via glReadPixels : %d : %d : %s : %s : Error %s\n", |
| (int)width, (int)height, |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType), |
| gluErrorString( err )); |
| *outError = -1; |
| } |
| |
| #ifdef DEBUG |
| log_info( "- glReadPixels: %d : %d : %s : %s \n", |
| (int)width, (int)height, |
| GetGLFormatName(glFormat), |
| GetGLTypeName(glType)); |
| |
| DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); |
| #endif |
| |
| if( !allocateMem ) |
| { |
| free( buffer ); |
| return NULL; |
| } |
| |
| if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < (size_t)width * height; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc2; |
| p[ i * 4 + 1 ] = uc1; |
| p[ i * 4 + 2 ] = uc0; |
| p[ i * 4 + 3 ] = uc3; |
| } |
| } |
| else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) |
| { |
| // Reverse and reorder to validate since in the |
| // kernel the read_imagef() call always returns RGBA |
| cl_uchar *p = (cl_uchar *)buffer; |
| for( size_t i = 0; i < width * height; i++ ) |
| { |
| cl_uchar uc0 = p[i * 4 + 0]; |
| cl_uchar uc1 = p[i * 4 + 1]; |
| cl_uchar uc2 = p[i * 4 + 2]; |
| cl_uchar uc3 = p[i * 4 + 3]; |
| |
| p[ i * 4 + 0 ] = uc1; |
| p[ i * 4 + 1 ] = uc2; |
| p[ i * 4 + 2 ] = uc3; |
| p[ i * 4 + 3 ] = uc0; |
| } |
| } |
| |
| return buffer; |
| } |
| |
| void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, |
| GLenum attachment, GLenum glFormat, |
| GLenum glInternalFormat, GLenum glType, |
| ExplicitType typeToReadAs, |
| size_t outWidth, size_t outHeight ) |
| { |
| glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, glFramebuffer ); |
| glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, glRenderbuffer ); |
| |
| // Attach to the framebuffer |
| GLint err = glGetError(); |
| if( glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ) != GL_FRAMEBUFFER_COMPLETE_EXT ) |
| { |
| log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s)\n", gluErrorString( err ) ); |
| return NULL; |
| } |
| |
| // Read results from the GL renderbuffer |
| #ifdef DEBUG |
| log_info( "- Reading back from GL: %d x %d : %s : %s : %s\n", |
| (int)outWidth, (int)outHeight, |
| GetGLFormatName( glInternalFormat ), |
| GetGLFormatName( glFormat ), |
| GetGLTypeName( glType )); |
| #endif |
| |
| GLenum readBackFormat = glFormat == GL_RGBA_INTEGER_EXT ? GL_RGBA_INTEGER_EXT : GL_RGBA; |
| GLenum readBackType = glType; |
| |
| size_t outBytes = outWidth * outHeight * 4 * GetGLTypeSize(readBackType); |
| void *outBuffer = malloc( outBytes ); |
| memset(outBuffer, 0, outBytes); |
| |
| glReadPixels( 0, 0, (GLsizei)outWidth, (GLsizei)outHeight, readBackFormat, readBackType, outBuffer ); |
| |
| #ifdef DEBUG |
| log_info( "- glReadPixels: %d : %d : %s : %s \n", |
| (int)outWidth, (int)outHeight, |
| GetGLFormatName(readBackFormat), |
| GetGLTypeName(readBackType)); |
| |
| DumpGLBuffer(readBackType, outWidth, outHeight, outBuffer); |
| #endif |
| |
| return (void *)outBuffer; |
| } |
| |
| GLenum |
| GetGLFormat(GLenum internalFormat) |
| { |
| GLenum glFormat; |
| switch (internalFormat) |
| { |
| case GL_BGRA: |
| case GL_RGBA8: |
| case GL_RGBA16: |
| case GL_RGBA32F_ARB: |
| glFormat = GL_RGBA; |
| break; |
| case GL_RGBA8I_EXT: |
| case GL_RGBA16I_EXT: |
| case GL_RGBA32I_EXT: |
| case GL_RGBA8UI_EXT: |
| case GL_RGBA16UI_EXT: |
| case GL_RGBA32UI_EXT: |
| glFormat = GL_RGBA_INTEGER_EXT; |
| break; |
| default: |
| glFormat = GL_RGBA; |
| break; |
| } |
| |
| return glFormat; |
| } |
| |
| GLenum GetGLTypeForExplicitType(ExplicitType type) |
| { |
| switch( type ) |
| { |
| case kFloat: |
| return GL_FLOAT; |
| case kInt: |
| return GL_INT; |
| case kUInt: |
| return GL_UNSIGNED_INT; |
| case kShort: |
| return GL_SHORT; |
| case kUShort: |
| return GL_UNSIGNED_SHORT; |
| case kChar: |
| return GL_BYTE; |
| case kUChar: |
| return GL_UNSIGNED_BYTE; |
| case kHalf: |
| #if defined( __APPLE__ ) |
| return GL_HALF_FLOAT; |
| #else |
| return GL_HALF_FLOAT_ARB; |
| #endif |
| default: |
| return GL_INT; |
| }; |
| } |
| |
| size_t GetGLTypeSize(GLenum type) |
| { |
| switch( type ) |
| { |
| case GL_FLOAT: |
| return sizeof(GLfloat); |
| case GL_INT: |
| return sizeof(GLint); |
| case GL_UNSIGNED_INT: |
| case GL_UNSIGNED_INT_10_10_10_2: |
| case GL_UNSIGNED_INT_2_10_10_10_REV: |
| case GL_UNSIGNED_INT_24_8: |
| return sizeof(GLuint); |
| case GL_SHORT: |
| return sizeof(GLshort); |
| case GL_UNSIGNED_SHORT: |
| return sizeof(GLushort); |
| case GL_UNSIGNED_INT_8_8_8_8_REV: |
| case GL_BYTE: |
| return sizeof(GLbyte); |
| case GL_UNSIGNED_BYTE: |
| return sizeof(GLubyte); |
| #if defined( __APPLE__ ) |
| case GL_HALF_FLOAT: |
| #else |
| case GL_HALF_FLOAT_ARB: |
| #endif |
| return sizeof(GLhalf); |
| case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: |
| return 2 * sizeof(GLfloat); |
| default: |
| log_error("Unknown type 0x%x\n",type); |
| return 0; |
| }; |
| } |
| |
| ExplicitType GetExplicitTypeForGLType(GLenum type) |
| { |
| switch( type ) |
| { |
| case GL_FLOAT: |
| return kFloat; |
| case GL_INT: |
| return kInt; |
| case GL_UNSIGNED_INT: |
| return kUInt; |
| case GL_SHORT: |
| return kShort; |
| case GL_UNSIGNED_SHORT: |
| return kUShort; |
| case GL_BYTE: |
| return kChar; |
| case GL_UNSIGNED_BYTE: |
| return kUChar; |
| #if defined( __APPLE__ ) |
| case GL_HALF_FLOAT: |
| #else |
| case GL_HALF_FLOAT_ARB: |
| #endif |
| return kHalf; |
| default: |
| return kFloat; |
| }; |
| } |
| |
| GLenum get_base_gl_target( GLenum target ) |
| { |
| switch( target ) |
| { |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |
| return GL_TEXTURE_CUBE_MAP; |
| default: |
| return target; |
| } |
| } |
| |
| const char *GetGLTypeName( GLenum type ) |
| { |
| switch( type ) |
| { |
| case GL_BYTE: return "GL_BYTE"; |
| case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; |
| case GL_INT: return "GL_INT"; |
| case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; |
| case GL_SHORT: return "GL_SHORT"; |
| case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; |
| #if defined( __APPLE__ ) |
| case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; |
| #else |
| case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; |
| #endif |
| case GL_FLOAT: return "GL_FLOAT"; |
| case GL_UNSIGNED_INT_8_8_8_8: return "GL_UNSIGNED_INT_8_8_8_8"; |
| case GL_UNSIGNED_INT_8_8_8_8_REV: return "GL_UNSIGNED_INT_8_8_8_8_REV"; |
| case GL_UNSIGNED_INT_10_10_10_2: return "GL_UNSIGNED_INT_10_10_10_2"; |
| case GL_UNSIGNED_INT_2_10_10_10_REV: return "GL_UNSIGNED_INT_2_10_10_10_REV"; |
| #ifdef GL_VERSION_3_2 |
| case GL_UNSIGNED_INT_24_8: return "GL_UNSIGNED_INT_24_8"; |
| case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: return "GL_FLOAT_32_UNSIGNED_INT_24_8_REV"; |
| #endif |
| default: |
| { |
| static char foo[ 128 ]; |
| sprintf( foo, "0x%04x", (int)type); |
| return foo; |
| } |
| } |
| } |
| |
| const char *GetGLTargetName( GLenum tgt ) |
| { |
| if( tgt == GL_TEXTURE_BUFFER ) return "GL_TEXTURE_BUFFER"; |
| if( tgt == GL_TEXTURE_1D ) return "GL_TEXTURE_1D"; |
| if( tgt == GL_TEXTURE_2D ) return "GL_TEXTURE_2D"; |
| if( tgt == GL_TEXTURE_3D ) return "GL_TEXTURE_3D"; |
| if( tgt == GL_TEXTURE_RECTANGLE_EXT ) return "GL_TEXTURE_RECTANGLE_EXT"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_X ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; |
| if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; |
| if( tgt == GL_TEXTURE_2D_MULTISAMPLE ) return "GL_TEXTURE_2D_MULTISAMPLE"; |
| if( tgt == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ) return "GL_TEXTURE_2D_MULTISAMPLE_ARRAY"; |
| |
| static char foo[ 128 ]; |
| sprintf( foo, "0x%04x", (int)tgt); |
| return foo; |
| } |
| |
| const char *GetGLAttachmentName( GLenum att ) |
| { |
| if( att == GL_COLOR_ATTACHMENT0_EXT ) return "GL_COLOR_ATTACHMENT0_EXT"; |
| if( att == GL_COLOR_ATTACHMENT1_EXT ) return "GL_COLOR_ATTACHMENT1_EXT"; |
| if( att == GL_COLOR_ATTACHMENT2_EXT ) return "GL_COLOR_ATTACHMENT2_EXT"; |
| if( att == GL_COLOR_ATTACHMENT3_EXT ) return "GL_COLOR_ATTACHMENT3_EXT"; |
| if( att == GL_COLOR_ATTACHMENT4_EXT ) return "GL_COLOR_ATTACHMENT4_EXT"; |
| if( att == GL_COLOR_ATTACHMENT5_EXT ) return "GL_COLOR_ATTACHMENT5_EXT"; |
| if( att == GL_COLOR_ATTACHMENT6_EXT ) return "GL_COLOR_ATTACHMENT6_EXT"; |
| if( att == GL_COLOR_ATTACHMENT7_EXT ) return "GL_COLOR_ATTACHMENT7_EXT"; |
| if( att == GL_COLOR_ATTACHMENT8_EXT ) return "GL_COLOR_ATTACHMENT8_EXT"; |
| if( att == GL_DEPTH_ATTACHMENT_EXT ) return "GL_DEPTH_ATTACHMENT_EXT"; |
| return ""; |
| } |
| const char *GetGLBaseFormatName( GLenum baseformat ) |
| { |
| switch( baseformat ) |
| { |
| case GL_RGBA8: return "GL_RGBA"; |
| case GL_RGBA16: return "GL_RGBA"; |
| case GL_RGBA: return "GL_RGBA"; |
| case GL_BGRA: return "GL_BGRA"; |
| case GL_RGBA8I_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA16I_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA32I_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA8UI_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA16UI_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA32UI_EXT: return "GL_RGBA_INTEGER_EXT"; |
| case GL_RGBA32F_ARB: return "GL_RGBA"; |
| |
| case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; |
| |
| case GL_ALPHA4: return "GL_ALPHA"; |
| case GL_ALPHA8: return "GL_ALPHA"; |
| case GL_ALPHA12: return "GL_ALPHA"; |
| case GL_ALPHA16: return "GL_ALPHA"; |
| case GL_LUMINANCE4: return "GL_LUMINANCE"; |
| case GL_LUMINANCE8: return "GL_LUMINANCE"; |
| case GL_LUMINANCE12: return "GL_LUMINANCE"; |
| case GL_LUMINANCE16: return "GL_LUMINANCE"; |
| case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE_ALPHA"; |
| case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE_ALPHA"; |
| case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE_ALPHA"; |
| case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE_ALPHA"; |
| case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE_ALPHA"; |
| case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE_ALPHA"; |
| case GL_INTENSITY: return "GL_INTENSITY"; |
| case GL_INTENSITY4: return "GL_INTENSITY"; |
| case GL_INTENSITY8: return "GL_INTENSITY"; |
| case GL_INTENSITY12: return "GL_INTENSITY"; |
| case GL_INTENSITY16: return "GL_INTENSITY"; |
| case GL_R3_G3_B2: return "GL_RGB"; |
| case GL_RGB4: return "GL_RGB"; |
| case GL_RGB5: return "GL_RGB"; |
| case GL_RGB8: return "GL_RGB"; |
| case GL_RGB10: return "GL_RGB"; |
| case GL_RGB12: return "GL_RGB"; |
| case GL_RGB16: return "GL_RGB"; |
| case GL_RGBA2: return "GL_RGBA"; |
| case GL_RGBA4: return "GL_RGBA"; |
| case GL_RGB5_A1: return "GL_RGBA"; |
| case GL_RGB10_A2: return "GL_RGBA"; |
| case GL_RGBA12: return "GL_RGBA"; |
| #ifdef GL_VERSION_3_2 |
| case GL_DEPTH_COMPONENT: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_COMPONENT16: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_COMPONENT24: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_COMPONENT32: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_COMPONENT32F: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_STENCIL: return "GL_DEPTH_STENCIL"; |
| case GL_DEPTH24_STENCIL8: return "GL_DEPTH_STENCIL"; |
| case GL_DEPTH32F_STENCIL8: return "GL_DEPTH_STENCIL"; |
| #endif |
| default: |
| { |
| static char foo[ 128 ]; |
| sprintf( foo, "0x%04x", (int)baseformat ); |
| return foo; |
| } |
| } |
| } |
| |
| const char *GetGLFormatName( GLenum format ) |
| { |
| switch( format ) |
| { |
| case GL_RGBA8: return "GL_RGBA8"; |
| case GL_RGBA16: return "GL_RGBA16"; |
| case GL_RGBA: return "GL_RGBA"; |
| case GL_BGRA: return "GL_BGRA"; |
| case GL_RGBA8I_EXT: return "GL_RGBA8I_EXT"; |
| case GL_RGBA16I_EXT: return "GL_RGBA16I_EXT"; |
| case GL_RGBA32I_EXT: return "GL_RGBA32I_EXT"; |
| case GL_RGBA8UI_EXT: return "GL_RGBA8UI_EXT"; |
| case GL_RGBA16UI_EXT: return "GL_RGBA16UI_EXT"; |
| case GL_RGBA32UI_EXT: return "GL_RGBA32UI_EXT"; |
| case GL_RGBA16F: return "GL_RGBA16F"; |
| case GL_RGBA32F: return "GL_RGBA32F"; |
| |
| case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; |
| |
| case GL_ALPHA4: return "GL_ALPHA4"; |
| case GL_ALPHA8: return "GL_ALPHA8"; |
| case GL_ALPHA12: return "GL_ALPHA12"; |
| case GL_ALPHA16: return "GL_ALPHA16"; |
| case GL_LUMINANCE4: return "GL_LUMINANCE4"; |
| case GL_LUMINANCE8: return "GL_LUMINANCE8"; |
| case GL_LUMINANCE12: return "GL_LUMINANCE12"; |
| case GL_LUMINANCE16: return "GL_LUMINANCE16"; |
| case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE4_ALPHA4"; |
| case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE6_ALPHA2"; |
| case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE8_ALPHA8"; |
| case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE12_ALPHA4"; |
| case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE12_ALPHA12"; |
| case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE16_ALPHA16"; |
| case GL_INTENSITY: return "GL_INTENSITY"; |
| case GL_INTENSITY4: return "GL_INTENSITY4"; |
| case GL_INTENSITY8: return "GL_INTENSITY8"; |
| case GL_INTENSITY12: return "GL_INTENSITY12"; |
| case GL_INTENSITY16: return "GL_INTENSITY16"; |
| case GL_R3_G3_B2: return "GL_R3_G3_B2"; |
| case GL_RGB4: return "GL_RGB4"; |
| case GL_RGB5: return "GL_RGB5"; |
| case GL_RGB8: return "GL_RGB8"; |
| case GL_RGB10: return "GL_RGB10"; |
| case GL_RGB12: return "GL_RGB12"; |
| case GL_RGB16: return "GL_RGB16"; |
| case GL_RGBA2: return "GL_RGBA2"; |
| case GL_RGBA4: return "GL_RGBA4"; |
| case GL_RGB5_A1: return "GL_RGB5_A1"; |
| case GL_RGB10_A2: return "GL_RGB10_A2"; |
| case GL_RGBA12: return "GL_RGBA12"; |
| |
| case GL_INT: return "GL_INT"; |
| case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; |
| case GL_SHORT: return "GL_SHORT"; |
| case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; |
| case GL_BYTE: return "GL_BYTE"; |
| case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; |
| case GL_FLOAT: return "GL_FLOAT"; |
| #if defined( __APPLE__ ) |
| case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; |
| #else |
| case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; |
| #endif |
| #ifdef GL_VERSION_3_2 |
| case GL_DEPTH_STENCIL: return "GL_DEPTH_STENCIL"; |
| case GL_DEPTH_COMPONENT: return "GL_DEPTH_COMPONENT"; |
| case GL_DEPTH_COMPONENT16: return "GL_DEPTH_COMPONENT16"; |
| case GL_DEPTH_COMPONENT24: return "GL_DEPTH_COMPONENT24"; |
| case GL_DEPTH_COMPONENT32: return "GL_DEPTH_COMPONENT32"; |
| case GL_DEPTH_COMPONENT32F: return "GL_DEPTH_COMPONENT32F"; |
| case GL_DEPTH24_STENCIL8: return "GL_DEPTH24_STENCIL8"; |
| case GL_DEPTH32F_STENCIL8: return "GL_DEPTH32F_STENCIL8"; |
| #endif |
| default: |
| { |
| static char foo[ 128 ]; |
| sprintf( foo, "0x%04x", (int)format); |
| return foo; |
| } |
| } |
| } |
| |
| void* CreateRandomData( ExplicitType type, size_t count, MTdata d ) |
| { |
| switch(type) |
| { |
| case (kChar): |
| { |
| cl_char *p = (cl_char *)malloc(count * sizeof(cl_char)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_char)genrand_int32(d); |
| } |
| return (void*)p; |
| } |
| case (kUChar): |
| case (kUnsignedChar): |
| { |
| cl_uchar *p = (cl_uchar *)malloc(count * sizeof(cl_uchar)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_uchar)genrand_int32(d); |
| } |
| |
| return (void*)p; |
| } |
| case (kShort): |
| { |
| cl_short *p = (cl_short *)malloc(count * sizeof(cl_short)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_short)genrand_int32(d); |
| } |
| |
| return (void*)p; |
| } |
| case (kUShort): |
| case (kUnsignedShort): |
| { |
| cl_ushort *p = (cl_ushort *)malloc(count * sizeof(cl_ushort)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_ushort)genrand_int32(d); |
| } |
| |
| return (void*)p; |
| } |
| case (kInt): |
| { |
| cl_int *p = (cl_int *)malloc(count * sizeof(cl_int)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_int)genrand_int32(d); |
| } |
| |
| return (void*)p; |
| } |
| case (kUInt): |
| case (kUnsignedInt): |
| { |
| cl_uint *p = (cl_uint *)malloc(count * sizeof(cl_uint)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = (cl_uint)genrand_int32(d); |
| } |
| |
| return (void*)p; |
| } |
| |
| case (kFloat): |
| { |
| cl_float *p = (cl_float *)malloc(count * sizeof(cl_float)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = get_random_float( 0.f, 1.f, d ); |
| } |
| |
| return (void*)p; |
| } |
| case (kHalf): |
| { |
| cl_half *p = (cl_half *)malloc(count * sizeof(cl_half)); |
| if(!p) return 0; |
| |
| for( size_t i = 0; i < count; i++ ) |
| { |
| p[ i ] = convert_float_to_half( get_random_float( 0.f, 1.f, d ) ); |
| } |
| |
| return (void*)p; |
| } |
| default: |
| { |
| log_error("Invalid explicit type specified for create random data!\n"); |
| return 0; |
| } |
| } |
| return 0; |
| } |
| |
| void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer) |
| { |
| size_t i; |
| size_t count = width * height; |
| if(type == GL_BYTE) |
| { |
| cl_char* p = (cl_char*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_UNSIGNED_BYTE) |
| { |
| cl_uchar* p = (cl_uchar*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_INT) |
| { |
| cl_int* p = (cl_int*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_UNSIGNED_INT) |
| { |
| cl_uint* p = (cl_uint*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_SHORT) |
| { |
| cl_short* p = (cl_short*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_UNSIGNED_SHORT) |
| { |
| cl_ushort* p = (cl_ushort*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| else if(type == GL_FLOAT) |
| { |
| cl_float* p = (cl_float*)buffer; |
| for(i = 0; i < count; i++) |
| log_info("[%4d] %#f %#f %#f %#f\n", (unsigned int)(i), |
| p[i* 4 + 0], |
| p[i* 4 + 1], |
| p[i* 4 + 2], |
| p[i* 4 + 3]); |
| } |
| } |
| |
| #if defined(_WIN32) |
| #include <string.h> |
| |
| GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString) |
| { |
| const size_t len = strlen((const char*)extName); |
| const char* str = (const char*)extString; |
| |
| while (str != NULL) { |
| str = strstr(str, (const char*)extName); |
| if (str == NULL) { |
| break; |
| } |
| if ((str > (const char*)extString || str[-1] == ' ') |
| && (str[len] == ' ' || str[len] == '\0')) { |
| return GL_TRUE; |
| } |
| str = strchr(str + len, ' '); |
| } |
| |
| return GL_FALSE; |
| } |
| |
| #endif |
| |
| // Function pointers for the GL/CL calls |
| clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; |
| clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; |
| clCreateFromGLTexture2D_fn clCreateFromGLTexture2D_ptr; |
| clCreateFromGLTexture3D_fn clCreateFromGLTexture3D_ptr; |
| clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; |
| clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; |
| clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; |
| clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; |
| clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; |
| |
| int init_clgl_ext() { |
| |
| // As OpenCL for the platforms. Warn if more than one platform found, |
| // since this might not be the platform we want. By default, we simply |
| // use the first returned platform. |
| |
| cl_uint nplatforms; |
| cl_platform_id platform; |
| clGetPlatformIDs(0, NULL, &nplatforms); |
| clGetPlatformIDs(1, &platform, NULL); |
| |
| if (nplatforms > 1) { |
| log_info("clGetPlatformIDs returned multiple values. This is not " |
| "an error, but might result in obtaining incorrect function " |
| "pointers if you do not want the first returned platform.\n"); |
| |
| // Show them the platform name, in case it is a problem. |
| |
| size_t size; |
| char *name; |
| |
| clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); |
| name = (char*)malloc(size); |
| clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); |
| |
| log_info("Using platform with name: %s \n", name); |
| free(name); |
| } |
| |
| // Create the function pointer table |
| clCreateFromGLBuffer_ptr = (clCreateFromGLBuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLBuffer"); |
| if (clCreateFromGLBuffer_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLBuffer) returned NULL.\n"); |
| return -1; |
| } |
| clCreateFromGLTexture2D_ptr = (clCreateFromGLTexture2D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture2D"); |
| if (clCreateFromGLTexture2D_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture2D) returned NULL.\n"); |
| return -1; |
| } |
| clCreateFromGLTexture3D_ptr = (clCreateFromGLTexture3D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture3D"); |
| if (clCreateFromGLTexture3D_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture3D\") returned NULL.\n"); |
| return -1; |
| } |
| clCreateFromGLTexture_ptr = (clCreateFromGLTexture_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture"); |
| if (clCreateFromGLTexture_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,\"clCreateFromGLTexture\") returned NULL.\n"); |
| return -1; |
| } |
| clCreateFromGLRenderbuffer_ptr = (clCreateFromGLRenderbuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLRenderbuffer"); |
| if (clCreateFromGLRenderbuffer_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLRenderbuffer) returned NULL.\n"); |
| return -1; |
| } |
| clGetGLObjectInfo_ptr = (clGetGLObjectInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLObjectInfo"); |
| if (clGetGLObjectInfo_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLObjectInfo) returned NULL.\n"); |
| return -1; |
| } |
| clGetGLTextureInfo_ptr = (clGetGLTextureInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLTextureInfo"); |
| if (clGetGLTextureInfo_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLTextureInfo) returned NULL.\n"); |
| return -1; |
| } |
| clEnqueueAcquireGLObjects_ptr = (clEnqueueAcquireGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueAcquireGLObjects"); |
| if (clEnqueueAcquireGLObjects_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueAcquireGLObjects) returned NULL.\n"); |
| return -1; |
| } |
| clEnqueueReleaseGLObjects_ptr = (clEnqueueReleaseGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueReleaseGLObjects"); |
| if (clEnqueueReleaseGLObjects_ptr == NULL) { |
| log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueReleaseGLObjects) returned NULL.\n"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| GLint get_gl_max_samples( GLenum target, GLenum internalformat ) |
| { |
| GLint max_samples = 0; |
| #ifdef GL_VERSION_4_2 |
| glGetInternalformativ(target, internalformat, GL_SAMPLES, 1, &max_samples); |
| #else |
| switch (internalformat) |
| { |
| case GL_RGBA8I: |
| case GL_RGBA16I: |
| case GL_RGBA32I: |
| case GL_RGBA8UI: |
| case GL_RGBA16UI: |
| case GL_RGBA32UI: |
| glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &max_samples); |
| break; |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT32F: |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &max_samples); |
| break; |
| default: |
| glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_samples); |
| break; |
| } |
| #endif |
| return max_samples; |
| } |