1 #define WANT_ARCAN_SHMIF_HELPER
2 #define AGP_ENABLE_UNPURE
3 #include "../arcan_shmif.h"
4 #include "../shmif_privext.h"
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xatom.h>
8 #include <X11/Xutil.h>
9 
10 #include "agp/glfun.h"
11 
12 #include <GL/glx.h>
13 
14 struct shmif_ext_hidden_int {
15 	GLXContext ctx;
16 	XVisualInfo* vi;
17 	Display* display;
18 	struct agp_rendertarget* rtgt;
19 	struct agp_vstore vstore;
20 	struct agp_fenv fenv;
21 	bool managed;
22 	Window wnd;
23 };
24 
arcan_shmifext_defaults(struct arcan_shmif_cont * con)25 struct arcan_shmifext_setup arcan_shmifext_defaults(
26 	struct arcan_shmif_cont* con)
27 {
28 	return (struct arcan_shmifext_setup){
29 		.red = 8, .green = 8, .blue = 8,
30 		.alpha = 0, .depth = 24,
31 		.api = API_OPENGL,
32 		.builtin_fbo = true,
33 		.major = 2, .minor = 1
34 	};
35 }
36 
arcan_shmifext_getfenv(struct arcan_shmif_cont * con)37 struct agp_fenv* arcan_shmifext_getfenv(struct arcan_shmif_cont* con)
38 {
39 	if (!con || !con->privext || !con->privext->internal)
40 		return false;
41 
42 	struct shmif_ext_hidden_int* in = con->privext->internal;
43 	return &in->fenv;
44 }
45 
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)46 bool arcan_shmifext_import_buffer(
47 	struct arcan_shmif_cont* cont,
48 	struct shmifext_buffer_plane* planes,
49 	int format,
50 	size_t n_planes,
51 	size_t buffer_plane_sz
52 )
53 {
54 	return false;
55 }
56 
arcan_shmifext_signal_planes(struct arcan_shmif_cont * c,int mask,size_t n_planes,struct shmifext_buffer_plane * planes)57 size_t arcan_shmifext_signal_planes(
58 	struct arcan_shmif_cont* c,
59 	int mask,
60 	size_t n_planes,
61 	struct shmifext_buffer_plane* planes
62 )
63 {
64 	return 0;
65 }
66 
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)67 size_t arcan_shmifext_export_image(
68 	struct arcan_shmif_cont* con,
69 	uintptr_t display, uintptr_t tex_id,
70 	size_t plane_limit, struct shmifext_buffer_plane* planes)
71 {
72 	return 0;
73 }
74 
x11_drop(struct arcan_shmif_cont * con)75 static void x11_drop(struct arcan_shmif_cont* con)
76 {
77 	if (!con->privext->internal)
78 		return;
79 
80 	struct shmif_ext_hidden_int* in = con->privext->internal;
81 
82 	if (in->managed){
83 		glXDestroyContext(in->display, in->ctx);
84 		XCloseDisplay(in->display);
85 	}
86 	if (in->rtgt){
87 		agp_drop_rendertarget(in->rtgt);
88 		agp_drop_vstore(&in->vstore);
89 		in->rtgt = NULL;
90 	}
91 
92 	free(con->privext->internal);
93 	con->privext->internal = NULL;
94 }
95 
arcan_shmifext_drop(struct arcan_shmif_cont * con)96 bool arcan_shmifext_drop(struct arcan_shmif_cont* con)
97 {
98 	if (!con || !con->privext || !con->privext->internal)
99 		return false;
100 	x11_drop(con);
101 	return true;
102 }
103 
arcan_shmifext_drop_context(struct arcan_shmif_cont * con)104 bool arcan_shmifext_drop_context(struct arcan_shmif_cont* con)
105 {
106 	return arcan_shmifext_drop(con);
107 }
108 
arcan_shmifext_lookup(struct arcan_shmif_cont * con,const char * fun)109 void* arcan_shmifext_lookup(
110 	struct arcan_shmif_cont* con, const char* fun)
111 {
112 	return glXGetProcAddress((const GLubyte*) fun);
113 }
114 
lookup_fun(void * tag,const char * sym,bool req)115 static void* lookup_fun(void* tag, const char* sym, bool req)
116 {
117 	return glXGetProcAddress((const GLubyte*) sym);
118 }
119 
arcan_shmifext_swap_context(struct arcan_shmif_cont * con,unsigned context)120 void arcan_shmifext_swap_context(
121 	struct arcan_shmif_cont* con, unsigned context)
122 {
123 }
124 
arcan_shmifext_add_context(struct arcan_shmif_cont * con,struct arcan_shmifext_setup arg)125 unsigned arcan_shmifext_add_context(
126 	struct arcan_shmif_cont* con, struct arcan_shmifext_setup arg)
127 {
128 	return 0;
129 }
130 
arcan_shmifext_setup(struct arcan_shmif_cont * con,struct arcan_shmifext_setup arg)131 enum shmifext_setup_status arcan_shmifext_setup(
132 	struct arcan_shmif_cont* con,
133 	struct arcan_shmifext_setup arg)
134 {
135 	if (con->privext->internal)
136 		con->privext->cleanup(con);
137 
138 	struct shmif_ext_hidden_int* ctx = con->privext->internal =
139 		malloc(sizeof(struct shmif_ext_hidden_int));
140 	memset(ctx, '\0', sizeof(struct shmif_ext_hidden_int));
141 
142 	if (!con->privext->internal)
143 		return SHMIFEXT_NO_DISPLAY;
144 
145 	int alist[] = {
146 		GLX_RGBA,
147 		GLX_DEPTH_SIZE,
148 		arg.depth,
149 		None
150 	};
151 
152 	con->privext->cleanup = x11_drop;
153 	ctx->display = XOpenDisplay(NULL);
154 	if (!ctx->display){
155 		free(con->privext->internal);
156 		con->privext->internal = NULL;
157 		return SHMIFEXT_NO_DISPLAY;
158 	}
159 
160 	ctx->wnd = DefaultRootWindow(ctx->display);
161 	ctx->vi = glXChooseVisual(ctx->display, DefaultScreen(ctx->display), alist);
162 	ctx->ctx = glXCreateContext(ctx->display, ctx->vi, 0, GL_TRUE);
163 	if (!ctx->ctx){
164 		XCloseDisplay(con->privext->internal->display);
165 		free(con->privext->internal);
166 		con->privext->internal = NULL;
167 		return SHMIFEXT_NO_CONTEXT;
168 	}
169 
170 	agp_glinit_fenv(&con->privext->internal->fenv, lookup_fun, NULL);
171 
172 	if (!glXMakeCurrent(ctx->display, ctx->wnd, ctx->ctx))
173 		XSync(ctx->display, False);
174 
175 	ctx->managed = true;
176 	if (arg.builtin_fbo){
177 		agp_empty_vstore(&ctx->vstore, con->w, con->h);
178 		ctx->rtgt = agp_setup_rendertarget(
179 			&ctx->vstore, arg.depth > 0 ? RENDERTARGET_COLOR_DEPTH_STENCIL :
180 				RENDERTARGET_COLOR);
181 	}
182 
183 	return SHMIFEXT_OK;
184 }
185 
arcan_shmifext_bufferfail(struct arcan_shmif_cont * cont,bool fl)186 void arcan_shmifext_bufferfail(struct arcan_shmif_cont* cont, bool fl)
187 {
188 }
189 
arcan_shmifext_dev(struct arcan_shmif_cont * con,uintptr_t * dev,bool clone)190 int arcan_shmifext_dev(struct arcan_shmif_cont* con,
191 	uintptr_t* dev, bool clone)
192 {
193 	if (dev)
194 		*dev = 0;
195 
196     return -1;
197 }
198 
arcan_shmifext_gl_handles(struct arcan_shmif_cont * con,uintptr_t * frame,uintptr_t * color,uintptr_t * depth)199 bool arcan_shmifext_gl_handles(struct arcan_shmif_cont* con,
200 	uintptr_t* frame, uintptr_t* color, uintptr_t* depth)
201 {
202 	if (!con || !con->privext || !con->privext->internal ||
203 		!con->privext->internal->display || !con->privext->internal->rtgt)
204 		return false;
205 
206 	agp_rendertarget_ids(con->privext->internal->rtgt, frame, color, depth);
207 	return true;
208 }
209 
arcan_shmifext_egl(struct arcan_shmif_cont * con,void ** display,void * (* lookupfun)(void *,const char *),void * tag)210 bool arcan_shmifext_egl(struct arcan_shmif_cont* con,
211 	void** display, void*(*lookupfun)(void*, const char*), void* tag)
212 {
213 	return false;
214 }
215 
arcan_shmifext_gltex_handle(struct arcan_shmif_cont * con,uintptr_t display,uintptr_t tex_id,int * dhandle,size_t * dstride,int * dfmt)216 bool arcan_shmifext_gltex_handle(struct arcan_shmif_cont* con,
217    uintptr_t display, uintptr_t tex_id,
218 	 int* dhandle, size_t* dstride, int* dfmt)
219 {
220 	return false;
221 }
222 
arcan_shmifext_free_color(struct arcan_shmif_cont * con,struct shmifext_color_buffer * out)223 void arcan_shmifext_free_color(
224 	struct arcan_shmif_cont* con, struct shmifext_color_buffer* out)
225 {
226 }
227 
arcan_shmifext_alloc_color(struct arcan_shmif_cont * con,struct shmifext_color_buffer * out)228 bool arcan_shmifext_alloc_color(
229 	struct arcan_shmif_cont* con, struct shmifext_color_buffer* out)
230 {
231 	return false;
232 }
233 
arcan_shmifext_make_current(struct arcan_shmif_cont * con)234 bool arcan_shmifext_make_current(struct arcan_shmif_cont* con)
235 {
236 	if (!con || !con->privext || !con->privext->internal)
237 		return false;
238 
239 	struct shmif_ext_hidden_int* ctx = con->privext->internal;
240 
241 	if (!glXMakeCurrent(ctx->display, ctx->wnd, ctx->ctx)){
242 		XSync(ctx->display, False);
243 		return false;
244 	}
245 
246 	if (ctx->rtgt){
247 		if (ctx->vstore.w != con->w || ctx->vstore.h != con->h){
248 			agp_activate_rendertarget(NULL);
249 			agp_resize_rendertarget(ctx->rtgt, con->w, con->h);
250 		}
251 		agp_activate_rendertarget(ctx->rtgt);
252 	}
253 
254 	return true;
255 }
256 
arcan_shmifext_isext(struct arcan_shmif_cont * con)257 int arcan_shmifext_isext(struct arcan_shmif_cont* con)
258 {
259 	if (con && con->privext && con->privext->internal)
260 		return 2; /* we don't support handle passing via IOSurfaces yet */
261 	return 0;
262 }
263 
arcan_shmifext_vk(struct arcan_shmif_cont * con,void ** display,void * (* lookupfun)(void *,const char *),void * tag)264 bool arcan_shmifext_vk(struct arcan_shmif_cont* con,
265 	void** display, void*(*lookupfun)(void*, const char*), void* tag)
266 {
267 	return false;
268 }
269 
arcan_shmifext_signal(struct arcan_shmif_cont * con,uintptr_t display,int mask,uintptr_t tex_id,...)270 int arcan_shmifext_signal(struct arcan_shmif_cont* con,
271 	uintptr_t display, int mask, uintptr_t tex_id, ...)
272 {
273 	if (!con || !con->privext || !con->privext->internal)
274 		return -1;
275 	struct shmif_ext_hidden_int* ctx = con->privext->internal;
276 
277 	if (tex_id == SHMIFEXT_BUILTIN){
278 		if (ctx->managed)
279 			tex_id = ctx->vstore.vinf.text.glid;
280 		else
281 			return -1;
282 	}
283 
284 /*
285  * There are some possible extensions for sharing resources from a GLX
286  * context between processes, but it's on the very distant research- list
287  * and would need a corresponding _map_handle etc. implementation server-side
288  *
289  * right now, juse use the slow readback method
290  */
291 	struct agp_vstore vstore = {
292 		.w = con->w,
293 		.h = con->h,
294 		.txmapped = TXSTATE_TEX2D,
295 		.vinf.text = {
296 			.glid = tex_id,
297 			.raw = (void*) con->vidp
298 		},
299 	};
300 
301 	if (ctx->rtgt){
302 		agp_activate_rendertarget(NULL);
303 		agp_readback_synchronous(&vstore);
304 		agp_activate_rendertarget(ctx->rtgt);
305 	}
306 	else
307 		agp_readback_synchronous(&vstore);
308 
309 	unsigned res = arcan_shmif_signal(con, mask);
310 	return res > INT_MAX ? INT_MAX : res;
311 }
312 
platform_video_map_handle(struct agp_vstore * store,int64_t handle)313 bool platform_video_map_handle(struct agp_vstore* store, int64_t handle)
314 {
315 	return false;
316 }
317