#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <dlfcn.h>
#include "appledri.h"
#include "apple_glx.h"
#include "apple_glx_context.h"
#include "apple_cgl.h"
#include "apple_xgl_api.h"
static bool initialized = false;
static int dri_event_base = 0;
const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
#ifndef OPENGL_LIB_PATH
#define OPENGL_LIB_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
#endif
static void *libgl_handle = NULL;
static bool diagnostic = false;
void apple_glx_diagnostic(const char *fmt, ...) {
va_list vl;
if(diagnostic) {
fprintf(stderr, "DIAG: ");
va_start(vl, fmt);
vfprintf(stderr, fmt, vl);
va_end(vl);
}
}
int apple_get_dri_event_base(void) {
if(!initialized) {
fprintf(stderr, "error: dri_event_base called before apple_init_glx!\n");
abort();
}
return dri_event_base;
}
static void surface_notify_handler(Display *dpy, unsigned int uid, int kind) {
switch(kind) {
case AppleDRISurfaceNotifyDestroyed:
apple_glx_diagnostic("%s: surface destroyed %u\n", __func__, uid);
apple_glx_surface_destroy(uid);
break;
case AppleDRISurfaceNotifyChanged: {
int updated;
updated = apple_glx_context_surface_changed(uid, pthread_self());
apple_glx_diagnostic("surface notify updated %d\n", updated);
}
break;
default:
fprintf(stderr, "unhandled kind of event: %d in %s\n", kind, __func__);
}
}
xp_client_id apple_glx_get_client_id(void) {
static xp_client_id id;
if(0 == id) {
if((XP_Success != xp_init(XP_IN_BACKGROUND)) ||
(Success != xp_get_client_id(&id))) {
return 0;
}
}
return id;
}
bool apple_init_glx(Display *dpy) {
int eventBase, errorBase;
int major, minor, patch;
if(!XAppleDRIQueryExtension(dpy, &eventBase, &errorBase))
return true;
if(!XAppleDRIQueryVersion(dpy, &major, &minor, &patch))
return true;
if(initialized)
return false;
if(getenv("LIBGL_DIAGNOSTIC")) {
printf("initializing libGL in %s\n", __func__);
diagnostic = true;
}
apple_cgl_init();
apple_xgl_init_direct();
libgl_handle = dlopen(OPENGL_LIB_PATH, RTLD_LAZY);
(void)apple_glx_get_client_id();
XAppleDRISetSurfaceNotifyHandler(surface_notify_handler);
dri_event_base = eventBase;
initialized = true;
return false;
}
void apple_glx_swap_buffers(void *ptr) {
struct apple_glx_context *ac = ptr;
glFlush();
apple_cgl.flush_drawable(ac->context_obj);
}
void *apple_glx_get_proc_address(const GLubyte *procname) {
size_t len;
void *h, *s;
char *pname = (char *)procname;
assert(NULL != procname);
len = strlen(pname);
if(len < 3) {
return NULL;
}
if((pname != strstr(pname, "glX")) &&
(pname != strstr(pname, "gl"))) {
fprintf(stderr, "warning: get proc address request is not for a gl or glX function");
return NULL;
}
(void)dlerror();
h = dlopen(NULL, RTLD_NOW);
if(NULL == h) {
fprintf(stderr, "warning: get proc address: %s\n", dlerror());
return NULL;
}
s = dlsym(h, pname);
if(NULL == s) {
s = dlsym(libgl_handle, pname);
}
dlclose(h);
return s;
}
void apple_glx_waitx(Display *dpy, void *ptr) {
struct apple_private_context *ac = ptr;
(void)ac;
glFlush();
glFinish();
XSync(dpy, False);
}