3 * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include <Cocoa/Cocoa.h>
27 #include "gstglcaopengllayer.h"
28 #include "gstgl_cocoa_private.h"
30 @implementation GstGLCAOpenGLLayer
32 if (self->draw_notify)
33 self->draw_notify (self->draw_data);
35 GST_TRACE ("dealloc GstGLCAOpenGLLayer %p context %p", self, self->gst_gl_context);
40 - (id)initWithGstGLContext:(GstGLContextCocoa *)parent_gl_context {
43 GST_LOG ("init CAOpenGLLayer");
45 self->gst_gl_context = parent_gl_context;
46 self.asynchronous = YES;
48 self.needsDisplayOnBoundsChange = YES;
53 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
54 CGLPixelFormatObj fmt = NULL;
56 if (self->gst_gl_context)
57 fmt = gst_gl_context_cocoa_get_pixel_format (self->gst_gl_context);
60 CGLPixelFormatAttribute attribs[] = {
68 GST_DEBUG ("creating new pixel format for CAOpenGLLayer %p", self);
70 ret = CGLChoosePixelFormat (attribs, &fmt, &npix);
71 if (ret != kCGLNoError) {
72 GST_ERROR ("CAOpenGLLayer cannot choose a pixel format: %s", CGLErrorString (ret));
79 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
80 CGLContextObj external_context = NULL;
83 if (self->gst_gl_context)
84 external_context = (CGLContextObj) gst_gl_context_get_gl_context (GST_GL_CONTEXT (self->gst_gl_context));
86 GST_INFO ("attempting to create CGLContext for CAOpenGLLayer with "
87 "share context %p", external_context);
89 ret = CGLCreateContext (pixelFormat, external_context, &self->gl_context);
90 if (ret != kCGLNoError) {
91 GST_ERROR ("failed to create CGL context in CAOpenGLLayer with share context %p: %s", external_context, CGLErrorString(ret));
94 return self->gl_context;
97 - (void)releaseCGLContext:(CGLContextObj)glContext {
98 CGLReleaseContext (glContext);
101 - (void)setDrawCallback:(GstGLWindowCB)cb data:(gpointer)data
102 notify:(GDestroyNotify)notify {
103 g_return_if_fail (cb);
105 if (self->draw_notify)
106 self->draw_notify (self->draw_data);
109 self->draw_data = data;
110 self->draw_notify = notify;
113 - (void)setResizeCallback:(GstGLWindowResizeCB)cb data:(gpointer)data
114 notify:(GDestroyNotify)notify {
115 if (self->resize_notify)
116 self->resize_notify (self->resize_notify);
118 self->resize_cb = cb;
119 self->resize_data = data;
120 self->resize_notify = notify;
123 - (void)drawInCGLContext:(CGLContextObj)glContext
124 pixelFormat:(CGLPixelFormatObj)pixelFormat
125 forLayerTime:(CFTimeInterval)interval
126 displayTime:(const CVTimeStamp *)timeStamp {
127 const GstGLFuncs *gl = ((GstGLContext *)self->gst_gl_context)->gl_vtable;
128 GstVideoRectangle src, dst, result;
131 GST_LOG ("CAOpenGLLayer drawing with cgl context %p", glContext);
133 /* attempt to get the correct viewport back due to CA being too smart
134 * and messing around with it so center the expected viewport into
135 * the CA viewport set up on entry to this function */
136 gl->GetIntegerv (GL_VIEWPORT, ca_viewport);
138 if (self->last_bounds.size.width != self.bounds.size.width
139 || self->last_bounds.size.height != self.bounds.size.height) {
140 if (self->resize_cb) {
141 self->resize_cb (self->resize_data, self.bounds.size.width,
142 self.bounds.size.height);
144 gl->GetIntegerv (GL_VIEWPORT, self->expected_dims);
146 /* default to whatever ca gives us */
147 self->expected_dims[0] = ca_viewport[0];
148 self->expected_dims[1] = ca_viewport[1];
149 self->expected_dims[2] = ca_viewport[2];
150 self->expected_dims[3] = ca_viewport[3];
153 self->last_bounds = self.bounds;
156 src.x = self->expected_dims[0];
157 src.y = self->expected_dims[1];
158 src.w = self->expected_dims[2];
159 src.h = self->expected_dims[3];
161 dst.x = ca_viewport[0];
162 dst.y = ca_viewport[1];
163 dst.w = ca_viewport[2];
164 dst.h = ca_viewport[3];
166 gst_video_sink_center_rect (src, dst, &result, TRUE);
168 gl->Viewport (result.x, result.y, result.w, result.h);
171 self->draw_cb (self->draw_data);
173 /* flushes the buffer */
174 [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:interval displayTime:timeStamp];