1 #define WANT_ARCAN_SHMIF_HELPER
2 #define AGP_ENABLE_UNPURE
3
4 #include "../arcan_shmif.h"
5 #include "../shmif_privext.h"
6 #include "agp/glfun.h"
7
8 #include <fcntl.h>
9 #include <dlfcn.h>
10
11 #include <OpenGL/OpenGL.h>
12 #include <OpenGL/GL.h>
13
14 struct shmif_ext_hidden_int {
15 struct agp_rendertarget* rtgt;
16 struct agp_vstore vstore;
17 struct agp_fenv fenv;
18 CGLContextObj context;
19 };
20
arcan_shmifext_defaults(struct arcan_shmif_cont * con)21 struct arcan_shmifext_setup arcan_shmifext_defaults(
22 struct arcan_shmif_cont* con)
23 {
24 return (struct arcan_shmifext_setup){
25 .red = 8, .green = 8, .blue = 8, .depth = 16,
26 .api = API_OPENGL,
27 .builtin_fbo = true,
28 .major = 2, .minor = 1
29 };
30 }
31
arcan_shmifext_signal_planes(struct arcan_shmif_cont * c,int mask,size_t n_planes,struct shmifext_buffer_plane * planes)32 size_t arcan_shmifext_signal_planes(
33 struct arcan_shmif_cont* c,
34 int mask,
35 size_t n_planes,
36 struct shmifext_buffer_plane* planes
37 )
38 {
39 return 0;
40 }
41
arcan_shmifext_export_image(struct arcan_shmif_cont * con,uintptr_t display,uintptr_t tex_id,size_t plane_limit,struct shmifext_buffer_plane * planes)42 size_t arcan_shmifext_export_image(
43 struct arcan_shmif_cont* con,
44 uintptr_t display, uintptr_t tex_id,
45 size_t plane_limit, struct shmifext_buffer_plane* planes)
46 {
47 return 0;
48 }
49
lookup_fenv(void * tag,const char * sym,bool req)50 static void* lookup_fenv(void* tag, const char* sym, bool req)
51 {
52 return arcan_shmifext_lookup(NULL, sym);
53 }
54
arcan_shmifext_getfenv(struct arcan_shmif_cont * con)55 struct agp_fenv* arcan_shmifext_getfenv(struct arcan_shmif_cont* con)
56 {
57 if (!con || !con->privext || !con->privext->internal)
58 return false;
59
60 struct shmif_ext_hidden_int* in = con->privext->internal;
61 return &in->fenv;
62 }
63
arcan_shmifext_isext(struct arcan_shmif_cont * con)64 int arcan_shmifext_isext(struct arcan_shmif_cont* con)
65 {
66 if (con && con->privext && con->privext->internal)
67 return 2; /* we don't support handle passing via IOSurfaces yet */
68 return 0;
69 }
70
arcan_shmifext_alloc_color(struct arcan_shmif_cont * con,struct shmifext_color_buffer * out)71 bool arcan_shmifext_alloc_color(
72 struct arcan_shmif_cont* con, struct shmifext_color_buffer* out)
73 {
74 return false;
75 }
76
arcan_shmifext_free_color(struct arcan_shmif_cont * con,struct shmifext_color_buffer * out)77 void arcan_shmifext_free_color(
78 struct arcan_shmif_cont* con, struct shmifext_color_buffer* out)
79 {
80 }
81
arcan_shmifext_drop(struct arcan_shmif_cont * con)82 bool arcan_shmifext_drop(struct arcan_shmif_cont* con)
83 {
84 if (!con || !con->privext || !con->privext->internal)
85 return false;
86
87 struct shmif_ext_hidden_int* in = con->privext->internal;
88 con->privext->internal = NULL;
89
90 if (in->rtgt){
91 agp_drop_rendertarget(in->rtgt);
92 agp_drop_vstore(&in->vstore);
93 }
94 CGLDestroyContext(in->context);
95
96 free(in);
97 return true;
98 }
99
arcan_shmifext_drop_context(struct arcan_shmif_cont * con)100 bool arcan_shmifext_drop_context(struct arcan_shmif_cont* con)
101 {
102 return arcan_shmifext_drop(con);
103 }
104
arcan_shmifext_swap_context(struct arcan_shmif_cont * con,unsigned context)105 void arcan_shmifext_swap_context(
106 struct arcan_shmif_cont* con, unsigned context)
107 {
108 }
109
arcan_shmifext_add_context(struct arcan_shmif_cont * con,struct arcan_shmifext_setup arg)110 unsigned arcan_shmifext_add_context(
111 struct arcan_shmif_cont* con, struct arcan_shmifext_setup arg)
112 {
113 return 0;
114 }
115
arcan_shmifext_setup(struct arcan_shmif_cont * con,struct arcan_shmifext_setup arg)116 enum shmifext_setup_status arcan_shmifext_setup(
117 struct arcan_shmif_cont* con,
118 struct arcan_shmifext_setup arg)
119 {
120 CGLPixelFormatObj pix;
121 CGLError errc;
122 GLint num;
123
124 CGLPixelFormatAttribute attributes[] = {
125 kCGLPFAAccelerated,
126 kCGLPFAOpenGLProfile,
127 (CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy,
128 (CGLPixelFormatAttribute) 0,
129 kCGLPFAColorSize, 24,
130 kCGLPFADepthSize, arg.depth,
131 (CGLPixelFormatAttribute) 0, /* supersample */
132 (CGLPixelFormatAttribute) 0,
133 };
134
135 if (arg.supersample)
136 attributes[8] = kCGLPFASupersample;
137
138 switch(arg.api){
139 case API_OPENGL:
140 break;
141 default:
142 return SHMIFEXT_NO_API;
143 break;
144 }
145
146 if (arg.major == 3){
147 attributes[2] = (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core;
148 }
149 else if (arg.major > 3){
150 return SHMIFEXT_NO_API;
151 }
152
153 errc = CGLChoosePixelFormat( attributes, &pix, &num );
154 if (!pix)
155 return SHMIFEXT_NO_CONFIG;
156
157 struct shmif_ext_hidden_int* ictx = malloc(sizeof(
158 struct shmif_ext_hidden_int));
159
160 if (!ictx){
161 CGLDestroyPixelFormat(pix);
162 return SHMIFEXT_NO_CONFIG;
163 }
164 memset(ictx, '\0', sizeof(struct shmif_ext_hidden_int));
165
166 errc = CGLCreateContext( pix, NULL, &ictx->context );
167 CGLDestroyPixelFormat( pix );
168 if (!ictx->context){
169 free(ictx);
170 return SHMIFEXT_NO_CONTEXT;
171 }
172 errc = CGLSetCurrentContext(ictx->context);
173
174 /*
175 * no double buffering,
176 * we let the parent transfer process act as the limiting clock.
177 */
178 GLint si = 0;
179 CGLSetParameter(ictx->context, kCGLCPSwapInterval, &si);
180
181 agp_glinit_fenv(&ictx->fenv, lookup_fenv, NULL);
182
183 if (arg.builtin_fbo){
184 agp_empty_vstore(&ictx->vstore, con->w, con->h);
185 ictx->rtgt = agp_setup_rendertarget(
186 &ictx->vstore, arg.depth > 0 ? RENDERTARGET_COLOR_DEPTH_STENCIL :
187 RENDERTARGET_COLOR);
188 }
189 con->privext->internal = ictx;
190 return SHMIFEXT_OK;
191 }
192
arcan_shmifext_make_current(struct arcan_shmif_cont * con)193 bool arcan_shmifext_make_current(struct arcan_shmif_cont* con)
194 {
195 if (!con || !con->addr || !con->privext || !con->privext->internal)
196 return false;
197
198 struct shmif_ext_hidden_int* ctx = con->privext->internal;
199 agp_setenv(&ctx->fenv);
200 CGLSetCurrentContext(con->privext->internal->context);
201 if (ctx->rtgt){
202 if (ctx->vstore.w != con->w || ctx->vstore.h != con->h){
203 agp_activate_rendertarget(NULL);
204 agp_resize_rendertarget(ctx->rtgt, con->w, con->h);
205 }
206 agp_activate_rendertarget(ctx->rtgt);
207 }
208
209 return true;
210 }
211
arcan_shmifext_gl_handles(struct arcan_shmif_cont * con,uintptr_t * frame,uintptr_t * color,uintptr_t * depth)212 bool arcan_shmifext_gl_handles(struct arcan_shmif_cont* con,
213 uintptr_t* frame, uintptr_t* color, uintptr_t* depth)
214 {
215 if (!con || !con->privext || !con->privext->internal ||
216 !con->privext->internal->rtgt)
217 return false;
218
219 agp_rendertarget_ids(con->privext->internal->rtgt, frame, color, depth);
220 return true;
221 }
222
arcan_shmifext_egl_meta(struct arcan_shmif_cont * con,uintptr_t * display,uintptr_t * surface,uintptr_t * context)223 bool arcan_shmifext_egl_meta(struct arcan_shmif_cont* con,
224 uintptr_t* display, uintptr_t* surface, uintptr_t* context)
225 {
226 if (!con || !con->addr || !con->privext || !con->privext->internal)
227 return false;
228
229 if (context)
230 *context = (uintptr_t) con->privext->internal->context;
231
232 if (display)
233 *display = 0;
234
235 if (surface)
236 *surface = 0;
237
238 return true;
239 }
240
arcan_shmifext_gltex_handle(struct arcan_shmif_cont * con,uintptr_t display,uintptr_t tex_id,int * dhandle,size_t * dstride,int * dfmt)241 bool arcan_shmifext_gltex_handle(struct arcan_shmif_cont* con,
242 uintptr_t display, uintptr_t tex_id,
243 int* dhandle, size_t* dstride, int* dfmt)
244 {
245 return false;
246 }
247
arcan_shmifext_dev(struct arcan_shmif_cont * con,uintptr_t * dev,bool clone)248 int arcan_shmifext_dev(struct arcan_shmif_cont* con,
249 uintptr_t* dev, bool clone)
250 {
251 if (dev)
252 *dev = 0;
253
254 return -1;
255 }
256
arcan_shmifext_bufferfail(struct arcan_shmif_cont * cont,bool fl)257 void arcan_shmifext_bufferfail(struct arcan_shmif_cont* cont, bool fl)
258 {
259 }
260
arcan_shmifext_lookup(struct arcan_shmif_cont * con,const char * sym)261 void* arcan_shmifext_lookup(
262 struct arcan_shmif_cont* con, const char* sym)
263 {
264 static void* dlh = NULL;
265 if (NULL == dlh)
266 dlh = dlopen("/System/Library/Frameworks/"
267 "OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
268
269 return dlh ? dlsym(dlh, sym) : NULL;
270 }
271
arcan_shmifext_egl(struct arcan_shmif_cont * con,void ** display,void * (* lookupfun)(void *,const char *),void * tag)272 bool arcan_shmifext_egl(struct arcan_shmif_cont* con,
273 void** display, void*(*lookupfun)(void*, const char*), void* tag)
274 {
275 return false;
276 }
277
arcan_shmifext_vk(struct arcan_shmif_cont * con,void ** display,void * (* lookupfun)(void *,const char *),void * tag)278 bool arcan_shmifext_vk(struct arcan_shmif_cont* con,
279 void** display, void*(*lookupfun)(void*, const char*), void* tag)
280 {
281 return false;
282 }
283
arcan_shmifext_signal(struct arcan_shmif_cont * con,uintptr_t display,int mask,uintptr_t tex_id,...)284 int arcan_shmifext_signal(struct arcan_shmif_cont* con,
285 uintptr_t display, int mask, uintptr_t tex_id, ...)
286 {
287 if (!con || !con->addr || !con->privext || !con->privext->internal)
288 return -1;
289 struct shmif_ext_hidden_int* ctx = con->privext->internal;
290
291 if (tex_id == SHMIFEXT_BUILTIN)
292 tex_id = ctx->vstore.vinf.text.glid;
293
294 struct agp_vstore vstore = {
295 .w = con->w,
296 .h = con->h,
297 .txmapped = TXSTATE_TEX2D,
298 .vinf.text = {
299 .glid = tex_id,
300 .raw = (void*) con->vidp
301 },
302 };
303
304 if (ctx->rtgt){
305 agp_activate_rendertarget(NULL);
306 agp_readback_synchronous(&vstore);
307 agp_activate_rendertarget(ctx->rtgt);
308 }
309 else
310 agp_readback_synchronous(&vstore);
311
312 unsigned res = arcan_shmif_signal(con, mask);
313 return res > INT_MAX ? INT_MAX : res;
314 }
315
arcan_shmifext_import_buffer(struct arcan_shmif_cont * cont,struct shmifext_buffer_plane * planes,int format,size_t n_planes,size_t buffer_plane_sz)316 bool arcan_shmifext_import_buffer(
317 struct arcan_shmif_cont* cont,
318 struct shmifext_buffer_plane* planes,
319 int format,
320 size_t n_planes,
321 size_t buffer_plane_sz
322 )
323 {
324 return false;
325 }
326
327 /*
328 * workaround for some namespace pollution
329 */
330 #include <mach/mach_time.h>
331
platform_video_map_handle(struct agp_vstore * dst,int64_t handle)332 bool platform_video_map_handle(
333 struct agp_vstore* dst, int64_t handle)
334 {
335 return false;
336 }
337
arcan_warning(const char * msg,...)338 void arcan_warning(const char* msg, ...)
339 {
340 }
341
arcan_fatal(const char * msg,...)342 void arcan_fatal(const char* msg, ...)
343 {
344 }
345
arcan_timemillis()346 unsigned long long int arcan_timemillis()
347 {
348 uint64_t time = mach_absolute_time();
349 static double sf;
350
351 if (!sf){
352 mach_timebase_info_data_t info;
353 kern_return_t ret = mach_timebase_info(&info);
354 if (ret == 0)
355 sf = (double)info.numer / (double)info.denom;
356 else{
357 sf = 1.0;
358 }
359 }
360 return ( (double)time * sf) / 1000000;
361 }
362
363
364