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