13464ebd5Sriastradh/*
23464ebd5Sriastradh Copyright (c) 2008, 2009 Apple Inc.
33464ebd5Sriastradh
43464ebd5Sriastradh Permission is hereby granted, free of charge, to any person
53464ebd5Sriastradh obtaining a copy of this software and associated documentation files
63464ebd5Sriastradh (the "Software"), to deal in the Software without restriction,
73464ebd5Sriastradh including without limitation the rights to use, copy, modify, merge,
83464ebd5Sriastradh publish, distribute, sublicense, and/or sell copies of the Software,
93464ebd5Sriastradh and to permit persons to whom the Software is furnished to do so,
103464ebd5Sriastradh subject to the following conditions:
113464ebd5Sriastradh
123464ebd5Sriastradh The above copyright notice and this permission notice shall be
133464ebd5Sriastradh included in all copies or substantial portions of the Software.
143464ebd5Sriastradh
153464ebd5Sriastradh THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
163464ebd5Sriastradh EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
173464ebd5Sriastradh MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
183464ebd5Sriastradh NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
193464ebd5Sriastradh HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
203464ebd5Sriastradh WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
213464ebd5Sriastradh OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
223464ebd5Sriastradh DEALINGS IN THE SOFTWARE.
233464ebd5Sriastradh
243464ebd5Sriastradh Except as contained in this notice, the name(s) of the above
253464ebd5Sriastradh copyright holders shall not be used in advertising or otherwise to
263464ebd5Sriastradh promote the sale, use or other dealings in this Software without
273464ebd5Sriastradh prior written authorization.
283464ebd5Sriastradh*/
293464ebd5Sriastradh
303464ebd5Sriastradh#include <stdbool.h>
313464ebd5Sriastradh#include <stdio.h>
323464ebd5Sriastradh#include <stdlib.h>
333464ebd5Sriastradh#include <assert.h>
343464ebd5Sriastradh#include <pthread.h>
35af69d88dSmrg#include <string.h>
363464ebd5Sriastradh#include "apple_glx.h"
373464ebd5Sriastradh#include "apple_glx_context.h"
383464ebd5Sriastradh#include "apple_glx_drawable.h"
393464ebd5Sriastradh#include "appledri.h"
403464ebd5Sriastradh
413464ebd5Sriastradhstatic pthread_mutex_t drawables_lock = PTHREAD_MUTEX_INITIALIZER;
423464ebd5Sriastradhstatic struct apple_glx_drawable *drawables_list = NULL;
433464ebd5Sriastradh
443464ebd5Sriastradhstatic void
453464ebd5Sriastradhlock_drawables_list(void)
463464ebd5Sriastradh{
473464ebd5Sriastradh   int err;
483464ebd5Sriastradh
493464ebd5Sriastradh   err = pthread_mutex_lock(&drawables_lock);
503464ebd5Sriastradh
513464ebd5Sriastradh   if (err) {
52af69d88dSmrg      fprintf(stderr, "pthread_mutex_lock failure in %s: %s\n",
53af69d88dSmrg              __func__, strerror(err));
543464ebd5Sriastradh      abort();
553464ebd5Sriastradh   }
563464ebd5Sriastradh}
573464ebd5Sriastradh
583464ebd5Sriastradhstatic void
593464ebd5Sriastradhunlock_drawables_list(void)
603464ebd5Sriastradh{
613464ebd5Sriastradh   int err;
623464ebd5Sriastradh
633464ebd5Sriastradh   err = pthread_mutex_unlock(&drawables_lock);
643464ebd5Sriastradh
653464ebd5Sriastradh   if (err) {
66af69d88dSmrg      fprintf(stderr, "pthread_mutex_unlock failure in %s: %s\n",
67af69d88dSmrg              __func__, strerror(err));
683464ebd5Sriastradh      abort();
693464ebd5Sriastradh   }
703464ebd5Sriastradh}
713464ebd5Sriastradh
723464ebd5Sriastradhstruct apple_glx_drawable *
733464ebd5Sriastradhapple_glx_find_drawable(Display * dpy, GLXDrawable drawable)
743464ebd5Sriastradh{
753464ebd5Sriastradh   struct apple_glx_drawable *i, *agd = NULL;
763464ebd5Sriastradh
773464ebd5Sriastradh   lock_drawables_list();
783464ebd5Sriastradh
793464ebd5Sriastradh   for (i = drawables_list; i; i = i->next) {
803464ebd5Sriastradh      if (i->drawable == drawable) {
813464ebd5Sriastradh         agd = i;
823464ebd5Sriastradh         break;
833464ebd5Sriastradh      }
843464ebd5Sriastradh   }
853464ebd5Sriastradh
863464ebd5Sriastradh   unlock_drawables_list();
873464ebd5Sriastradh
883464ebd5Sriastradh   return agd;
893464ebd5Sriastradh}
903464ebd5Sriastradh
913464ebd5Sriastradhstatic void
923464ebd5Sriastradhdrawable_lock(struct apple_glx_drawable *agd)
933464ebd5Sriastradh{
943464ebd5Sriastradh   int err;
953464ebd5Sriastradh
963464ebd5Sriastradh   err = pthread_mutex_lock(&agd->mutex);
973464ebd5Sriastradh
983464ebd5Sriastradh   if (err) {
99af69d88dSmrg      fprintf(stderr, "pthread_mutex_lock error: %s\n", strerror(err));
1003464ebd5Sriastradh      abort();
1013464ebd5Sriastradh   }
1023464ebd5Sriastradh}
1033464ebd5Sriastradh
1043464ebd5Sriastradhstatic void
1053464ebd5Sriastradhdrawable_unlock(struct apple_glx_drawable *d)
1063464ebd5Sriastradh{
1073464ebd5Sriastradh   int err;
1083464ebd5Sriastradh
1093464ebd5Sriastradh   err = pthread_mutex_unlock(&d->mutex);
1103464ebd5Sriastradh
1113464ebd5Sriastradh   if (err) {
112af69d88dSmrg      fprintf(stderr, "pthread_mutex_unlock error: %s\n", strerror(err));
1133464ebd5Sriastradh      abort();
1143464ebd5Sriastradh   }
1153464ebd5Sriastradh}
1163464ebd5Sriastradh
1173464ebd5Sriastradh
1183464ebd5Sriastradhstatic void
1193464ebd5Sriastradhreference_drawable(struct apple_glx_drawable *d)
1203464ebd5Sriastradh{
1213464ebd5Sriastradh   d->lock(d);
1223464ebd5Sriastradh   d->reference_count++;
1233464ebd5Sriastradh   d->unlock(d);
1243464ebd5Sriastradh}
1253464ebd5Sriastradh
1263464ebd5Sriastradhstatic void
1273464ebd5Sriastradhrelease_drawable(struct apple_glx_drawable *d)
1283464ebd5Sriastradh{
1293464ebd5Sriastradh   d->lock(d);
1303464ebd5Sriastradh   d->reference_count--;
1313464ebd5Sriastradh   d->unlock(d);
1323464ebd5Sriastradh}
1333464ebd5Sriastradh
1343464ebd5Sriastradh/* The drawables list must be locked prior to calling this. */
1353464ebd5Sriastradh/* Return true if the drawable was destroyed. */
1363464ebd5Sriastradhstatic bool
1373464ebd5Sriastradhdestroy_drawable(struct apple_glx_drawable *d)
1383464ebd5Sriastradh{
139af69d88dSmrg   int err;
1403464ebd5Sriastradh
1413464ebd5Sriastradh   d->lock(d);
1423464ebd5Sriastradh
1433464ebd5Sriastradh   if (d->reference_count > 0) {
1443464ebd5Sriastradh      d->unlock(d);
1453464ebd5Sriastradh      return false;
1463464ebd5Sriastradh   }
1473464ebd5Sriastradh
1483464ebd5Sriastradh   d->unlock(d);
1493464ebd5Sriastradh
1503464ebd5Sriastradh   if (d->previous) {
1513464ebd5Sriastradh      d->previous->next = d->next;
1523464ebd5Sriastradh   }
1533464ebd5Sriastradh   else {
1543464ebd5Sriastradh      /*
1553464ebd5Sriastradh       * The item must be at the head of the list, if it
1563464ebd5Sriastradh       * has no previous pointer.
1573464ebd5Sriastradh       */
1583464ebd5Sriastradh      drawables_list = d->next;
1593464ebd5Sriastradh   }
1603464ebd5Sriastradh
1613464ebd5Sriastradh   if (d->next)
1623464ebd5Sriastradh      d->next->previous = d->previous;
1633464ebd5Sriastradh
1643464ebd5Sriastradh   unlock_drawables_list();
1653464ebd5Sriastradh
1663464ebd5Sriastradh   if (d->callbacks.destroy) {
1673464ebd5Sriastradh      /*
1683464ebd5Sriastradh       * Warning: this causes other routines to be called (potentially)
1693464ebd5Sriastradh       * from surface_notify_handler.  It's probably best to not have
1703464ebd5Sriastradh       * any locks at this point locked.
1713464ebd5Sriastradh       */
1723464ebd5Sriastradh      d->callbacks.destroy(d->display, d);
1733464ebd5Sriastradh   }
1743464ebd5Sriastradh
1753464ebd5Sriastradh   apple_glx_diagnostic("%s: freeing %p\n", __func__, (void *) d);
1763464ebd5Sriastradh
177af69d88dSmrg   /* Stupid recursive locks */
178af69d88dSmrg   while (pthread_mutex_unlock(&d->mutex) == 0);
179af69d88dSmrg
180af69d88dSmrg   err = pthread_mutex_destroy(&d->mutex);
181af69d88dSmrg   if (err) {
182af69d88dSmrg      fprintf(stderr, "pthread_mutex_destroy error: %s\n", strerror(err));
183af69d88dSmrg      abort();
184af69d88dSmrg   }
185af69d88dSmrg
1863464ebd5Sriastradh   free(d);
1873464ebd5Sriastradh
1883464ebd5Sriastradh   /* So that the locks are balanced and the caller correctly unlocks. */
1893464ebd5Sriastradh   lock_drawables_list();
1903464ebd5Sriastradh
1913464ebd5Sriastradh   return true;
1923464ebd5Sriastradh}
1933464ebd5Sriastradh
1943464ebd5Sriastradh/*
1953464ebd5Sriastradh * This is typically called when a context is destroyed or the current
1963464ebd5Sriastradh * drawable is made None.
1973464ebd5Sriastradh */
1983464ebd5Sriastradhstatic bool
1993464ebd5Sriastradhdestroy_drawable_callback(struct apple_glx_drawable *d)
2003464ebd5Sriastradh{
2013464ebd5Sriastradh   bool result;
2023464ebd5Sriastradh
2033464ebd5Sriastradh   d->lock(d);
2043464ebd5Sriastradh
2053464ebd5Sriastradh   apple_glx_diagnostic("%s: %p ->reference_count before -- %d\n", __func__,
2063464ebd5Sriastradh                        (void *) d, d->reference_count);
2073464ebd5Sriastradh
2083464ebd5Sriastradh   d->reference_count--;
2093464ebd5Sriastradh
2103464ebd5Sriastradh   if (d->reference_count > 0) {
2113464ebd5Sriastradh      d->unlock(d);
2123464ebd5Sriastradh      return false;
2133464ebd5Sriastradh   }
2143464ebd5Sriastradh
2153464ebd5Sriastradh   d->unlock(d);
2163464ebd5Sriastradh
2173464ebd5Sriastradh   lock_drawables_list();
2183464ebd5Sriastradh
2193464ebd5Sriastradh   result = destroy_drawable(d);
2203464ebd5Sriastradh
2213464ebd5Sriastradh   unlock_drawables_list();
2223464ebd5Sriastradh
2233464ebd5Sriastradh   return result;
2243464ebd5Sriastradh}
2253464ebd5Sriastradh
2263464ebd5Sriastradhstatic bool
2273464ebd5Sriastradhis_pbuffer(struct apple_glx_drawable *d)
2283464ebd5Sriastradh{
2293464ebd5Sriastradh   return APPLE_GLX_DRAWABLE_PBUFFER == d->type;
2303464ebd5Sriastradh}
2313464ebd5Sriastradh
2323464ebd5Sriastradhstatic bool
2333464ebd5Sriastradhis_pixmap(struct apple_glx_drawable *d)
2343464ebd5Sriastradh{
2353464ebd5Sriastradh   return APPLE_GLX_DRAWABLE_PIXMAP == d->type;
2363464ebd5Sriastradh}
2373464ebd5Sriastradh
2383464ebd5Sriastradhstatic void
2393464ebd5Sriastradhcommon_init(Display * dpy, GLXDrawable drawable, struct apple_glx_drawable *d)
2403464ebd5Sriastradh{
2413464ebd5Sriastradh   int err;
2423464ebd5Sriastradh   pthread_mutexattr_t attr;
2433464ebd5Sriastradh
2443464ebd5Sriastradh   d->display = dpy;
2453464ebd5Sriastradh   d->reference_count = 0;
2463464ebd5Sriastradh   d->drawable = drawable;
2473464ebd5Sriastradh   d->type = -1;
2483464ebd5Sriastradh
2493464ebd5Sriastradh   err = pthread_mutexattr_init(&attr);
2503464ebd5Sriastradh
2513464ebd5Sriastradh   if (err) {
252af69d88dSmrg      fprintf(stderr, "pthread_mutexattr_init error: %s\n", strerror(err));
2533464ebd5Sriastradh      abort();
2543464ebd5Sriastradh   }
2553464ebd5Sriastradh
2563464ebd5Sriastradh   /*
2573464ebd5Sriastradh    * There are some patterns that require a recursive mutex,
2583464ebd5Sriastradh    * when working with locks that protect the apple_glx_drawable,
2593464ebd5Sriastradh    * and reference functions like ->reference, and ->release.
2603464ebd5Sriastradh    */
2613464ebd5Sriastradh   err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
2623464ebd5Sriastradh
2633464ebd5Sriastradh   if (err) {
264af69d88dSmrg      fprintf(stderr, "error: setting pthread mutex type: %s\n", strerror(err));
2653464ebd5Sriastradh      abort();
2663464ebd5Sriastradh   }
2673464ebd5Sriastradh
2683464ebd5Sriastradh   err = pthread_mutex_init(&d->mutex, &attr);
2693464ebd5Sriastradh
2703464ebd5Sriastradh   if (err) {
271af69d88dSmrg      fprintf(stderr, "pthread_mutex_init error: %s\n", strerror(err));
2723464ebd5Sriastradh      abort();
2733464ebd5Sriastradh   }
2743464ebd5Sriastradh
2753464ebd5Sriastradh   (void) pthread_mutexattr_destroy(&attr);
2763464ebd5Sriastradh
2773464ebd5Sriastradh   d->lock = drawable_lock;
2783464ebd5Sriastradh   d->unlock = drawable_unlock;
2793464ebd5Sriastradh
2803464ebd5Sriastradh   d->reference = reference_drawable;
2813464ebd5Sriastradh   d->release = release_drawable;
2823464ebd5Sriastradh
2833464ebd5Sriastradh   d->destroy = destroy_drawable_callback;
2843464ebd5Sriastradh
2853464ebd5Sriastradh   d->is_pbuffer = is_pbuffer;
2863464ebd5Sriastradh   d->is_pixmap = is_pixmap;
2873464ebd5Sriastradh
2883464ebd5Sriastradh   d->width = -1;
2893464ebd5Sriastradh   d->height = -1;
2903464ebd5Sriastradh   d->row_bytes = 0;
2913464ebd5Sriastradh   d->path[0] = '\0';
2923464ebd5Sriastradh   d->fd = -1;
2933464ebd5Sriastradh   d->buffer = NULL;
2943464ebd5Sriastradh   d->buffer_length = 0;
2953464ebd5Sriastradh
2963464ebd5Sriastradh   d->previous = NULL;
2973464ebd5Sriastradh   d->next = NULL;
2983464ebd5Sriastradh}
2993464ebd5Sriastradh
3003464ebd5Sriastradhstatic void
3013464ebd5Sriastradhlink_tail(struct apple_glx_drawable *agd)
3023464ebd5Sriastradh{
3033464ebd5Sriastradh   lock_drawables_list();
3043464ebd5Sriastradh
3053464ebd5Sriastradh   /* Link the new drawable into the global list. */
3063464ebd5Sriastradh   agd->next = drawables_list;
3073464ebd5Sriastradh
3083464ebd5Sriastradh   if (drawables_list)
3093464ebd5Sriastradh      drawables_list->previous = agd;
3103464ebd5Sriastradh
3113464ebd5Sriastradh   drawables_list = agd;
3123464ebd5Sriastradh
3133464ebd5Sriastradh   unlock_drawables_list();
3143464ebd5Sriastradh}
3153464ebd5Sriastradh
3163464ebd5Sriastradh/*WARNING: this returns a locked and referenced object. */
3173464ebd5Sriastradhbool
3183464ebd5Sriastradhapple_glx_drawable_create(Display * dpy,
3193464ebd5Sriastradh                          int screen,
3203464ebd5Sriastradh                          GLXDrawable drawable,
3213464ebd5Sriastradh                          struct apple_glx_drawable **agdResult,
3223464ebd5Sriastradh                          struct apple_glx_drawable_callbacks *callbacks)
3233464ebd5Sriastradh{
3243464ebd5Sriastradh   struct apple_glx_drawable *d;
3253464ebd5Sriastradh
3263464ebd5Sriastradh   d = calloc(1, sizeof *d);
3273464ebd5Sriastradh
3283464ebd5Sriastradh   if (NULL == d) {
3293464ebd5Sriastradh      perror("malloc");
3303464ebd5Sriastradh      return true;
3313464ebd5Sriastradh   }
3323464ebd5Sriastradh
3333464ebd5Sriastradh   common_init(dpy, drawable, d);
3343464ebd5Sriastradh   d->type = callbacks->type;
3353464ebd5Sriastradh   d->callbacks = *callbacks;
3363464ebd5Sriastradh
3373464ebd5Sriastradh   d->reference(d);
3383464ebd5Sriastradh   d->lock(d);
3393464ebd5Sriastradh
3403464ebd5Sriastradh   link_tail(d);
3413464ebd5Sriastradh
3423464ebd5Sriastradh   apple_glx_diagnostic("%s: new drawable %p\n", __func__, (void *) d);
3433464ebd5Sriastradh
3443464ebd5Sriastradh   *agdResult = d;
3453464ebd5Sriastradh
3463464ebd5Sriastradh   return false;
3473464ebd5Sriastradh}
3483464ebd5Sriastradh
3493464ebd5Sriastradhstatic int error_count = 0;
3503464ebd5Sriastradh
3513464ebd5Sriastradhstatic int
3523464ebd5Sriastradherror_handler(Display * dpy, XErrorEvent * err)
3533464ebd5Sriastradh{
3543464ebd5Sriastradh   if (err->error_code == BadWindow) {
3553464ebd5Sriastradh      ++error_count;
3563464ebd5Sriastradh   }
3573464ebd5Sriastradh
3583464ebd5Sriastradh   return 0;
3593464ebd5Sriastradh}
3603464ebd5Sriastradh
3613464ebd5Sriastradhvoid
3623464ebd5Sriastradhapple_glx_garbage_collect_drawables(Display * dpy)
3633464ebd5Sriastradh{
3643464ebd5Sriastradh   struct apple_glx_drawable *d, *dnext;
3653464ebd5Sriastradh   Window root;
3663464ebd5Sriastradh   int x, y;
3673464ebd5Sriastradh   unsigned int width, height, bd, depth;
3683464ebd5Sriastradh   int (*old_handler) (Display *, XErrorEvent *);
3693464ebd5Sriastradh
3703464ebd5Sriastradh
3713464ebd5Sriastradh   if (NULL == drawables_list)
3723464ebd5Sriastradh      return;
3733464ebd5Sriastradh
3743464ebd5Sriastradh   old_handler = XSetErrorHandler(error_handler);
3753464ebd5Sriastradh
3763464ebd5Sriastradh   XSync(dpy, False);
3773464ebd5Sriastradh
3783464ebd5Sriastradh   lock_drawables_list();
3793464ebd5Sriastradh
3803464ebd5Sriastradh   for (d = drawables_list; d;) {
3813464ebd5Sriastradh      dnext = d->next;
3823464ebd5Sriastradh
3833464ebd5Sriastradh      d->lock(d);
3843464ebd5Sriastradh
3853464ebd5Sriastradh      if (d->reference_count > 0) {
3863464ebd5Sriastradh         /*
3873464ebd5Sriastradh          * Skip this, because some context still retains a reference
3883464ebd5Sriastradh          * to the drawable.
3893464ebd5Sriastradh          */
3903464ebd5Sriastradh         d->unlock(d);
3913464ebd5Sriastradh         d = dnext;
3923464ebd5Sriastradh         continue;
3933464ebd5Sriastradh      }
3943464ebd5Sriastradh
3953464ebd5Sriastradh      d->unlock(d);
3963464ebd5Sriastradh
3973464ebd5Sriastradh      error_count = 0;
3983464ebd5Sriastradh
3993464ebd5Sriastradh      /*
4003464ebd5Sriastradh       * Mesa uses XGetWindowAttributes, but some of these things are
4013464ebd5Sriastradh       * most definitely not Windows, and that's against the rules.
4023464ebd5Sriastradh       * XGetGeometry on the other hand is legal with a Pixmap and Window.
4033464ebd5Sriastradh       */
4043464ebd5Sriastradh      XGetGeometry(dpy, d->drawable, &root, &x, &y, &width, &height, &bd,
4053464ebd5Sriastradh                   &depth);
4063464ebd5Sriastradh
4073464ebd5Sriastradh      if (error_count > 0) {
4083464ebd5Sriastradh         /*
4093464ebd5Sriastradh          * Note: this may not actually destroy the drawable.
4103464ebd5Sriastradh          * If another context retains a reference to the drawable
4113464ebd5Sriastradh          * after the reference count test above.
4123464ebd5Sriastradh          */
4133464ebd5Sriastradh         (void) destroy_drawable(d);
4143464ebd5Sriastradh         error_count = 0;
4153464ebd5Sriastradh      }
4163464ebd5Sriastradh
4173464ebd5Sriastradh      d = dnext;
4183464ebd5Sriastradh   }
4193464ebd5Sriastradh
4203464ebd5Sriastradh   XSetErrorHandler(old_handler);
4213464ebd5Sriastradh
4223464ebd5Sriastradh   unlock_drawables_list();
4233464ebd5Sriastradh}
4243464ebd5Sriastradh
4253464ebd5Sriastradhunsigned int
4263464ebd5Sriastradhapple_glx_get_drawable_count(void)
4273464ebd5Sriastradh{
4283464ebd5Sriastradh   unsigned int result = 0;
4293464ebd5Sriastradh   struct apple_glx_drawable *d;
4303464ebd5Sriastradh
4313464ebd5Sriastradh   lock_drawables_list();
4323464ebd5Sriastradh
4333464ebd5Sriastradh   for (d = drawables_list; d; d = d->next)
4343464ebd5Sriastradh      ++result;
4353464ebd5Sriastradh
4363464ebd5Sriastradh   unlock_drawables_list();
4373464ebd5Sriastradh
4383464ebd5Sriastradh   return result;
4393464ebd5Sriastradh}
4403464ebd5Sriastradh
4413464ebd5Sriastradhstruct apple_glx_drawable *
4423464ebd5Sriastradhapple_glx_drawable_find_by_type(GLXDrawable drawable, int type, int flags)
4433464ebd5Sriastradh{
4443464ebd5Sriastradh   struct apple_glx_drawable *d;
4453464ebd5Sriastradh
4463464ebd5Sriastradh   lock_drawables_list();
4473464ebd5Sriastradh
4483464ebd5Sriastradh   for (d = drawables_list; d; d = d->next) {
4493464ebd5Sriastradh      if (d->type == type && d->drawable == drawable) {
4503464ebd5Sriastradh         if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
4513464ebd5Sriastradh            d->reference(d);
4523464ebd5Sriastradh
4533464ebd5Sriastradh         if (flags & APPLE_GLX_DRAWABLE_LOCK)
4543464ebd5Sriastradh            d->lock(d);
4553464ebd5Sriastradh
4563464ebd5Sriastradh         unlock_drawables_list();
4573464ebd5Sriastradh
4583464ebd5Sriastradh         return d;
4593464ebd5Sriastradh      }
4603464ebd5Sriastradh   }
4613464ebd5Sriastradh
4623464ebd5Sriastradh   unlock_drawables_list();
4633464ebd5Sriastradh
4643464ebd5Sriastradh   return NULL;
4653464ebd5Sriastradh}
4663464ebd5Sriastradh
4673464ebd5Sriastradhstruct apple_glx_drawable *
4683464ebd5Sriastradhapple_glx_drawable_find(GLXDrawable drawable, int flags)
4693464ebd5Sriastradh{
4703464ebd5Sriastradh   struct apple_glx_drawable *d;
4713464ebd5Sriastradh
4723464ebd5Sriastradh   lock_drawables_list();
4733464ebd5Sriastradh
4743464ebd5Sriastradh   for (d = drawables_list; d; d = d->next) {
4753464ebd5Sriastradh      if (d->drawable == drawable) {
4763464ebd5Sriastradh         if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
4773464ebd5Sriastradh            d->reference(d);
4783464ebd5Sriastradh
4793464ebd5Sriastradh         if (flags & APPLE_GLX_DRAWABLE_LOCK)
4803464ebd5Sriastradh            d->lock(d);
4813464ebd5Sriastradh
4823464ebd5Sriastradh         unlock_drawables_list();
4833464ebd5Sriastradh
4843464ebd5Sriastradh         return d;
4853464ebd5Sriastradh      }
4863464ebd5Sriastradh   }
4873464ebd5Sriastradh
4883464ebd5Sriastradh   unlock_drawables_list();
4893464ebd5Sriastradh
4903464ebd5Sriastradh   return NULL;
4913464ebd5Sriastradh}
4923464ebd5Sriastradh
4933464ebd5Sriastradh/* Return true if the type is valid for the drawable. */
4943464ebd5Sriastradhbool
4953464ebd5Sriastradhapple_glx_drawable_destroy_by_type(Display * dpy,
4963464ebd5Sriastradh                                   GLXDrawable drawable, int type)
4973464ebd5Sriastradh{
4983464ebd5Sriastradh   struct apple_glx_drawable *d;
4993464ebd5Sriastradh
5003464ebd5Sriastradh   lock_drawables_list();
5013464ebd5Sriastradh
5023464ebd5Sriastradh   for (d = drawables_list; d; d = d->next) {
5033464ebd5Sriastradh      if (drawable == d->drawable && type == d->type) {
5043464ebd5Sriastradh         /*
5053464ebd5Sriastradh          * The user has requested that we destroy this resource.
5063464ebd5Sriastradh          * However, there may be references in the contexts to it, so
5073464ebd5Sriastradh          * release it, and call destroy_drawable which doesn't destroy
5083464ebd5Sriastradh          * if the reference_count is > 0.
5093464ebd5Sriastradh          */
5103464ebd5Sriastradh         d->release(d);
5113464ebd5Sriastradh
5123464ebd5Sriastradh         apple_glx_diagnostic("%s d->reference_count %d\n",
5133464ebd5Sriastradh                              __func__, d->reference_count);
5143464ebd5Sriastradh
5153464ebd5Sriastradh         destroy_drawable(d);
5163464ebd5Sriastradh         unlock_drawables_list();
5173464ebd5Sriastradh         return true;
5183464ebd5Sriastradh      }
5193464ebd5Sriastradh   }
5203464ebd5Sriastradh
5213464ebd5Sriastradh   unlock_drawables_list();
5223464ebd5Sriastradh
5233464ebd5Sriastradh   return false;
5243464ebd5Sriastradh}
5253464ebd5Sriastradh
5263464ebd5Sriastradhstruct apple_glx_drawable *
5273464ebd5Sriastradhapple_glx_drawable_find_by_uid(unsigned int uid, int flags)
5283464ebd5Sriastradh{
5293464ebd5Sriastradh   struct apple_glx_drawable *d;
5303464ebd5Sriastradh
5313464ebd5Sriastradh   lock_drawables_list();
5323464ebd5Sriastradh
5333464ebd5Sriastradh   for (d = drawables_list; d; d = d->next) {
5343464ebd5Sriastradh      /* Only surfaces have a uid. */
5353464ebd5Sriastradh      if (APPLE_GLX_DRAWABLE_SURFACE == d->type) {
5363464ebd5Sriastradh         if (d->types.surface.uid == uid) {
5373464ebd5Sriastradh            if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
5383464ebd5Sriastradh               d->reference(d);
5393464ebd5Sriastradh
5403464ebd5Sriastradh            if (flags & APPLE_GLX_DRAWABLE_LOCK)
5413464ebd5Sriastradh               d->lock(d);
5423464ebd5Sriastradh
5433464ebd5Sriastradh            unlock_drawables_list();
5443464ebd5Sriastradh
5453464ebd5Sriastradh            return d;
5463464ebd5Sriastradh         }
5473464ebd5Sriastradh      }
5483464ebd5Sriastradh   }
5493464ebd5Sriastradh
5503464ebd5Sriastradh   unlock_drawables_list();
5513464ebd5Sriastradh
5523464ebd5Sriastradh   return NULL;
5533464ebd5Sriastradh}
554