20 #define glGenVertexArrays glGenVertexArraysAPPLE
21 #define glBindVertexArray glBindVertexArrayAPPLE
22 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
25 #import <IOSurface/IOSurface.h>
29 "title" :
"VuoGraphicsLayer",
35 "QuartzCore.framework",
45 GLint length = (GLint)strlen(source);
46 GLuint shader = glCreateShader(type);
47 glShaderSource(shader, 1, (
const GLchar**)&source, &length);
48 glCompileShader(shader);
50 int infologLength = 0;
51 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
52 if (infologLength > 0)
54 char *infoLog = (
char *)malloc(infologLength);
56 glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog);
88 @property double lastProfileLoggedTime;
107 void *callerData = l.userData;
111 NSRect frame = l.frame;
112 frame.origin.x *= gw.backingScaleFactor;
113 frame.origin.y *= gw.backingScaleFactor;
114 frame.size.width *= gw.backingScaleFactor;
115 frame.size.height *= gw.backingScaleFactor;
121 int width = frame.size.width;
122 int height = frame.size.height;
125 NSSize desiredAspectSize = gw.contentAspectRatio;
126 bool isAspectLocked = !NSEqualSizes(desiredAspectSize, NSMakeSize(0,0));
129 float desiredAspect = desiredAspectSize.width / desiredAspectSize.height;
130 float screenAspect = frame.size.width / frame.size.height;
132 if (desiredAspect > screenAspect)
135 width = frame.size.width;
136 height = frame.size.width / desiredAspect;
138 y = frame.size.height/2 - height/2;
143 width = frame.size.height * desiredAspect;
144 height = frame.size.height;
145 x = frame.size.width/2 - width/2;
154 NSRect contentRectWhenWindowed = [gv convertRectToBacking:gw.contentRectWhenWindowed];
155 width = contentRectWhenWindowed.size.width;
156 height = contentRectWhenWindowed.size.height;
157 x = frame.size.width/2 - width/2;
158 y = frame.size.height/2 - height/2;
163 NSRect newViewport = NSMakeRect(x, y, width, height);
164 if (!NSEqualRects(gv.
viewport, newViewport) || l.firstFrame || backingScaleFactorChanged)
172 if (backingScaleFactorChanged)
175 l.resizeCallback(callerData, width, height);
187 [gw.recorder saveImage:vis];
202 backingScaleFactor:(
float)backingScaleFactor
205 userData:(
void *)userData
207 if (
self = [super init])
210 _initCallback = initCallback;
211 _updateBackingCallback = updateBackingCallback;
212 _resizeCallback = resizeCallback;
213 _drawCallback = drawCallback;
214 _userData = userData;
216 if ([
self respondsToSelector:
@selector(setColorspace:)])
217 [
self performSelector:@selector(setColorspace:) withObject:(id)CGColorSpaceCreateWithName(kCGColorSpaceSRGB)];
219 self.needsDisplayOnBoundsChange = YES;
228 _initCallback(_userData, backingScaleFactor);
241 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
251 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
253 CGLContextObj context = [
super copyCGLContextForPixelFormat:pixelFormat];
257 CGLSetCurrentContext(context);
263 const GLfloat trianglePositions[] = {
268 GLuint trianglePositionBuffer;
269 glGenBuffers(1, &trianglePositionBuffer);
270 glBindBuffer(GL_ARRAY_BUFFER, trianglePositionBuffer);
271 glBufferData(GL_ARRAY_BUFFER,
sizeof(trianglePositions), trianglePositions, GL_STATIC_DRAW);
275 attribute vec2 position;
278 gl_Position = vec4(position.x, position.y, 0., 1.);
282 uniform sampler2DRect t;
283 uniform vec2 textureOrigin;
286 gl_FragColor = texture2DRect(t, gl_FragCoord.xy - textureOrigin);
289 GLuint vertexShader =
CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
290 GLuint fragmentShader =
CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
291 GLuint program = glCreateProgram();
292 glAttachShader(program, vertexShader);
293 glAttachShader(program, fragmentShader);
294 glLinkProgram(program);
296 GLuint positionAttribute = glGetAttribLocation(program,
"position");
298 _receiveTextureUniform = glGetUniformLocation(program,
"t");
299 _receiveTextureOffsetUniform = glGetUniformLocation(program,
"textureOrigin");
300 glUseProgram(program);
301 glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE,
sizeof(GLfloat)*2, (
void*)0);
302 glEnableVertexAttribArray(positionAttribute);
304 CGLSetCurrentContext(NULL);
317 float backingScaleFactor = _window.backingScaleFactor;
318 if (backingScaleFactor != _window.backingScaleFactorCached)
320 VDebugLog(
"backingScaleFactor changed from %g to %g", _window.backingScaleFactorCached, backingScaleFactor);
321 float oldBackingScaleFactor = _window.backingScaleFactorCached;
322 NSSize contentSize = [_window contentRectForFrameRect:_window.frame].size;
324 _window.backingScaleFactorCached = backingScaleFactor;
325 self.contentsScale = backingScaleFactor;
327 _updateBackingCallback(_userData, backingScaleFactor);
329 if (_window.maintainsPixelSizeWhenBackingChanges)
331 float backingScaleRatio = oldBackingScaleFactor / backingScaleFactor;
332 [_window scheduleResize:NSMakeSize(contentSize.width * backingScaleRatio,
333 contentSize.height * backingScaleRatio)];
338 NSSize newContentSize = [_window contentRectForFrameRect:_window.frame].size;
339 _resizeCallback(_userData, newContentSize.width * _window.backingScaleFactorCached,
340 newContentSize.height * _window.backingScaleFactorCached);
364 - (void)setBounds:(CGRect)bounds
366 [
super setBounds:bounds];
377 if (now - _renderScheduled > 0.4)
379 _renderScheduled = now;
380 dispatch_async(dispatch_get_main_queue(), ^{
381 [
self setNeedsDisplay];
392 - (void)drawInCGLContext:(CGLContextObj)context pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
394 _renderScheduled = -INFINITY;
399 dispatch_sync(_drawQueue, ^{
404 NSRect frameInPoints =
self.frame;
405 double s = _window.backingScaleFactor;
406 NSRect frameInPixels = NSMakeRect(frameInPoints.origin.x * s, frameInPoints.origin.y * s, frameInPoints.size.width * s, frameInPoints.size.height * s);
414 GLuint receiveTexture;
415 GLuint receiveTextureBytes;
417 glGenTextures(1, &receiveTexture);
418 glActiveTexture(GL_TEXTURE0);
419 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
420 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
421 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
422 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
424 glUniform1i(_receiveTextureUniform, 0);
426 CGLError err = CGLTexImageIOSurface2D(context, GL_TEXTURE_RECTANGLE_EXT, GL_RGB, ioSurfaceWidth, ioSurfaceHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
VuoIoSurfacePool_getIOSurfaceRef(_ioSurface), 0);
427 if(err != kCGLNoError)
429 VUserLog(
"Error in CGLTexImageIOSurface2D(context, GL_TEXTURE_RECTANGLE_EXT, GL_RGB, %zu, %zu, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, %d, 0) 2: %s", ioSurfaceWidth, ioSurfaceHeight,
VuoIoSurfacePool_getId(_ioSurface), CGLErrorString(err));
433 receiveTextureBytes = ioSurfaceWidth * ioSurfaceHeight * 4;
436 glUniform2f(_receiveTextureOffsetUniform, viewport.origin.x, viewport.origin.y);
437 glViewport(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
443 if (!NSEqualRects(viewport, frameInPixels))
446 glClearColor(0,0,0,1);
447 glClear(GL_COLOR_BUFFER_BIT);
450 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
451 glDrawArrays(GL_TRIANGLES, 0, 3);
453 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
454 glDeleteTextures(1, &receiveTexture);
463 ++_framesRenderedSinceProfileLogged;
465 const double profileSeconds = 10;
466 if (t > _lastProfileLoggedTime + profileSeconds)
468 VDebugLog(
"%4.1f fps", _framesRenderedSinceProfileLogged / profileSeconds);
469 _lastProfileLoggedTime = t;
470 _framesRenderedSinceProfileLogged = 0;
485 #pragma clang diagnostic push
486 #pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
501 #pragma clang diagnostic pop