diff options
Diffstat (limited to 'src/glx/apple/apple_glx_context.c')
-rw-r--r-- | src/glx/apple/apple_glx_context.c | 616 |
1 files changed, 0 insertions, 616 deletions
diff --git a/src/glx/apple/apple_glx_context.c b/src/glx/apple/apple_glx_context.c deleted file mode 100644 index c58d05a59a..0000000000 --- a/src/glx/apple/apple_glx_context.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - Copyright (c) 2008, 2009 Apple Inc. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT - HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. -*/ - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <assert.h> -#include <pthread.h> - -#include <fcntl.h> -#include <sys/mman.h> -#include <unistd.h> - -// Get the newer glext.h first -#include <GL/gl.h> -#include <GL/glext.h> - -#include <OpenGL/CGLTypes.h> -#include <OpenGL/CGLCurrent.h> -#include <OpenGL/OpenGL.h> - -#include "glxclient.h" - -#include "apple_glx.h" -#include "apple_glx_context.h" -#include "appledri.h" -#include "apple_visual.h" -#include "apple_cgl.h" -#include "apple_glx_drawable.h" - -static pthread_mutex_t context_lock = PTHREAD_MUTEX_INITIALIZER; - -/* - * This should be locked on creation and destruction of the - * apple_glx_contexts. - * - * It's also locked when the surface_notify_handler is searching - * for a uid associated with a surface. - */ -static struct apple_glx_context *context_list = NULL; - -/* This guards the context_list above. */ -static void -lock_context_list(void) -{ - int err; - - err = pthread_mutex_lock(&context_lock); - - if (err) { - fprintf(stderr, "pthread_mutex_lock failure in %s: %d\n", - __func__, err); - abort(); - } -} - -static void -unlock_context_list(void) -{ - int err; - - err = pthread_mutex_unlock(&context_lock); - - if (err) { - fprintf(stderr, "pthread_mutex_unlock failure in %s: %d\n", - __func__, err); - abort(); - } -} - -static bool -is_context_valid(struct apple_glx_context *ac) -{ - struct apple_glx_context *i; - - lock_context_list(); - - for (i = context_list; i; i = i->next) { - if (ac == i) { - unlock_context_list(); - return true; - } - } - - unlock_context_list(); - - return false; -} - -/* This creates an apple_private_context struct. - * - * It's typically called to save the struct in a GLXContext. - * - * This is also where the CGLContextObj is created, and the CGLPixelFormatObj. - */ -bool -apple_glx_create_context(void **ptr, Display * dpy, int screen, - const void *mode, void *sharedContext, - int *errorptr, bool * x11errorptr) -{ - struct apple_glx_context *ac; - struct apple_glx_context *sharedac = sharedContext; - CGLError error; - - *ptr = NULL; - - ac = malloc(sizeof *ac); - - if (NULL == ac) { - *errorptr = BadAlloc; - *x11errorptr = true; - return true; - } - - if (sharedac && !is_context_valid(sharedac)) { - *errorptr = GLXBadContext; - *x11errorptr = false; - return true; - } - - ac->context_obj = NULL; - ac->pixel_format_obj = NULL; - ac->drawable = NULL; - ac->thread_id = pthread_self(); - ac->screen = screen; - ac->double_buffered = false; - ac->uses_stereo = false; - ac->need_update = false; - ac->is_current = false; - ac->made_current = false; - ac->last_surface_window = None; - - apple_visual_create_pfobj(&ac->pixel_format_obj, mode, - &ac->double_buffered, &ac->uses_stereo, - /*offscreen */ false); - - error = apple_cgl.create_context(ac->pixel_format_obj, - sharedac ? sharedac->context_obj : NULL, - &ac->context_obj); - - - if (error) { - (void) apple_cgl.destroy_pixel_format(ac->pixel_format_obj); - - free(ac); - - if (kCGLBadMatch == error) { - *errorptr = BadMatch; - *x11errorptr = true; - } - else { - *errorptr = GLXBadContext; - *x11errorptr = false; - } - - if (getenv("LIBGL_DIAGNOSTIC")) - fprintf(stderr, "error: %s\n", apple_cgl.error_string(error)); - - return true; - } - - /* The context creation succeeded, so we can link in the new context. */ - lock_context_list(); - - if (context_list) - context_list->previous = ac; - - ac->previous = NULL; - ac->next = context_list; - context_list = ac; - - *ptr = ac; - - apple_glx_diagnostic("%s: ac %p ac->context_obj %p\n", - __func__, (void *) ac, (void *) ac->context_obj); - - unlock_context_list(); - - return false; -} - -void -apple_glx_destroy_context(void **ptr, Display * dpy) -{ - struct apple_glx_context *ac = *ptr; - - if (NULL == ac) - return; - - apple_glx_diagnostic("%s: ac %p ac->context_obj %p\n", - __func__, (void *) ac, (void *) ac->context_obj); - - if (apple_cgl.get_current_context() == ac->context_obj) { - apple_glx_diagnostic("%s: context ac->context_obj %p " - "is still current!\n", __func__, - (void *) ac->context_obj); - if (apple_cgl.set_current_context(NULL)) { - abort(); - } - } - - /* Remove ac from the context_list as soon as possible. */ - lock_context_list(); - - if (ac->previous) { - ac->previous->next = ac->next; - } - else { - context_list = ac->next; - } - - if (ac->next) { - ac->next->previous = ac->previous; - } - - unlock_context_list(); - - - if (apple_cgl.clear_drawable(ac->context_obj)) { - fprintf(stderr, "error: while clearing drawable!\n"); - abort(); - } - - /* - * This potentially causes surface_notify_handler to be called in - * apple_glx.c... - * We can NOT have a lock held at this point. It would result in - * an abort due to an attempted deadlock. This is why we earlier - * removed the ac pointer from the double-linked list. - */ - if (ac->drawable) { - ac->drawable->destroy(ac->drawable); - } - - if (apple_cgl.destroy_pixel_format(ac->pixel_format_obj)) { - fprintf(stderr, "error: destroying pixel format in %s\n", __func__); - abort(); - } - - if (apple_cgl.destroy_context(ac->context_obj)) { - fprintf(stderr, "error: destroying context_obj in %s\n", __func__); - abort(); - } - - free(ac); - - *ptr = NULL; - - apple_glx_garbage_collect_drawables(dpy); -} - - -/* Return true if an error occured. */ -bool -apple_glx_make_current_context(Display * dpy, void *oldptr, void *ptr, - GLXDrawable drawable) -{ - struct apple_glx_context *oldac = oldptr; - struct apple_glx_context *ac = ptr; - struct apple_glx_drawable *newagd = NULL; - CGLError cglerr; - bool same_drawable = false; - -#if 0 - apple_glx_diagnostic("%s: oldac %p ac %p drawable 0x%lx\n", - __func__, (void *) oldac, (void *) ac, drawable); - - apple_glx_diagnostic("%s: oldac->context_obj %p ac->context_obj %p\n", - __func__, - (void *) (oldac ? oldac->context_obj : NULL), - (void *) (ac ? ac->context_obj : NULL)); -#endif - - /* This a common path for GLUT and other apps, so special case it. */ - if (ac && ac->drawable && ac->drawable->drawable == drawable) { - same_drawable = true; - - if (ac->is_current) - return false; - } - - /* Reset the is_current state of the old context, if non-NULL. */ - if (oldac && (ac != oldac)) - oldac->is_current = false; - - if (NULL == ac) { - /*Clear the current context for this thread. */ - apple_cgl.set_current_context(NULL); - - if (oldac) { - oldac->is_current = false; - - if (oldac->drawable) { - oldac->drawable->destroy(oldac->drawable); - oldac->drawable = NULL; - } - - /* Invalidate this to prevent surface recreation. */ - oldac->last_surface_window = None; - } - - return false; - } - - if (None == drawable) { - bool error = false; - - /* Clear the current drawable for this context_obj. */ - - if (apple_cgl.set_current_context(ac->context_obj)) - error = true; - - if (apple_cgl.clear_drawable(ac->context_obj)) - error = true; - - if (ac->drawable) { - ac->drawable->destroy(ac->drawable); - ac->drawable = NULL; - } - - /* Invalidate this to prevent surface recreation. */ - ac->last_surface_window = None; - - apple_glx_diagnostic("%s: drawable is None, error is: %d\n", - __func__, error); - - return error; - } - - /* This is an optimisation to avoid searching for the current drawable. */ - if (ac->drawable && ac->drawable->drawable == drawable) { - newagd = ac->drawable; - } - else { - /* Find the drawable if possible, and retain a reference to it. */ - newagd = - apple_glx_drawable_find(drawable, APPLE_GLX_DRAWABLE_REFERENCE); - } - - /* - * Try to destroy the old drawable, so long as the new one - * isn't the old. - */ - if (ac->drawable && !same_drawable) { - ac->drawable->destroy(ac->drawable); - ac->drawable = NULL; - } - - if (NULL == newagd) { - if (apple_glx_surface_create(dpy, ac->screen, drawable, &newagd)) - return true; - - /* The drawable is referenced once by apple_glx_surface_create. */ - - /* - * FIXME: We actually need 2 references to prevent premature surface - * destruction. The problem is that the surface gets destroyed in - * the case of the context being reused for another window, and - * we then lose the surface contents. Wait for destruction of a - * window to destroy a surface. - * - * Note: this may leave around surfaces we don't want around, if - * say we are using X for raster drawing after OpenGL rendering, - * but it will be compatible with the old libGL's behavior. - * - * Someday the X11 and OpenGL rendering must be unified at some - * layer. I suspect we can do that via shared memory and - * multiple threads in the X server (1 for each context created - * by a client). This would also allow users to render from - * multiple clients to the same OpenGL surface. In fact it could - * all be OpenGL. - * - */ - newagd->reference(newagd); - - /* Save the new drawable with the context structure. */ - ac->drawable = newagd; - } - else { - /* We are reusing an existing drawable structure. */ - - if (same_drawable) { - assert(ac->drawable == newagd); - /* The drawable_find above retained a reference for us. */ - } - else { - ac->drawable = newagd; - } - } - - /* - * Avoid this costly path if this is the same drawable and the - * context is already current. - */ - - if (same_drawable && ac->is_current) { - apple_glx_diagnostic("%s: same_drawable and ac->is_current\n"); - return false; - } - - cglerr = apple_cgl.set_current_context(ac->context_obj); - - if (kCGLNoError != cglerr) { - fprintf(stderr, "set current error: %s\n", - apple_cgl.error_string(cglerr)); - return true; - } - - ac->is_current = true; - - assert(NULL != ac->context_obj); - assert(NULL != ac->drawable); - - ac->thread_id = pthread_self(); - - /* This will be set if the pending_destroy code indicates it should be: */ - ac->last_surface_window = None; - - switch (ac->drawable->type) { - case APPLE_GLX_DRAWABLE_PBUFFER: - case APPLE_GLX_DRAWABLE_SURFACE: - case APPLE_GLX_DRAWABLE_PIXMAP: - if (ac->drawable->callbacks.make_current) { - if (ac->drawable->callbacks.make_current(ac, ac->drawable)) - return true; - } - break; - - default: - fprintf(stderr, "internal error: invalid drawable type: %d\n", - ac->drawable->type); - abort(); - } - - return false; -} - -bool -apple_glx_is_current_drawable(Display * dpy, void *ptr, GLXDrawable drawable) -{ - struct apple_glx_context *ac = ptr; - - if (ac->drawable && ac->drawable->drawable == drawable) { - return true; - } - else if (NULL == ac->drawable && None != ac->last_surface_window) { - apple_glx_context_update(dpy, ac); - - return (ac->drawable && ac->drawable->drawable == drawable); - } - - return false; -} - -bool -apple_glx_copy_context(void *currentptr, void *srcptr, void *destptr, - unsigned long mask, int *errorptr, bool * x11errorptr) -{ - struct apple_glx_context *src, *dest; - CGLError err; - - src = srcptr; - dest = destptr; - - if (src->screen != dest->screen) { - *errorptr = BadMatch; - *x11errorptr = true; - return true; - } - - if (dest == currentptr || dest->is_current) { - *errorptr = BadAccess; - *x11errorptr = true; - return true; - } - - /* - * If srcptr is the current context then we should do an implicit glFlush. - */ - if (currentptr == srcptr) - glFlush(); - - err = apple_cgl.copy_context(src->context_obj, dest->context_obj, - (GLbitfield) mask); - - if (kCGLNoError != err) { - *errorptr = GLXBadContext; - *x11errorptr = false; - return true; - } - - return false; -} - -/* - * The value returned is the total number of contexts set to update. - * It's meant for debugging/introspection. - */ -int -apple_glx_context_surface_changed(unsigned int uid, pthread_t caller) -{ - struct apple_glx_context *ac; - int updated = 0; - - lock_context_list(); - - for (ac = context_list; ac; ac = ac->next) { - if (ac->drawable && APPLE_GLX_DRAWABLE_SURFACE == ac->drawable->type - && ac->drawable->types.surface.uid == uid) { - - if (caller == ac->thread_id) { - apple_glx_diagnostic("caller is the same thread for uid %u\n", - uid); - - xp_update_gl_context(ac->context_obj); - } - else { - ac->need_update = true; - ++updated; - } - } - } - - unlock_context_list(); - - return updated; -} - -void -apple_glx_context_update(Display * dpy, void *ptr) -{ - struct apple_glx_context *ac = ptr; - - if (NULL == ac->drawable && None != ac->last_surface_window) { - bool failed; - - /* Attempt to recreate the surface for a destroyed drawable. */ - failed = - apple_glx_make_current_context(dpy, ac, ac, ac->last_surface_window); - - apple_glx_diagnostic("%s: surface recreation failed? %s\n", __func__, - failed ? "YES" : "NO"); - } - - if (ac->need_update) { - xp_update_gl_context(ac->context_obj); - ac->need_update = false; - - apple_glx_diagnostic("%s: updating context %p\n", __func__, ptr); - } - - if (ac->drawable && APPLE_GLX_DRAWABLE_SURFACE == ac->drawable->type - && ac->drawable->types.surface.pending_destroy) { - apple_glx_diagnostic("%s: clearing drawable %p\n", __func__, ptr); - apple_cgl.clear_drawable(ac->context_obj); - - if (ac->drawable) { - struct apple_glx_drawable *d; - - apple_glx_diagnostic("%s: attempting to destroy drawable %p\n", - __func__, ptr); - apple_glx_diagnostic("%s: ac->drawable->drawable is 0x%lx\n", - __func__, ac->drawable->drawable); - - d = ac->drawable; - - ac->last_surface_window = d->drawable; - - ac->drawable = NULL; - - /* - * This will destroy the surface drawable if there are - * no references to it. - * It also subtracts 1 from the reference_count. - * If there are references to it, then it's probably made - * current in another context. - */ - d->destroy(d); - } - } -} - -bool -apple_glx_context_uses_stereo(void *ptr) -{ - struct apple_glx_context *ac = ptr; - - return ac->uses_stereo; -} |