1 /*
2 * Copyright 2014-2017, Björn Ståhl
3 * License: 3-Clause BSD, see COPYING file in arcan source repository.
4 * Reference: http://arcan-fe.com
5 */
6
7 /*
8 * PLATFORM DRIVER NOTICE:
9 * This platform driver is incomplete in the sense that it was only set
10 * up in order to allow for headless LWA/hijack/retro3d.
11 *
12 * Note that we can probably get decent working buffer passing without
13 * readbacks here using IOSurface, see the serverOpenGLView.m
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <math.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <dlfcn.h>
27
28 #include "arcan_math.h"
29 #include "arcan_general.h"
30 #include "arcan_video.h"
31 #include "arcan_videoint.h"
32
33 #ifndef PLATFORM_SUFFIX
34 #define PLATFORM_SUFFIX platform
35 #endif
36
37 #define MERGE(X,Y) X ## Y
38 #define EVAL(X,Y) MERGE(X,Y)
39 #define PLATFORM_SYMBOL(fun) EVAL(PLATFORM_SUFFIX, fun)
40
41 #include <OpenGL/OpenGL.h>
42 #include <OpenGL/GL.h>
43
44 static char* darwin_synchopts[] = {
45 "default", "driver- specific GL swap",
46 NULL
47 };
48
49 static char* darwin_envopts[] = {
50 NULL
51 };
52
53 static struct {
54 size_t mdispw, mdisph;
55 size_t canvasw, canvash;
56 } darwin;
57
58 static CGLContextObj context;
59
PLATFORM_SYMBOL(_video_init)60 bool PLATFORM_SYMBOL(_video_init)(uint16_t w, uint16_t h,
61 uint8_t bpp, bool fs, bool frames, const char* cap)
62 {
63 CGLPixelFormatObj pix;
64 CGLError errorCode;
65 GLint num;
66
67 CGLPixelFormatAttribute attributes[4] = {
68 kCGLPFAAccelerated,
69 kCGLPFAOpenGLProfile,
70 (CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy,
71 (CGLPixelFormatAttribute) 0
72 };
73
74 errorCode = CGLChoosePixelFormat( attributes, &pix, &num );
75 errorCode = CGLCreateContext( pix, NULL, &context );
76 CGLDestroyPixelFormat( pix );
77 errorCode = CGLSetCurrentContext( context );
78
79 /*
80 * no double buffering,
81 * we let the parent transfer process act as the limiting clock.
82 */
83 GLint si = 0;
84 CGLSetParameter(context, kCGLCPSwapInterval, &si);
85
86 darwin.mdispw = darwin.canvasw = w;
87 darwin.mdisph = darwin.canvash = h;
88
89 return true;
90 }
91
92 size_t platform_nupd;
PLATFORM_SYMBOL(_video_synch)93 void PLATFORM_SYMBOL(_video_synch)(uint64_t tick_count, float fract,
94 video_synchevent pre, video_synchevent post)
95 {
96 if (pre)
97 pre();
98
99 #ifndef HEADLESS_NOARCAN
100 arcan_bench_register_cost( arcan_vint_refresh(fract, &platform_nupd) );
101
102 agp_activate_rendertarget(NULL);
103
104 arcan_vint_drawrt(arcan_vint_world(), 0, 0,
105 darwin.mdispw, darwin.mdisph);
106 arcan_vint_drawcursor(false);
107 #endif
108
109 glFlush();
110
111 if (post)
112 post();
113 }
114
PLATFORM_SYMBOL(_map_buffer)115 bool PLATFORM_SYMBOL(_map_buffer)(
116 struct agp_vstore* vs, struct agp_buffer_plane* planes, size_t n)
117 {
118 return false;
119 }
120
PLATFORM_SYMBOL(_video_decay)121 size_t PLATFORM_SYMBOL(_video_decay){
122 return 0;
123 }
124
PLATFORM_SYMBOL(_video_dpms)125 enum dpms_state PLATFORM_SYMBOL(_video_dpms)(
126 platform_display_id disp, enum dpms_state state)
127 {
128 return ADPMS_ON;
129 }
130
PLATFORM_SYMBOL(_video_query_modes)131 struct monitor_mode* PLATFORM_SYMBOL(_video_query_modes)(
132 platform_display_id id, size_t* count)
133 {
134 static struct monitor_mode mode = {};
135
136 mode.width = darwin.canvasw;
137 mode.height = darwin.canvash;
138 mode.depth = sizeof(av_pixel) * 8;
139 mode.refresh = 60; /* should be queried */
140 *count = 1;
141
142 return &mode;
143 }
144
PLATFORM_SYMBOL(_video_dimensions)145 struct monitor_mode PLATFORM_SYMBOL(_video_dimensions)()
146 {
147 struct monitor_mode res = {
148 .width = darwin.canvasw,
149 .height = darwin.canvash,
150 .phy_width = darwin.mdispw,
151 .phy_height = darwin.mdisph
152 };
153 return res;
154 }
155
PLATFORM_SYMBOL(_video_auth)156 bool PLATFORM_SYMBOL(_video_auth)(int cardn, unsigned token)
157 {
158 return false;
159 }
160
PLATFORM_SYMBOL(_video_map_handle)161 bool PLATFORM_SYMBOL(_video_map_handle)(
162 struct agp_vstore* dst, int64_t handle)
163 {
164 return false;
165 }
166
PLATFORM_SYMBOL(_video_specify_mode)167 bool PLATFORM_SYMBOL(_video_specify_mode)(platform_display_id id,
168 struct monitor_mode mode)
169 {
170 return false;
171 }
172
PLATFORM_SYMBOL(_video_synchopts)173 const char** PLATFORM_SYMBOL(_video_synchopts)(void)
174 {
175 return (const char**) darwin_synchopts;
176 }
177
PLATFORM_SYMBOL(_video_envopts)178 const char** PLATFORM_SYMBOL(_video_envopts)(void)
179 {
180 return (const char**) darwin_envopts;
181 }
182
PLATFORM_SYMBOL(_video_setsynch)183 void PLATFORM_SYMBOL(_video_setsynch)(const char* arg)
184 {
185 arcan_warning("unhandled synchronization strategy (%s) ignored.\n", arg);
186 }
187
PLATFORM_SYMBOL(_video_prepare_external)188 void PLATFORM_SYMBOL(_video_prepare_external) () {}
PLATFORM_SYMBOL(_video_restore_external)189 void PLATFORM_SYMBOL(_video_restore_external) () {}
190
PLATFORM_SYMBOL(_video_shutdown)191 void PLATFORM_SYMBOL(_video_shutdown) ()
192 {
193 }
194
PLATFORM_SYMBOL(_video_display_edid)195 bool PLATFORM_SYMBOL(_video_display_edid)(platform_display_id did,
196 char** out, size_t* sz)
197 {
198 *out = NULL;
199 *sz = 0;
200 return false;
201 }
202
PLATFORM_SYMBOL(_video_displays)203 size_t PLATFORM_SYMBOL(_video_displays)(platform_display_id* dids, size_t* lim)
204 {
205 if (dids && lim && *lim > 0){
206 dids[0] = 0;
207 }
208
209 return 1;
210 }
211
PLATFORM_SYMBOL(_video_gfxsym)212 void* PLATFORM_SYMBOL(_video_gfxsym)(const char* sym)
213 {
214 static void* dlh = NULL;
215 if (NULL == dlh)
216 dlh = dlopen("/System/Library/Frameworks/"
217 "OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
218
219 return dlh ? dlsym(dlh, sym) : NULL;
220 }
221
PLATFORM_SYMBOL(_video_capstr)222 const char* PLATFORM_SYMBOL(_video_capstr)(void)
223 {
224 static char* capstr;
225
226 if (!capstr){
227 const char* vendor = (const char*) glGetString(GL_VENDOR);
228 const char* render = (const char*) glGetString(GL_RENDERER);
229 const char* version = (const char*) glGetString(GL_VERSION);
230 const char* shading = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
231 const char* exts = (const char*) glGetString(GL_EXTENSIONS);
232
233 size_t interim_sz = 64 * 1024;
234 char* interim = malloc(interim_sz);
235 size_t nw = snprintf(interim, interim_sz, "Video Platform (LWA-Darwin)\n"
236 "Vendor: %s\nRenderer: %s\nGL Version: %s\n"
237 "GLSL Version: %s\n\n Extensions Supported: \n%s\n\n",
238 vendor, render, version, shading, exts
239 ) + 1;
240
241 if (nw < (interim_sz >> 1)){
242 capstr = malloc(nw);
243 memcpy(capstr, interim, nw);
244 free(interim);
245 }
246 else
247 capstr = interim;
248 }
249
250 return capstr;
251 }
252
PLATFORM_SYMBOL(_video_minimize)253 void PLATFORM_SYMBOL(_video_minimize) () {}
254
255