1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "testBase.h"
17 #if defined( __APPLE__ )
18         #include <OpenGL/glu.h>
19 #else
20         #include <GL/glu.h>
21 #endif
22 
get_kernel_suffix(cl_image_format * format)23 const char *get_kernel_suffix( cl_image_format *format )
24 {
25     switch( format->image_channel_data_type )
26     {
27         case CL_UNORM_INT8:
28         case CL_UNORM_INT16:
29     case CL_UNORM_INT24:
30         case CL_SNORM_INT8:
31         case CL_SNORM_INT16:
32         case CL_HALF_FLOAT:
33         case CL_FLOAT:
34         case CL_UNORM_INT_101010:
35             return "f";
36         case CL_SIGNED_INT8:
37         case CL_SIGNED_INT16:
38         case CL_SIGNED_INT32:
39             return "i";
40         case CL_UNSIGNED_INT8:
41         case CL_UNSIGNED_INT16:
42         case CL_UNSIGNED_INT32:
43             return "ui";
44         default:
45       log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type);
46             return "";
47     }
48 }
49 
get_read_kernel_type(cl_image_format * format)50 ExplicitType get_read_kernel_type( cl_image_format *format )
51 {
52     switch( format->image_channel_data_type )
53     {
54         case CL_UNORM_INT8:
55         case CL_UNORM_INT16:
56     case CL_UNORM_INT24:
57         case CL_SNORM_INT8:
58         case CL_SNORM_INT16:
59         case CL_HALF_FLOAT:
60         case CL_FLOAT:
61         case CL_UNORM_INT_101010:
62 #ifdef GL_VERSION_3_2
63     case CL_DEPTH:
64 #endif
65             return kFloat;
66         case CL_SIGNED_INT8:
67         case CL_SIGNED_INT16:
68         case CL_SIGNED_INT32:
69             return kInt;
70         case CL_UNSIGNED_INT8:
71         case CL_UNSIGNED_INT16:
72         case CL_UNSIGNED_INT32:
73             return kUInt;
74         default:
75       log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type);
76             return kNumExplicitTypes;
77     }
78 }
79 
get_write_kernel_type(cl_image_format * format)80 ExplicitType get_write_kernel_type( cl_image_format *format )
81 {
82     switch( format->image_channel_data_type )
83     {
84         case CL_UNORM_INT8:
85             return kFloat;
86         case CL_UNORM_INT16:
87             return kFloat;
88     case CL_UNORM_INT24:
89       return kFloat;
90         case CL_SNORM_INT8:
91             return kFloat;
92         case CL_SNORM_INT16:
93             return kFloat;
94         case CL_HALF_FLOAT:
95             return kHalf;
96         case CL_FLOAT:
97             return kFloat;
98         case CL_SIGNED_INT8:
99             return kChar;
100         case CL_SIGNED_INT16:
101             return kShort;
102         case CL_SIGNED_INT32:
103             return kInt;
104         case CL_UNSIGNED_INT8:
105             return kUChar;
106         case CL_UNSIGNED_INT16:
107             return kUShort;
108         case CL_UNSIGNED_INT32:
109             return kUInt;
110         case CL_UNORM_INT_101010:
111             return kFloat;
112 #ifdef GL_VERSION_3_2
113     case CL_DEPTH:
114       return kFloat;
115 #endif
116         default:
117             return kInt;
118     }
119 }
120 
get_write_conversion(cl_image_format * format,ExplicitType type)121 const char* get_write_conversion( cl_image_format *format, ExplicitType type )
122 {
123     switch( format->image_channel_data_type )
124     {
125         case CL_UNORM_INT8:
126         case CL_UNORM_INT16:
127         case CL_SNORM_INT8:
128         case CL_SNORM_INT16:
129         case CL_HALF_FLOAT:
130         case CL_FLOAT:
131         case CL_UNORM_INT_101010:
132         case CL_UNORM_INT24:
133             if(type != kFloat) return "convert_float4";
134             break;
135         case CL_SIGNED_INT8:
136         case CL_SIGNED_INT16:
137         case CL_SIGNED_INT32:
138             if(type != kInt) return "convert_int4";
139             break;
140         case CL_UNSIGNED_INT8:
141         case CL_UNSIGNED_INT16:
142         case CL_UNSIGNED_INT32:
143             if(type != kUInt) return "convert_uint4";
144             break;
145         default:
146             return "";
147     }
148     return "";
149 }
150 
151 // The only three input types to this function are kInt, kUInt and kFloat, due to the way we set up our tests
152 // The output types, though, are pretty much anything valid for GL to receive
153 
154 #define DOWNSCALE_INTEGER_CASE( enum, type, bitShift )    \
155     case enum:    \
156     {        \
157         cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
158         for( size_t i = 0; i < numPixels * 4; i++ ) \
159             dst[ i ] = src[ i ];    \
160         return (char *)dst;        \
161     }
162 
163 #define UPSCALE_FLOAT_CASE( enum, type, typeMax )    \
164     case enum:    \
165     {        \
166         cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
167         for( size_t i = 0; i < numPixels * 4; i++ ) \
168             dst[ i ] = (cl_##type)( src[ i ] * typeMax );    \
169         return (char *)dst;        \
170     }
171 
convert_to_expected(void * inputBuffer,size_t numPixels,ExplicitType inType,ExplicitType outType,size_t channelNum,GLenum glDataType)172 char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType, size_t channelNum, GLenum glDataType )
173 {
174 #ifdef DEBUG
175     log_info( "- Converting from input type '%s' to output type '%s'\n",
176              get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
177 #endif
178 
179     if( inType == outType )
180     {
181         char *outData = new char[ numPixels * channelNum * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ];
182         if (glDataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) {
183             for (size_t i = 0; i < numPixels; ++i) {
184                 ((cl_float*)outData)[i] = ((cl_float*)inputBuffer)[2 * i];
185             }
186         }
187         else {
188             memcpy( outData, inputBuffer, numPixels * channelNum * get_explicit_type_size(inType)  );
189         }
190         return outData;
191     }
192     else if( inType == kChar )
193     {
194         cl_char *src = (cl_char *)inputBuffer;
195 
196         switch( outType )
197         {
198             case kInt:
199             {
200                 cl_int *outData = new cl_int[ numPixels * channelNum ];
201                 for( size_t i = 0; i < numPixels * channelNum; i++ )
202                 {
203                     outData[ i ] = (cl_int)((src[ i ]));
204                 }
205                 return (char *)outData;
206             }
207             case kFloat:
208             {
209                 // If we're converting to float, then CL decided that we should be normalized
210                 cl_float *outData = new cl_float[ numPixels * channelNum ];
211                 for( size_t i = 0; i < numPixels * channelNum; i++ )
212                 {
213                     outData[ i ] = (cl_float)src[ i ] / 127.0f;
214                 }
215                 return (char *)outData;
216             }
217             default:
218                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
219                 return NULL;
220         }
221     }
222     else if( inType == kUChar )
223     {
224         cl_uchar *src = (cl_uchar *)inputBuffer;
225 
226         switch( outType )
227         {
228             case kUInt:
229             {
230                 cl_uint *outData = new cl_uint[ numPixels * channelNum ];
231                 for( size_t i = 0; i < numPixels * channelNum; i++ )
232                 {
233                     outData[ i ] = (cl_uint)((src[ i ]));
234                 }
235                 return (char *)outData;
236             }
237             case kFloat:
238             {
239                 // If we're converting to float, then CL decided that we should be normalized
240                 cl_float *outData = new cl_float[ numPixels * channelNum ];
241                 for( size_t i = 0; i < numPixels * channelNum; i++ )
242                 {
243                     outData[ i ] = (cl_float)(src[ i ]) / 256.0f;
244                 }
245                 return (char *)outData;
246             }
247             default:
248                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
249                 return NULL;
250         }
251     }
252     else if( inType == kShort )
253     {
254         cl_short *src = (cl_short *)inputBuffer;
255 
256         switch( outType )
257         {
258             case kInt:
259             {
260                 cl_int *outData = new cl_int[ numPixels * channelNum ];
261                 for( size_t i = 0; i < numPixels * channelNum; i++ )
262                 {
263                     outData[ i ] = (cl_int)((src[ i ]));
264                 }
265                 return (char *)outData;
266             }
267             case kFloat:
268             {
269                 // If we're converting to float, then CL decided that we should be normalized
270                 cl_float *outData = new cl_float[ numPixels * channelNum ];
271                 for( size_t i = 0; i < numPixels * channelNum; i++ )
272                 {
273                     outData[ i ] = (cl_float)src[ i ] / 32768.0f;
274                 }
275                 return (char *)outData;
276             }
277             default:
278                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
279                 return NULL;
280         }
281     }
282     else if( inType == kUShort )
283     {
284         cl_ushort *src = (cl_ushort *)inputBuffer;
285 
286         switch( outType )
287         {
288             case kUInt:
289             {
290                 cl_uint *outData = new cl_uint[ numPixels * channelNum ];
291                 for( size_t i = 0; i < numPixels * channelNum; i++ )
292                 {
293                     outData[ i ] = (cl_uint)((src[ i ]));
294                 }
295                 return (char *)outData;
296             }
297             case kFloat:
298             {
299                 // If we're converting to float, then CL decided that we should be normalized
300                 cl_float *outData = new cl_float[ numPixels * channelNum ];
301                 for( size_t i = 0; i < numPixels * channelNum; i++ )
302                 {
303                     outData[ i ] = (cl_float)(src[ i ]) / 65535.0f;
304                 }
305                 return (char *)outData;
306             }
307             default:
308                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
309                 return NULL;
310         }
311     }
312     else if( inType == kInt )
313     {
314         cl_int *src = (cl_int *)inputBuffer;
315 
316         switch( outType )
317         {
318                 DOWNSCALE_INTEGER_CASE( kShort, short, 16 )
319                 DOWNSCALE_INTEGER_CASE( kChar, char, 24 )
320             case kFloat:
321             {
322                 // If we're converting to float, then CL decided that we should be normalized
323                 cl_float *outData = new cl_float[ numPixels * channelNum ];
324                 for( size_t i = 0; i < numPixels * channelNum; i++ )
325                 {
326                     outData[ i ] = (cl_float)fmaxf( (float)src[ i ] / 2147483647.f, -1.f );
327                 }
328                 return (char *)outData;
329             }
330             default:
331                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
332                 return NULL;
333         }
334     }
335     else if( inType == kUInt )
336     {
337         cl_uint *src = (cl_uint *)inputBuffer;
338 
339         switch( outType )
340         {
341                 DOWNSCALE_INTEGER_CASE( kUShort, ushort, 16 )
342                 DOWNSCALE_INTEGER_CASE( kUChar, uchar, 24 )
343             case kFloat:
344             {
345                 // If we're converting to float, then CL decided that we should be normalized
346                 cl_float *outData = new cl_float[ numPixels * channelNum ];
347                 const cl_float MaxValue = (glDataType == GL_UNSIGNED_INT_24_8) ? 16777215.f : 4294967295.f;
348                 const cl_uint ShiftBits = (glDataType == GL_UNSIGNED_INT_24_8) ? 8 : 0;
349                 for( size_t i = 0; i < numPixels * channelNum; i++ )
350                 {
351                     outData[ i ] = (cl_float)(src[ i ] >> ShiftBits) / MaxValue;
352                 }
353                 return (char *)outData;
354             }
355             default:
356                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
357                 return NULL;
358         }
359     }
360     else if( inType == kHalf )
361     {
362         cl_half *src = (cl_half *)inputBuffer;
363 
364         switch( outType )
365         {
366             case kFloat:
367             {
368                 cl_float *outData = new cl_float[ numPixels * channelNum ];
369                 for( size_t i = 0; i < numPixels * channelNum; i++ )
370                 {
371                     outData[i] = cl_half_to_float(src[i]);
372                 }
373                 return (char *)outData;
374             }
375             default:
376                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
377                 return NULL;
378         }
379     }
380     else
381     {
382         cl_float *src = (cl_float *)inputBuffer;
383 
384         switch( outType )
385         {
386                 UPSCALE_FLOAT_CASE( kChar, char, 127.f )
387                 UPSCALE_FLOAT_CASE( kUChar, uchar, 255.f )
388                 UPSCALE_FLOAT_CASE( kShort, short, 32767.f )
389                 UPSCALE_FLOAT_CASE( kUShort, ushort, 65535.f )
390                 UPSCALE_FLOAT_CASE( kInt, int, 2147483647.f )
391                 UPSCALE_FLOAT_CASE( kUInt, uint, 4294967295.f )
392             default:
393                 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
394                 return NULL;
395         }
396     }
397 
398     return NULL;
399 }
400 
validate_integer_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t sampleNum,size_t typeSize)401 int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t typeSize )
402 {
403     return validate_integer_results( expectedResults, actualResults, width, height, sampleNum, 0, typeSize );
404 }
405 
validate_integer_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t depth,size_t sampleNum,size_t typeSize)406 int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t typeSize )
407 {
408     char *expected = (char *)expectedResults;
409     char *actual = (char *)actualResults;
410   for ( size_t s = 0; s < sampleNum; s++ )
411   {
412     for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
413     {
414         for( size_t y = 0; y < height; y++ )
415         {
416             for( size_t x = 0; x < width; x++ )
417             {
418                 if( memcmp( expected, actual, typeSize * 4 ) != 0 )
419                 {
420                     char scratch[ 1024 ];
421 
422                     if( depth == 0 )
423               log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s );
424                     else
425               log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
426                     log_error( "\tExpected: %s\n", GetDataVectorString( expected, typeSize, 4, scratch ) );
427                     log_error( "\t  Actual: %s\n", GetDataVectorString( actual, typeSize, 4, scratch ) );
428                     return -1;
429                 }
430                 expected += typeSize * 4;
431                 actual += typeSize * 4;
432             }
433         }
434     }
435   }
436 
437     return 0;
438 }
439 
validate_float_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t sampleNum,size_t channelNum)440 int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t channelNum  )
441 {
442     return validate_float_results( expectedResults, actualResults, width, height, sampleNum, 0, channelNum );
443 }
444 
validate_float_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t depth,size_t sampleNum,size_t channelNum)445 int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t channelNum )
446 {
447     cl_float *expected = (cl_float *)expectedResults;
448     cl_float *actual = (cl_float *)actualResults;
449   for ( size_t s = 0; s < sampleNum; s++ )
450   {
451     for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
452     {
453         for( size_t y = 0; y < height; y++ )
454         {
455             for( size_t x = 0; x < width; x++ )
456             {
457                 float err = 0.f;
458           for( size_t i = 0; i < channelNum; i++ )
459                 {
460                     float error = fabsf( expected[ i ] - actual[ i ] );
461                     if( error > err )
462                         err = error;
463                 }
464 
465                 if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float
466                 {
467                     if( depth == 0 )
468               log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s );
469                     else
470               log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
471 
472             if (channelNum == 4)
473             {
474                     log_error( "\tExpected: %f %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
475                     log_error( "\t        : %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
476                     log_error( "\t  Actual: %f %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
477                     log_error( "\t        : %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
478             }
479             else if(channelNum == 1)
480             {
481               log_error( "\tExpected: %f\n", expected[ 0 ] );
482               log_error( "\t        : %a\n", expected[ 0 ]  );
483               log_error( "\t  Actual: %f\n", actual[ 0 ] );
484               log_error( "\t        : %a\n", actual[ 0 ] );
485             }
486                     return -1;
487                 }
488           expected += channelNum;
489           actual += channelNum;
490             }
491         }
492     }
493   }
494 
495     return 0;
496 }
497 
validate_float_results_rgb_101010(void * expectedResults,void * actualResults,size_t width,size_t height,size_t sampleNum)498 int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum )
499 {
500     return validate_float_results_rgb_101010( expectedResults, actualResults, width, height, sampleNum, 0 );
501 }
502 
validate_float_results_rgb_101010(void * expectedResults,void * actualResults,size_t width,size_t height,size_t depth,size_t sampleNum)503 int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum )
504 {
505     cl_float *expected = (cl_float *)expectedResults;
506     cl_float *actual = (cl_float *)actualResults;
507   for ( size_t s = 0; s < sampleNum; s++ )
508   {
509     for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
510     {
511         for( size_t y = 0; y < height; y++ )
512         {
513             for( size_t x = 0; x < width; x++ )
514             {
515                 float err = 0.f;
516                 for( size_t i = 0; i < 3; i++ ) // skip the fourth channel
517                 {
518                     float error = fabsf( expected[ i ] - actual[ i ] );
519                     if( error > err )
520                         err = error;
521                 }
522 
523                 if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float
524                 {
525                     if( depth == 0 )
526               log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s );
527                     else
528               log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
529                     log_error( "\tExpected: %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] );
530                     log_error( "\t        : %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] );
531                     log_error( "\t  Actual: %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] );
532                     log_error( "\t        : %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] );
533                     return -1;
534                 }
535                 expected += 4;
536                 actual += 4;
537             }
538         }
539     }
540   }
541 
542     return 0;
543 }
544 
CheckGLObjectInfo(cl_mem mem,cl_gl_object_type expected_cl_gl_type,GLuint expected_gl_name,GLenum expected_cl_gl_texture_target,GLint expected_cl_gl_mipmap_level)545 int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name,
546                   GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level)
547 {
548   cl_gl_object_type object_type;
549   GLuint object_name;
550   GLenum texture_target;
551   GLint mipmap_level;
552     int error;
553 
554   error = (*clGetGLObjectInfo_ptr)(mem, &object_type, &object_name);
555   test_error( error, "clGetGLObjectInfo failed");
556   if (object_type != expected_cl_gl_type) {
557     log_error("clGetGLObjectInfo did not return expected object type: expected %d, got %d.\n", expected_cl_gl_type, object_type);
558     return -1;
559   }
560   if (object_name != expected_gl_name) {
561     log_error("clGetGLObjectInfo did not return expected object name: expected %d, got %d.\n", expected_gl_name, object_name);
562     return -1;
563   }
564 
565   // If we're dealing with a buffer or render buffer, we are done.
566 
567   if (object_type == CL_GL_OBJECT_BUFFER || object_type == CL_GL_OBJECT_RENDERBUFFER) {
568     return 0;
569   }
570 
571   // Otherwise, it's a texture-based object and requires a bit more checking.
572 
573   error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_TEXTURE_TARGET, sizeof(texture_target), &texture_target, NULL);
574   test_error( error, "clGetGLTextureInfo for CL_GL_TEXTURE_TARGET failed");
575 
576   if (texture_target != expected_cl_gl_texture_target) {
577     log_error("clGetGLTextureInfo did not return expected texture target: expected %d, got %d.\n", expected_cl_gl_texture_target, texture_target);
578     return -1;
579   }
580 
581   error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_MIPMAP_LEVEL, sizeof(mipmap_level), &mipmap_level, NULL);
582   test_error( error, "clGetGLTextureInfo for CL_GL_MIPMAP_LEVEL failed");
583 
584   if (mipmap_level != expected_cl_gl_mipmap_level) {
585     log_error("clGetGLTextureInfo did not return expected mipmap level: expected %d, got %d.\n", expected_cl_gl_mipmap_level, mipmap_level);
586     return -1;
587   }
588 
589   return 0;
590 }
591 
CheckGLIntegerExtensionSupport()592 bool CheckGLIntegerExtensionSupport()
593 {
594     // Get the OpenGL version and supported extensions
595     const GLubyte *glVersion = glGetString(GL_VERSION);
596     const GLubyte *glExtensionList = glGetString(GL_EXTENSIONS);
597 
598     // Check if the OpenGL vrsion is 3.0 or grater or GL_EXT_texture_integer is supported
599     return (((glVersion[0] - '0') >= 3) || (strstr((const char*)glExtensionList, "GL_EXT_texture_integer")));
600 }
601 
is_rgb_101010_supported(cl_context context,GLenum gl_target)602 int is_rgb_101010_supported( cl_context context, GLenum gl_target )
603 {
604     cl_image_format formatList[ 128 ];
605     cl_uint formatCount = 0;
606     unsigned int i;
607     int error;
608 
609     cl_mem_object_type image_type;
610 
611     switch (get_base_gl_target(gl_target)) {
612         case GL_TEXTURE_1D:
613             image_type = CL_MEM_OBJECT_IMAGE1D;
614         case GL_TEXTURE_BUFFER:
615             image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER;
616             break;
617         case GL_TEXTURE_RECTANGLE_EXT:
618         case GL_TEXTURE_2D:
619         case GL_COLOR_ATTACHMENT0:
620         case GL_RENDERBUFFER:
621         case GL_TEXTURE_CUBE_MAP:
622         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
623         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
624         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
625         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
626         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
627         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
628             image_type = CL_MEM_OBJECT_IMAGE2D;
629             break;
630         case GL_TEXTURE_3D:
631             image_type = CL_MEM_OBJECT_IMAGE3D;
632         case GL_TEXTURE_1D_ARRAY:
633             image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
634         case GL_TEXTURE_2D_ARRAY:
635             image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
636             break;
637         default:
638             image_type = CL_MEM_OBJECT_IMAGE2D;
639     }
640 
641     if ((error = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE,
642                                                                                     image_type, 128, formatList,
643                                                                                     &formatCount ))) {
644         return error;
645     }
646 
647     // Check if the RGB 101010 format is supported
648     for( i = 0; i < formatCount; i++ )
649     {
650         if( formatList[ i ].image_channel_data_type == CL_UNORM_INT_101010 )
651         {
652             return 1;
653         }
654     }
655 
656     return 0;
657 }
658