Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
10 kB · 417 lines
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417#include <stdlib.h>#include <stdio.h> // for fprintf(stderr, "unimplemented")
#include <pthread.h>
#include <OpenGL/OpenGL.h>#include <OpenGL/CGLInternal.h>#include <CoreFoundation/CFDictionary.h>#include <pthread.h>
// Try to get the right (generic) type definitions.// In particular, we really want EGLNativeDisplayType to be void *,// not int as it is if __APPLE__ is defined.#undef APPLE#undef __APPLE__
#define __unix__#define EGL_NO_X11
#include <EGL/egl.h>
#define APPLE#define __APPLE__
static EGLDisplay display;
static EGLConfig config;static int num_config;
static EGLint const attribute_list[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_NONE};
struct _CGLDisplay{ EGLDisplay display; EGLConfig config; int num_config;};
static CFMutableDictionaryRef g_displays;static pthread_mutex_t g_displaysMutex = PTHREAD_MUTEX_INITIALIZER;
struct _CGLContextObj { GLuint retain_count; pthread_mutex_t lock; EGLContext egl_context; EGLSurface egl_surface; // EGL has no function for getting the current swap interval, // so we need to save the last set value. The default is 1. int swap_interval;};
struct _CGLPixelFormatObj { GLuint retain_count; CGLPixelFormatAttribute *attributes;};
static inline int attribute_has_argument(CGLPixelFormatAttribute attr) { switch (attr) { case kCGLPFAAuxBuffers: case kCGLPFAColorSize: case kCGLPFAAlphaSize: case kCGLPFADepthSize: case kCGLPFAStencilSize: case kCGLPFAAccumSize: case kCGLPFARendererID: case kCGLPFADisplayMask: return 1; default: return 0; }}
__attribute__((constructor))static void _CGLInitialize(void){ g_displays = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);}
static int attributes_count(const CGLPixelFormatAttribute *attrs) { int result; for (result = 0; attrs[result] != 0; result++) { if (attribute_has_argument(attrs[result])) { result++; } } return result;}
CGLError CGLRegisterNativeDisplay(void *native_display) {
display = eglGetDisplay(native_display);
if (display == EGL_NO_DISPLAY) { return kCGLBadConnection; }
eglInitialize(display, NULL, NULL); eglChooseConfig(display, attribute_list, &config, 1, &num_config);
eglBindAPI(EGL_OPENGL_API);
return kCGLNoError;}
static struct _CGLDisplay* getCGLDisplay(CGSConnectionID cid){ struct _CGLDisplay* rv;
pthread_mutex_lock(&g_displaysMutex); rv = (struct _CGLDisplay*) CFDictionaryGetValue(g_displays, (const void*)(unsigned long) cid); pthread_mutex_unlock(&g_displaysMutex);
if (!rv) { EGLDisplay disp = eglGetDisplay(_CGSNativeDisplay(cid)); if (disp == EGL_NO_DISPLAY) return NULL;
rv = (struct _CGLDisplay*) malloc(sizeof(*rv)); rv->display = disp;
eglInitialize(rv->display, NULL, NULL); eglChooseConfig(rv->display, attribute_list, &rv->config, 1, &rv->num_config);
eglBindAPI(EGL_OPENGL_API);
pthread_mutex_lock(&g_displaysMutex); CFDictionaryAddValue(g_displays, (const void*)(unsigned long) cid, rv); pthread_mutex_unlock(&g_displaysMutex); }
return rv;}
CGLError CGLSetSurface(CGLContextObj gl, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid){ struct _CGLDisplay* disp = getCGLDisplay(cid); if (!disp) return kCGLBadConnection;
EGLNativeWindowType window; if (sid) window = (EGLNativeWindowType) _CGSNativeWindowForSurfaceID(cid, wid, sid); else window = (EGLNativeWindowType) _CGSNativeWindowForID(cid, wid);
if (!window) return kCGLBadWindow;
gl->egl_surface = eglCreateWindowSurface(disp->display, disp->config, window, NULL); if (gl->egl_surface == EGL_NO_SURFACE) return kCGLBadState; return kCGLNoError;}
CGLWindowRef CGLGetWindow(void *native_window) {
EGLNativeWindowType window = (EGLNativeWindowType) native_window; EGLSurface surface = eglCreateWindowSurface(display, config, window, NULL);
if (surface == EGL_NO_SURFACE) { return NULL; }
return (CGLWindowRef) surface;}
CGL_EXPORT void CGLDestroyWindow(CGLWindowRef window) { eglDestroySurface(display, (EGLSurface) window);}
CGL_EXPORT CGLError CGLContextMakeCurrentAndAttachToWindow(CGLContextObj context, CGLWindowRef window) { if (!context) return kCGLBadContext; context->egl_surface = (EGLSurface) window; return CGLSetCurrentContext(context);}
static pthread_key_t current_context_key;
static void make_key() { pthread_key_create(¤t_context_key, NULL);}
static pthread_key_t get_current_context_key() { static pthread_once_t key_once = PTHREAD_ONCE_INIT; pthread_once(&key_once, make_key); return current_context_key;}
CGLContextObj CGLGetCurrentContext(void) { pthread_key_t key = get_current_context_key(); return pthread_getspecific(key);}
CGLError CGLSetCurrentContext(CGLContextObj context) { pthread_key_t key = get_current_context_key(); pthread_setspecific(key, context);
if (context != NULL) { EGLSurface surface = context->egl_surface; eglMakeCurrent(display, surface, surface, context->egl_context); } else { eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); }
return kCGLNoError; // FIXME}
CGLError CGLChoosePixelFormat( const CGLPixelFormatAttribute *attrs, CGLPixelFormatObj *result, GLint *number_of_screens) { CGLPixelFormatObj format = malloc(sizeof(struct _CGLPixelFormatObj)); int count = attributes_count(attrs);
format->retain_count = 1; format->attributes = malloc(sizeof(CGLPixelFormatAttribute) * count); for (int i = 0; i < count; i++) { format->attributes[i] = attrs[i]; }
*result = format; *number_of_screens = 1;
return kCGLNoError;}
CGLError CGLDescribePixelFormat( CGLPixelFormatObj format, GLint sreen_num, CGLPixelFormatAttribute attr, GLint *value) { for (int i = 0; format->attributes[i] != 0; i++) { int has_arg = attribute_has_argument(format->attributes[i]);
if (format->attributes[i] == attr) { if (has_arg) { *value = format->attributes[i + 1]; } else { *value = 1; } return kCGLNoError; }
if (has_arg) { i++; } }
*value = 0; return kCGLNoError;}
CGLPixelFormatObj CGLRetainPixelFormat(CGLPixelFormatObj format) { if (format == NULL) { return NULL; }
format->retain_count++; return format;}
void CGLReleasePixelFormat(CGLPixelFormatObj format) { if (format == NULL) { return; }
format->retain_count--;
if (format->retain_count == 0) { free(format->attributes); free(format); }}
CGLError CGLDestroyPixelFormat(CGLPixelFormatObj pixelFormat) { CGLReleasePixelFormat(pixelFormat); return kCGLNoError;}
GLuint CGLGetPixelFormatRetainCount(CGLPixelFormatObj pixelFormat) { return pixelFormat->retain_count;}
CGLError CGLCreateContext(CGLPixelFormatObj pixelFormat, CGLContextObj share, CGLContextObj *resultp) {
EGLContext egl_share = EGL_NO_CONTEXT; if (share != NULL) { egl_share = share->egl_context; } EGLContext egl_context = eglCreateContext(display, config, egl_share, NULL);
if (egl_context == EGL_NO_CONTEXT) { return kCGLBadContext; }
CGLContextObj context = malloc(sizeof(struct _CGLContextObj));
context->retain_count = 1; pthread_mutex_init(&(context->lock), NULL); context->egl_context = egl_context; context->egl_surface = NULL; context->swap_interval = 1;
*resultp = context;
return kCGLNoError;}
CGLContextObj CGLRetainContext(CGLContextObj context) { if (context == NULL) { return NULL; }
context->retain_count++; return context;}
void CGLReleaseContext(CGLContextObj context) { if (context == NULL) { return; }
context->retain_count--;
if (context->retain_count != 0) { return; }
if (CGLGetCurrentContext() == context) { CGLSetCurrentContext(NULL); }
pthread_mutex_destroy(&(context->lock));
eglDestroyContext(display, context->egl_context);
free(context);}
GLuint CGLGetContextRetainCount(CGLContextObj context) { if (context == NULL) { return 0; }
return context->retain_count;}
CGLError CGLDestroyContext(CGLContextObj context) { CGLReleaseContext(context);
return kCGLNoError;}
CGLError CGLLockContext(CGLContextObj context) { pthread_mutex_lock(&(context->lock)); return kCGLNoError;}
CGLError CGLUnlockContext(CGLContextObj context) { pthread_mutex_unlock(&(context->lock)); return kCGLNoError;}
CGLError CGLFlushDrawable(CGLContextObj context) { eglSwapBuffers(display,context->egl_surface); return kCGLNoError;}
CGLError CGLSetParameter(CGLContextObj context, CGLContextParameter parameter, const GLint *value) { if (!value) return kCGLBadAddress;
if (parameter == kCGLCPSwapInterval) { GLint v = *value; EGLBoolean success = eglSwapInterval(display, v); if (success) context->swap_interval = v; return success ? kCGLNoError : kCGLBadValue; } fprintf(stderr, "CGLSetParameter unimplemented for parameter %d\n", parameter); return kCGLNoError;}
CGLError CGLGetParameter(CGLContextObj context, CGLContextParameter parameter, GLint *value) { if (!value) return kCGLBadAddress;
if (parameter == kCGLCPSwapInterval) { *value = context->swap_interval; return kCGLNoError; } fprintf(stderr, "CGLGetParameter unimplemented for parameter %d\n", parameter); return kCGLNoError;}
CGLError CGLDescribeRenderer(CGLRendererInfoObj rend, long rend_num, CGLRendererProperty prop, long *value) { return kCGLNoError;}
CGLError CGLQueryRendererInfo(unsigned long display_mask, CGLRendererInfoObj *rend, long *nrend) { return kCGLNoError;}
CGLError CGLDestroyRendererInfo(CGLRendererInfoObj rend) { return kCGLNoError;}