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);
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);
322 NSRect contentRect = [_window contentRectForFrameRect:_window.frame];
323 NSSize oldContentRectPixelSize = NSMakeSize(contentRect.size.width * _window.backingScaleFactorCached,
324 contentRect.size.height * _window.backingScaleFactorCached);
326 _window.backingScaleFactorCached = backingScaleFactor;
327 self.contentsScale = backingScaleFactor;
329 _updateBackingCallback(_userData, backingScaleFactor);
331 if (_window.maintainsPixelSizeWhenBackingChanges)
335 NSSize newContentRectPointSize = NSMakeSize(oldContentRectPixelSize.width / _window.backingScaleFactorCached,
336 oldContentRectPixelSize.height / _window.backingScaleFactorCached);
338 NSRect contentRect = [_window contentRectForFrameRect:_window.frame];
342 contentRect.origin.y += contentRect.size.height - newContentRectPointSize.height;
344 contentRect.size = newContentRectPointSize;
345 [_window setFrame:[_window frameRectForContentRect:contentRect] display:YES animate:NO];
370 - (void)setBounds:(CGRect)bounds
372 [
super setBounds:bounds];
383 if (now - _renderScheduled > 0.4)
385 _renderScheduled = now;
386 dispatch_async(dispatch_get_main_queue(), ^{
387 [
self setNeedsDisplay];
398 - (void)drawInCGLContext:(CGLContextObj)context pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
400 _renderScheduled = -INFINITY;
405 dispatch_sync(_drawQueue, ^{
410 NSRect frameInPoints =
self.frame;
411 double s = _window.backingScaleFactor;
412 NSRect frameInPixels = NSMakeRect(frameInPoints.origin.x * s, frameInPoints.origin.y * s, frameInPoints.size.width * s, frameInPoints.size.height * s);
420 GLuint receiveTexture;
421 GLuint receiveTextureBytes;
423 glGenTextures(1, &receiveTexture);
424 glActiveTexture(GL_TEXTURE0);
425 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
426 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
427 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
428 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
430 glUniform1i(_receiveTextureUniform, 0);
432 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);
433 if(err != kCGLNoError)
435 VUserLog(
"Error in CGLTexImageIOSurface2D() 2: %s", CGLErrorString(err));
439 receiveTextureBytes = ioSurfaceWidth * ioSurfaceHeight * 4;
442 glUniform2f(_receiveTextureOffsetUniform, viewport.origin.x, viewport.origin.y);
443 glViewport(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
449 if (!NSEqualRects(viewport, frameInPixels))
452 glClearColor(0,0,0,1);
453 glClear(GL_COLOR_BUFFER_BIT);
456 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, receiveTexture);
457 glDrawArrays(GL_TRIANGLES, 0, 3);
459 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
460 glDeleteTextures(1, &receiveTexture);
469 ++_framesRenderedSinceProfileLogged;
471 const double profileSeconds = 10;
472 if (t > _lastProfileLoggedTime + profileSeconds)
474 VDebugLog(
"%4.1f fps", _framesRenderedSinceProfileLogged / profileSeconds);
475 _lastProfileLoggedTime = t;
476 _framesRenderedSinceProfileLogged = 0;
491 #pragma clang diagnostic push
492 #pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
507 #pragma clang diagnostic pop