31 #include <dispatch/dispatch.h>
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <IOSurface/IOSurface.h>
36 #include <OpenGL/CGLIOSurface.h>
37 #include <OpenGL/CGLMacro.h>
38 #include <ApplicationServices/ApplicationServices.h>
41 static map<VuoGlPoolType, map<unsigned long, vector<GLuint> > > VuoGlPool __attribute__((init_priority(101)));
60 if (VuoGlPool[type][size].size())
62 name = VuoGlPool[type][size].back();
63 VuoGlPool[type][size].pop_back();
68 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
70 if (type == VuoGlPool_ArrayBuffer || type == VuoGlPool_ElementArrayBuffer)
72 glGenBuffers(1, &name);
73 GLenum bufferType = type == VuoGlPool_ArrayBuffer ? GL_ARRAY_BUFFER : GL_ELEMENT_ARRAY_BUFFER;
74 glBindBuffer(bufferType, name);
75 glBufferData(bufferType, size, NULL, GL_STREAM_DRAW);
76 glBindBuffer(bufferType, 0);
81 VUserLog(
"Unknown pool type %d.", type);
101 if (type == VuoGlPool_ArrayBuffer || type == VuoGlPool_ElementArrayBuffer)
102 VuoGlPool[type][size].push_back(name);
104 VUserLog(
"Unknown pool type %d.", type);
112 static void __attribute__((constructor)) VuoGlPool_referenceCountsInit(
void)
120 void VuoGlPool_retainF(GLuint glBufferName,
const char *file,
unsigned int linenumber,
const char *func)
122 if (glBufferName == 0)
127 VuoGlPoolReferenceCounts::iterator it = VuoGlPool_referenceCounts.find(glBufferName);
128 if (it == VuoGlPool_referenceCounts.end())
129 VuoGlPool_referenceCounts[glBufferName] = 1;
131 ++VuoGlPool_referenceCounts[glBufferName];
142 if (glBufferName == 0)
147 VuoGlPoolReferenceCounts::iterator it = VuoGlPool_referenceCounts.find(glBufferName);
148 if (it == VuoGlPool_referenceCounts.end())
149 VuoLog(file, linenumber, func,
"Error: VuoGlPool_release() was called with OpenGL Buffer Object %d, which was never retained.", glBufferName);
152 if (--VuoGlPool_referenceCounts[glBufferName] == 0)
180 internalFormat(internalFormat),
221 if (format == GL_YCBCR_422_APPLE)
222 return GL_UNSIGNED_SHORT_8_8_APPLE;
223 else if (format == GL_RGB
224 || format == GL_LUMINANCE
225 || format == GL_LUMINANCE_ALPHA
226 || format == GL_BGR_EXT)
227 return GL_UNSIGNED_BYTE;
228 else if (format == GL_RGBA
229 || format == GL_RGBA8
230 || format == GL_BGRA)
231 return GL_UNSIGNED_INT_8_8_8_8_REV;
232 else if (format == GL_DEPTH_COMPONENT)
235 return GL_UNSIGNED_BYTE;
238 VUserLog(
"Unknown format %s", formatString);
249 if (format == GL_LUMINANCE
250 || format == GL_LUMINANCE8
251 || format == GL_LUMINANCE16F_ARB
252 || format == GL_LUMINANCE32F_ARB
253 || format == GL_DEPTH_COMPONENT)
255 else if (format == GL_YCBCR_422_APPLE
256 || format == GL_LUMINANCE_ALPHA
257 || format == GL_LUMINANCE_ALPHA16F_ARB
258 || format == GL_LUMINANCE_ALPHA32F_ARB)
260 else if (format == GL_RGB
261 || format == GL_RGB16F_ARB
262 || format == GL_RGB32F_ARB
263 || format == GL_BGR_EXT)
265 else if (format == GL_RGBA
266 || format == GL_RGBA8
267 || format == GL_RGBA16F_ARB
268 || format == GL_RGBA32F_ARB
269 || format == GL_BGRA)
273 VUserLog(
"Unknown format %s", formatString);
284 if (internalformat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
286 if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT
287 || internalformat == GL_COMPRESSED_RED_RGTC1)
291 if (internalformat == GL_RGB
292 || internalformat == GL_RGBA
293 || internalformat == GL_RGBA8
294 || internalformat == GL_LUMINANCE8
295 || internalformat == GL_LUMINANCE8_ALPHA8)
297 else if (internalformat == GL_RGB16F_ARB
298 || internalformat == GL_RGBA16F_ARB
299 || internalformat == GL_DEPTH_COMPONENT
300 || internalformat == GL_LUMINANCE16F_ARB
301 || internalformat == GL_LUMINANCE_ALPHA16F_ARB)
303 else if (internalformat == GL_RGB32F_ARB
304 || internalformat == GL_RGBA32F_ARB
305 || internalformat == GL_LUMINANCE32F_ARB
306 || internalformat == GL_LUMINANCE_ALPHA32F_ARB)
320 if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT
321 || internalformat == GL_COMPRESSED_RED_RGTC1)
323 if (internalformat == GL_LUMINANCE8
324 || internalformat == GL_LUMINANCE
325 || internalformat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
327 if (internalformat == GL_LUMINANCE8_ALPHA8
328 || internalformat == GL_LUMINANCE16F_ARB
329 || internalformat == GL_DEPTH_COMPONENT)
331 if (internalformat == GL_RGB
332 || internalformat == GL_BGR)
334 if (internalformat == GL_RGBA
335 || internalformat == GL_RGBA8
336 || internalformat == GL_BGRA
337 || internalformat == GL_LUMINANCE_ALPHA16F_ARB
338 || internalformat == GL_LUMINANCE32F_ARB)
340 if (internalformat == GL_RGB16F_ARB)
342 if (internalformat == GL_RGBA16F_ARB
343 || internalformat == GL_LUMINANCE_ALPHA32F_ARB)
345 if (internalformat == GL_RGB32F_ARB)
347 if (internalformat == GL_RGBA32F_ARB)
351 VUserLog(
"Unknown internalformat %s", formatString);
363 if (format == GL_BGRA
364 || format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
365 || format == GL_LUMINANCE8_ALPHA8
366 || format == GL_LUMINANCE_ALPHA
367 || format == GL_LUMINANCE_ALPHA16F_ARB
368 || format == GL_LUMINANCE_ALPHA32F_ARB
370 || format == GL_RGBA16F_ARB
371 || format == GL_RGBA32F_ARB
372 || format == GL_RGBA8)
383 #pragma clang diagnostic push
384 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
385 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
386 static unsigned long maximumTextureBytes = 0;
387 static dispatch_once_t maximumTextureBytesQuery = 0;
388 dispatch_once(&maximumTextureBytesQuery, ^{
389 GLint contextRendererID;
390 CGLGetParameter(cgl_ctx, kCGLCPCurrentRendererID, &contextRendererID);
396 CGLRendererInfoObj ri;
397 GLint rendererCount = 0;
398 CGLQueryRendererInfo(-1, &ri, &rendererCount);
399 for (
int i = 0; i < rendererCount; ++i)
402 CGLDescribeRenderer(ri, i, kCGLRPRendererID, &rendererID);
403 if (rendererID == contextRendererID)
405 GLint textureMegabytes = 0;
406 if (CGLDescribeRenderer(ri, i, kCGLRPTextureMemoryMegabytes, &textureMegabytes) == kCGLNoError)
412 if ((rendererID & kCGLRendererIDMatchingMask) == kCGLRendererIntelHD4000ID)
416 maximumTextureBytes = (textureMegabytes - 85) * 1048576UL * fudge;
417 VDebugLog(
"%ld MB", maximumTextureBytes / 1024 / 1024);
422 CGLDestroyRendererInfo(ri);
424 return maximumTextureBytes;
425 #pragma clang diagnostic pop
433 static GLint maximumTextureDimension = 0;
434 static dispatch_once_t maximumTextureDimensionQuery = 0;
435 dispatch_once(&maximumTextureDimensionQuery, ^{
436 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
437 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maximumTextureDimension);
439 return maximumTextureDimension;
442 #pragma clang diagnostic push
443 #pragma clang diagnostic ignored "-Wunused-function"
449 return allocation == VuoGlTexturePool_NoAllocation ?
"NoAlloc" :
450 (allocation == VuoGlTexturePool_Allocate ?
"Alloc" :
451 allocation == VuoGlTexturePool_AllocateIOSurface ?
"AllocIOSurf" :
"?");
453 #pragma clang diagnostic pop
481 if (allocation == VuoGlTexturePool_AllocateIOSurface
482 && target != GL_TEXTURE_RECTANGLE_ARB)
484 VUserLog(
"Error: To use VuoGlTexturePool_AllocateIOSurface, target must be GL_TEXTURE_RECTANGLE_ARB.");
489 unsigned long requiredBytes = width * height * bytesPerPixel;
494 if (allocation != VuoGlTexturePool_AllocateIOSurface)
500 name = it->second.first.front();
501 it->second.first.pop();
509 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
515 if (maximumTextureBytes > 0)
517 if (requiredBytes > maximumTextureBytes)
520 VUserLog(
"Not enough graphics memory for a %dx%d (%d bytes/pixel) texture. Requires %lu MB, have %lu MB.", width, height, bytesPerPixel, requiredBytes/1024/1024, maximumTextureBytes/1024/1024);
527 if (width > maxDimension || height > maxDimension)
530 VUserLog(
"This GPU doesn't support textures of size %dx%d (GPU's limit is %dx%d).", width, height, maxDimension, maxDimension);
534 glGenTextures(1, &name);
536 glBindTexture(target, name);
537 if (allocation == VuoGlTexturePool_Allocate)
539 glTexImage2D(target, 0, internalformat, width, height, 0, format,
VuoGlTexture_getType(format), NULL);
542 else if (allocation == VuoGlTexturePool_AllocateIOSurface)
544 #pragma clang diagnostic push
545 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
546 CGLError err = CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_ARB, internalformat, width, height, format,
VuoGlTexture_getType(format), (IOSurfaceRef)ioSurfaceRef, 0);
547 if (err != kCGLNoError)
552 VUserLog(
"Error in CGLTexImageIOSurface2D(context, GL_TEXTURE_RECTANGLE_ARB, %s, %hu, %hu, %s, %s, iosurface, 0): %s",
553 internalFormatString, width, height, formatString, typeString, CGLErrorString(err));
554 free(internalFormatString);
560 #pragma clang diagnostic pop
565 glBindTexture(target, name);
568 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
569 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
571 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
572 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
574 glBindTexture(target, 0);
591 if (internalformat == 0)
593 VUserLog(
"Error: Can't recycle texture %d since we don't know its internalformat. Deleting.", name);
595 glDeleteTextures(1, &name);
601 if (allocation == VuoGlTexturePool_AllocateIOSurface)
604 glDeleteTextures(1, &name);
614 auto it = &(*VuoGlTexturePool)[descriptor];
615 it->first.push(name);
632 unsigned int referenceCount;
634 void *freeCallbackContext;
642 static void __attribute__((constructor(101))) VuoGlTexture_init(
void)
656 if (glTextureName == 0)
663 (*VuoGlTexture_referenceCounts)[glTextureName] = (
VuoGlTexture){1, freeCallback, freeCallbackContext};
665 ++(*it).second.referenceCount;
679 if (glTextureName == 0)
686 VUserLog(
"Error: VuoGlTexture_release() was called with OpenGL Texture Object %d, which was never retained.", glTextureName);
689 VuoGlTexture t = (*VuoGlTexture_referenceCounts)[glTextureName];
690 if (--t.referenceCount == 0)
695 struct _VuoImage i = (
struct _VuoImage){glTextureName, internalformat, glTextureTarget, width, height, 1, t.freeCallbackContext, NULL, NULL, NULL};
724 if (glTextureName == 0)
731 VUserLog(
"Error: VuoGlTexture_disown() was called with OpenGL Texture Object %d, which was never retained.", glTextureName);
734 VuoGlTexture t = (*VuoGlTexture_referenceCounts)[glTextureName];
735 if (t.referenceCount != 1)
736 VUserLog(
"Error: VuoGlTexture_disown() was called with OpenGL Texture Object %d, which has a reference count of %d (but it should be 1).", glTextureName, t.referenceCount);
751 IOSurfaceRef ioSurface;
753 unsigned short pixelsWide;
754 unsigned short pixelsHigh;
813 unsigned long totalTextureCount = 0;
814 static unsigned long totalTextureCountMax = 0;
816 vector<GLuint> texturesToDelete;
817 vector<VuoIoSurfacePoolEntryType> iosurfaceTexturesToDisuse;
824 unsigned long textureCount = poolItem->second.first.size();
825 double timeSinceLastUsed = now - poolItem->second.second;
832 while (!poolItem->second.first.empty())
834 GLuint textureName = poolItem->second.first.front();
835 poolItem->second.first.pop();
836 texturesToDelete.push_back(textureName);
845 totalTextureCount += textureCount;
852 if (totalTextureCount > totalTextureCountMax)
853 totalTextureCountMax = totalTextureCount;
856 unsigned long totalIOSurfaceCount = 0;
857 static unsigned long totalIOSurfaceCountMax = 0;
864 for (deque<VuoIoSurfacePoolEntryType>::iterator quarantinedIoSurfaceEntry = quarantinedQueue->second.begin(); quarantinedIoSurfaceEntry != quarantinedQueue->second.end();)
872 (*VuoIoSurfacePool)[quarantinedQueue->first].push_back(e);
873 quarantinedIoSurfaceEntry = quarantinedQueue->second.erase(quarantinedIoSurfaceEntry);
879 ++totalIOSurfaceCount;
880 ++quarantinedIoSurfaceEntry;
889 for (deque<VuoIoSurfacePoolEntryType>::iterator poolIoSurfaceEntry = poolQueue->second.begin(); poolIoSurfaceEntry != poolQueue->second.end();)
896 CFRelease(e.ioSurface);
897 iosurfaceTexturesToDisuse.push_back(e);
898 poolIoSurfaceEntry = poolQueue->second.erase(poolIoSurfaceEntry);
902 ++totalIOSurfaceCount;
903 ++poolIoSurfaceEntry;
910 if (totalIOSurfaceCount > totalIOSurfaceCountMax)
911 totalIOSurfaceCountMax = totalIOSurfaceCount;
915 if (texturesToDelete.size())
917 for (vector<GLuint>::const_iterator i = texturesToDelete.begin(); i != texturesToDelete.end(); ++i)
920 glDeleteTextures(1, &t);
924 for (
auto e : iosurfaceTexturesToDisuse)
925 VuoGlTexturePool_disuse(VuoGlTexturePool_AllocateIOSurface, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, e.pixelsWide, e.pixelsHigh, e.texture);
930 static unsigned long cleanupCount = 0;
934 || totalTextureCount > 0 || totalTextureCountMax > 0
935 || totalIOSurfaceCount > 0 || totalIOSurfaceCountMax > 0))
937 __block
unsigned long maximumTextureBytes;
942 if (maximumTextureBytes > 0)
943 VUserLog(
"VRAM used: %5lu MB (%5lu MB max, %3lu%%). Textures in pool: %3lu (%3lu max). IOSurfaces in pool: %3lu (%3lu max).",
947 totalTextureCount, totalTextureCountMax,
948 totalIOSurfaceCount, totalIOSurfaceCountMax);
950 VUserLog(
"VRAM used: %5lu MB (%5lu MB max). Textures in pool: %3lu (%3lu max). IOSurfaces in pool: %3lu (%3lu max).",
953 totalTextureCount, totalTextureCountMax,
954 totalIOSurfaceCount, totalIOSurfaceCountMax);
957 static void __attribute__((constructor)) VuoGlPool_init(
void)
969 VuoGlPool_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
980 static void __attribute__((destructor)) VuoGlPool_fini(
void)
1009 *outputTexture = e.texture;
1010 (*VuoIoSurfacePool)[dimensions].pop_front();
1018 CFMutableDictionaryRef properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
1020 #pragma clang diagnostic push
1021 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1024 CFDictionaryAddValue(properties, kIOSurfaceIsGlobal, kCFBooleanTrue);
1025 #pragma clang diagnostic pop
1027 long long pixelsWideLL = pixelsWide;
1028 CFNumberRef pixelsWideCF = CFNumberCreate(NULL, kCFNumberLongLongType, &pixelsWideLL);
1029 CFDictionaryAddValue(properties, kIOSurfaceWidth, pixelsWideCF);
1031 long long pixelsHighLL = pixelsHigh;
1032 CFNumberRef pixelsHighCF = CFNumberCreate(NULL, kCFNumberLongLongType, &pixelsHighLL);
1033 CFDictionaryAddValue(properties, kIOSurfaceHeight, pixelsHighCF);
1035 long long bytesPerElement = 4;
1036 CFNumberRef bytesPerElementCF = CFNumberCreate(NULL, kCFNumberLongLongType, &bytesPerElement);
1037 CFDictionaryAddValue(properties, kIOSurfaceBytesPerElement, bytesPerElementCF);
1039 uint32_t pixelFormat =
'BGRA';
1040 CFNumberRef pixelFormatCF = CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormat);
1041 CFDictionaryAddValue(properties, kIOSurfacePixelFormat, pixelFormatCF);
1043 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1047 e->ioSurface = IOSurfaceCreate(properties);
1048 e->pixelsWide = pixelsWide;
1049 e->pixelsHigh = pixelsHigh;
1050 e->lastUsedTime = -1;
1051 CFRelease(pixelsWideCF);
1052 CFRelease(pixelsHighCF);
1053 CFRelease(bytesPerElementCF);
1054 CFRelease(properties);
1056 *outputTexture =
VuoGlTexturePool_use(cgl_ctx, VuoGlTexturePool_AllocateIOSurface, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, pixelsWide, pixelsHigh, GL_BGRA, e->ioSurface);
1057 e->texture = *outputTexture;
1071 return IOSurfaceGetID(e->ioSurface);
1080 return e->ioSurface;
1089 return e->pixelsWide;
1098 return e->pixelsHigh;
1132 (*VuoIoSurfaceQuarantine)[dimensions].push_back(*e);
1147 IOSurfaceRef ioSurface = (IOSurfaceRef)ios;
1160 int infologLength = 0;
1161 glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
1162 if (infologLength > 0)
1164 char *infoLog = (
char *)malloc(infologLength);
1165 int charsWritten = 0;
1166 glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
1170 istringstream iss(infoLog);
1172 while (getline(iss, ln))
1175 char *message = (
char *)malloc(ln.length() + 1);
1176 char *quotation = (
char *)malloc(ln.length() + 1);
1177 if (sscanf(ln.c_str(),
"ERROR: 0:%d: '' : %[^\n]", &lineNumber, message) == 2)
1178 outIssues->
addIssue(stage, lineNumber, message);
1179 else if (sscanf(ln.c_str(),
"ERROR: 0:%d: '%[^']' : syntax error: %[^\n]", &lineNumber, quotation, message) == 3)
1180 outIssues->
addIssue(stage, lineNumber, message +
string(
": '") + quotation +
"'");
1181 else if (sscanf(ln.c_str(),
"ERROR: 0:%d: %[^\n]", &lineNumber, message) == 2)
1182 outIssues->
addIssue(stage, lineNumber, message);
1183 else if (sscanf(ln.c_str(),
"WARNING: 0:%d: %[^\n]", &lineNumber, message) == 2)
1184 outIssues->
addIssue(stage, lineNumber, message);
1187 VUserLog(
"Warning: Couldn't parse GLSL log message: \"%s\"", ln.c_str());
1204 map<GLenum, map<long, GLuint> > VuoGlShaderPool __attribute__((init_priority(101)));
1210 __attribute__((constructor))
static void VuoGlShaderPool_init(
void)
1227 userModulesPath =
"";
1230 systemModulesPath =
"";
1232 set<string> includedFiles;
1236 const string includeKeyword =
"#include";
1238 size_t includeStart = source.find(includeKeyword);
1239 if (includeStart == string::npos)
1242 size_t offset = includeStart + includeKeyword.length();
1244 while (source[offset] ==
' ')
1247 if (source[offset] !=
'"'
1248 && source[offset] !=
'<')
1254 VUserLog(
"Error: Syntax error in #include statement. Expected syntax: #include \"filename.glsl\"");
1259 size_t filenameStart = offset;
1261 while (source[offset] !=
'"'
1262 && source[offset] !=
'>')
1265 size_t filenameEnd = offset;
1267 string filename = source.substr(filenameStart, filenameEnd - filenameStart);
1269 vector<string> pathsToTest;
1270 if (strcmp(cwd,
"/") != 0)
1271 pathsToTest.push_back(cwd +
string(
"/") + filename);
1272 if (!vuoFrameworkPath.empty())
1273 pathsToTest.push_back(vuoFrameworkPath +
"/Resources/shaders/" + filename);
1274 if (!vuoRunnerFrameworkPath.empty())
1275 pathsToTest.push_back(vuoRunnerFrameworkPath +
"/Resources/shaders/" + filename);
1276 if (!userModulesPath.empty())
1277 pathsToTest.push_back(userModulesPath +
"/" + filename);
1278 if (!systemModulesPath.empty())
1279 pathsToTest.push_back(systemModulesPath +
"/" + filename);
1281 for (vector<string>::iterator i = pathsToTest.begin(); i != pathsToTest.end(); ++i)
1287 source.erase(includeStart, offset - includeStart + 1);
1290 if (includedFiles.count(*i))
1292 source.insert(includeStart,
1294 "// ============================================================\n"
1295 "// Skipped including file \"" + *i +
"\" since it was already included.\n"
1296 "// ============================================================\n"
1301 includedFiles.insert(*i);
1303 source.insert(includeStart,
1305 "// ============================================================\n"
1306 "// Begin included file \"" + *i +
"\"\n"
1309 "// End included file \"" + *i +
"\"\n"
1310 "// ============================================================\n"
1323 VUserLog(
"Error: Couldn't find include file \"%s\".", filename.c_str());
1356 if (!outIssues && VuoGlShaderPool[type].find(hash) != VuoGlShaderPool[type].end())
1357 shader = VuoGlShaderPool[type][hash];
1360 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1362 string combinedSource = source;
1366 if (type == GL_VERTEX_SHADER)
1367 stage = VuoShaderFile::Vertex;
1368 else if (type == GL_GEOMETRY_SHADER_EXT)
1369 stage = VuoShaderFile::Geometry;
1371 stage = VuoShaderFile::Fragment;
1381 shader = glCreateShader(type);
1382 GLint length = combinedSource.length();
1383 const GLchar *combinedSourceCString = combinedSource.c_str();
1384 glShaderSource(shader, 1, (
const GLchar**)&combinedSourceCString, &length);
1385 glCompileShader(shader);
1388 GLint status = GL_FALSE;
1389 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
1390 if (status == GL_FALSE)
1392 glDeleteShader(shader);
1397 VuoGlShaderPool[type][hash] = shader;
1411 static void __attribute__((constructor)) VuoGlProgramPool_init(
void)
1439 VuoGlProgramDescriptorType e(vertexShaderName, std::make_pair(geometryShaderName, std::make_pair(fragmentShaderName, std::make_pair(assemblyMethod, expectedOutputPrimitiveCount))));
1443 program = it->second;
1446 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1448 GLuint programName = glCreateProgram();
1449 glAttachShader(programName, vertexShaderName);
1450 if (geometryShaderName)
1451 glAttachShader(programName, geometryShaderName);
1452 if (fragmentShaderName)
1453 glAttachShader(programName, fragmentShaderName);
1455 bool transformFeedback =
false;
1457 if (!fragmentShaderName)
1458 transformFeedback =
true;
1461 glBindAttribLocation(programName, 0,
"position");
1463 if (geometryShaderName)
1465 GLuint inputPrimitiveGlMode = GL_TRIANGLES;
1468 inputPrimitiveGlMode = GL_LINES;
1470 inputPrimitiveGlMode = GL_POINTS;
1471 glProgramParameteriEXT(programName, GL_GEOMETRY_INPUT_TYPE_EXT, inputPrimitiveGlMode);
1473 GLuint outputPrimitiveGlMode = GL_TRIANGLE_STRIP;
1474 if (transformFeedback)
1479 outputPrimitiveGlMode = GL_LINE_STRIP;
1481 outputPrimitiveGlMode = GL_POINTS;
1483 glProgramParameteriEXT(programName, GL_GEOMETRY_OUTPUT_TYPE_EXT, outputPrimitiveGlMode);
1485 unsigned int expectedVertexCount = expectedOutputPrimitiveCount;
1486 if (outputPrimitiveGlMode == GL_TRIANGLE_STRIP)
1487 expectedVertexCount *= 3;
1488 else if (outputPrimitiveGlMode == GL_LINE_STRIP)
1489 expectedVertexCount *= 2;
1490 glProgramParameteriEXT(programName, GL_GEOMETRY_VERTICES_OUT_EXT, expectedVertexCount);
1493 if (transformFeedback)
1495 const GLchar *varyings[] = {
"outPosition",
"outNormal",
"outTextureCoordinate",
"outVertexColor" };
1496 glTransformFeedbackVaryingsEXT(programName, 4, varyings, GL_SEPARATE_ATTRIBS_EXT);
1499 glLinkProgram(programName);
1502 int infologLength = 0;
1503 glGetProgramiv(programName, GL_INFO_LOG_LENGTH, &infologLength);
1504 if (infologLength > 0)
1506 char *infoLog = (
char *)malloc(infologLength);
1507 int charsWritten = 0;
1508 glGetProgramInfoLog(programName, infologLength, &charsWritten, infoLog);
1514 istringstream iss(infoLog);
1516 while (getline(iss, ln))
1525 VUserLog(
"Warning: Couldn't parse GLSL log message: \"%s\"", ln.c_str());
1531 VUserLog(
"%s: %s", description, infoLog);
1538 glGetProgramiv(programName, GL_LINK_STATUS, &linkStatus);
1539 if (linkStatus == GL_FALSE)
1541 glDeleteProgram(programName);
1546 program.programName = programName;
1549 glGetProgramiv(programName, GL_ACTIVE_UNIFORMS, &uniformCount);
1551 GLint maxNameLength;
1552 glGetProgramiv(programName, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
1553 char *name = (
char *)malloc(maxNameLength + 1);
1556 program.uniforms = (
void *)uniforms;
1558 for (GLuint i = 0; i < uniformCount; ++i)
1561 glGetActiveUniform(programName, i, maxNameLength+1, NULL, &size, NULL, name);
1564 size_t nameLen = strlen(name);
1566 (*uniforms)[hash] = glGetUniformLocation(programName, name);
1572 if (name[nameLen-2] ==
'0' && name[nameLen-1] ==
']')
1574 name[nameLen-2] = 0;
1575 for (
int i = 1; i < size; ++i)
1577 std::stringstream ss;
1578 ss << name << i <<
"]";
1579 string sss = ss.str();
1581 (*uniforms)[sHash] = glGetUniformLocation(programName, sss.c_str());
1601 long hash =
VuoGlPool_collate.hash(uniformIdentifier, uniformIdentifier+strlen(uniformIdentifier));
1603 VuoGlUniformMap::iterator i = uniforms->find(hash);
1604 if (i != uniforms->end())
1611 #define RETURN_STRING_IF_EQUAL(value) if (constant == value) return strdup(#value)
1621 return strdup(
"(GL_ZERO or GL_POINTS)");
1623 return strdup(
"(GL_ONE or GL_LINES)");