You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2489 lines
78 KiB
2489 lines
78 KiB
//
|
|
// 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"
|
|
|
|
#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_half *)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_half *)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;
|
|
}
|