18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
23 #define glGenVertexArrays glGenVertexArraysAPPLE
24 #define glBindVertexArray glBindVertexArrayAPPLE
25 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
28 #import <IOSurface/IOSurface.h>
32 "title" :
"VuoGraphicsLayer",
38 "QuartzCore.framework",
48 GLint length = (GLint)strlen(source);
49 GLuint shader = glCreateShader(type);
50 glShaderSource(shader, 1, (
const GLchar**)&source, &length);
51 glCompileShader(shader);
53 int infologLength = 0;
54 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
55 if (infologLength > 0)
57 char *infoLog = (
char *)malloc(infologLength);
59 glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog);
91 @property double lastProfileLoggedTime;
110 void *callerData = l.userData;
114 NSRect frame = l.frame;
115 frame.origin.x *= gw.backingScaleFactor;
116 frame.origin.y *= gw.backingScaleFactor;
117 frame.size.width *= gw.backingScaleFactor;
118 frame.size.height *= gw.backingScaleFactor;
124 int width = frame.size.width;
125 int height = frame.size.height;
128 NSSize desiredAspectSize = gw.contentAspectRatio;
129 bool isAspectLocked = !NSEqualSizes(desiredAspectSize, NSMakeSize(0,0));
132 float desiredAspect = desiredAspectSize.width / desiredAspectSize.height;
133 float screenAspect = frame.size.width / frame.size.height;
135 if (desiredAspect > screenAspect)
138 width = frame.size.width;
139 height = frame.size.width / desiredAspect;
141 y = frame.size.height/2 - height/2;
146 width = frame.size.height * desiredAspect;
147 height = frame.size.height;
148 x = frame.size.width/2 - width/2;
157 NSRect contentRectWhenWindowed = [gv convertRectToBacking:gw.contentRectWhenWindowed];
158 width = contentRectWhenWindowed.size.width;
159 height = contentRectWhenWindowed.size.height;
160 x = frame.size.width/2 - width/2;
161 y = frame.size.height/2 - height/2;
166 NSRect newViewport = NSMakeRect(x, y, width, height);
167 if (!NSEqualRects(gv.
viewport, newViewport) || l.firstFrame || backingScaleFactorChanged)
175 if (backingScaleFactorChanged)
178 l.resizeCallback(callerData, width, height);
190 [gw.recorder saveImage:vis];
205 backingScaleFactor:(
float)backingScaleFactor
208 userData:(
void *)userData
210 if (
self = [super init])
213 _initCallback = initCallback;
214 _updateBackingCallback = updateBackingCallback;
215 _resizeCallback = resizeCallback;
216 _drawCallback = drawCallback;
217 _userData = userData;
219 if ([
self respondsToSelector:
@selector(setColorspace:)])
220 [
self performSelector:@selector(setColorspace:) withObject:(id)CGColorSpaceCreateWithName(kCGColorSpaceSRGB)];
222 self.needsDisplayOnBoundsChange = YES;
231 _initCallback(_userData, backingScaleFactor);
244 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
254 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
256 CGLContextObj context = [
super copyCGLContextForPixelFormat:pixelFormat];
260 CGLSetCurrentContext(context);
266 const GLfloat trianglePositions[] = {
271 GLuint trianglePositionBuffer;
272 glGenBuffers(1, &trianglePositionBuffer);
273 glBindBuffer(GL_ARRAY_BUFFER, trianglePositionBuffer);
274 glBufferData(GL_ARRAY_BUFFER,
sizeof(trianglePositions), trianglePositions, GL_STATIC_DRAW);
278 attribute vec2 position;
281 gl_Position = vec4(position.x, position.y, 0., 1.);
285 uniform sampler2DRect t;
286 uniform vec2 textureOrigin;
289 gl_FragColor = texture2DRect(t, gl_FragCoord.xy - textureOrigin);
292 GLuint vertexShader =
CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
293 GLuint fragmentShader =
CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
294 GLuint program = glCreateProgram();
295 glAttachShader(program, vertexShader);
296 glAttachShader(program, fragmentShader);
297 glLinkProgram(program);
299 GLuint positionAttribute = glGetAttribLocation(program,
"position");
301 _receiveTextureUniform = glGetUniformLocation(program,
"t");
302 _receiveTextureOffsetUniform = glGetUniformLocation(program,
"textureOrigin");
303 glUseProgram(program);
304 glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE,
sizeof(GLfloat)*2, (
void*)0);
305 glEnableVertexAttribArray(positionAttribute);
307 CGLSetCurrentContext(NULL);
320 float backingScaleFactor = _window.backingScaleFactor;
321 if (backingScaleFactor != _window.backingScaleFactorCached)
323 VDebugLog(
"backingScaleFactor changed from %g to %g", _window.backingScaleFactorCached, backingScaleFactor);
324 float oldBackingScaleFactor = _window.backingScaleFactorCached;
325 NSSize contentSize = [_window contentRectForFrameRect:_window.frame].size;
327 _window.backingScaleFactorCached = backingScaleFactor;
328 self.contentsScale = backingScaleFactor;
330 _updateBackingCallback(_userData, backingScaleFactor);
332 if (_window.maintainsPixelSizeWhenBackingChanges)
334 float backingScaleRatio = oldBackingScaleFactor / backingScaleFactor;
335 [_window scheduleResize:NSMakeSize(contentSize.width * backingScaleRatio,
336 contentSize.height * backingScaleRatio)];
341 NSSize newContentSize = [_window contentRectForFrameRect:_window.frame].size;
342 _resizeCallback(_userData, newContentSize.width * _window.backingScaleFactorCached,
343 newContentSize.height * _window.backingScaleFactorCached);
367 - (void)setBounds:(CGRect)bounds
369 [
super setBounds:bounds];
380 if (now - _renderScheduled > 0.4)
382 _renderScheduled = now;
383 dispatch_async(dispatch_get_main_queue(), ^{
384 [
self setNeedsDisplay];
395 - (void)drawInCGLContext:(CGLContextObj)context pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
397 _renderScheduled = -INFINITY;
402 dispatch_sync(_drawQueue, ^{
407 NSRect frameInPoints =
self.frame;
408 double s = _window.backingScaleFactor;
409 NSRect frameInPixels = NSMakeRect(frameInPoints.origin.x * s, frameInPoints.origin.y * s, frameInPoints.size.width * s, frameInPoints.size.height * s);
417 GLuint receiveTexture;
418 GLuint receiveTextureBytes;
420 glGenTextures(1, &receiveTexture);
421 glActiveTexture(GL_TEXTURE0);
422 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
423 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
424 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
425 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
427 glUniform1i(_receiveTextureUniform, 0);
429 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);
430 if(err != kCGLNoError)
432 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));
436 receiveTextureBytes = ioSurfaceWidth * ioSurfaceHeight * 4;
439 glUniform2f(_receiveTextureOffsetUniform, viewport.origin.x, viewport.origin.y);
440 glViewport(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
446 if (!NSEqualRects(viewport, frameInPixels))
449 glClearColor(0,0,0,1);
450 glClear(GL_COLOR_BUFFER_BIT);
453 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
454 glDrawArrays(GL_TRIANGLES, 0, 3);
456 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
457 glDeleteTextures(1, &receiveTexture);
466 ++_framesRenderedSinceProfileLogged;
468 const double profileSeconds = 10;
469 if (t > _lastProfileLoggedTime + profileSeconds)
471 VDebugLog(
"%4.1f fps", _framesRenderedSinceProfileLogged / profileSeconds);
472 _lastProfileLoggedTime = t;
473 _framesRenderedSinceProfileLogged = 0;
488 #pragma clang diagnostic push
489 #pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
504 #pragma clang diagnostic pop
507 #pragma clang diagnostic pop