1ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston/*
2ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston Copyright (c) 2009 Apple Inc.
3ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
4ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston Permission is hereby granted, free of charge, to any person
5ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston obtaining a copy of this software and associated documentation files
6ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston (the "Software"), to deal in the Software without restriction,
7ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston including without limitation the rights to use, copy, modify, merge,
8ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston publish, distribute, sublicense, and/or sell copies of the Software,
9ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston and to permit persons to whom the Software is furnished to do so,
10ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston subject to the following conditions:
11ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
12ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston The above copyright notice and this permission notice shall be
13ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston included in all copies or substantial portions of the Software.
14ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
15ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
19ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston DEALINGS IN THE SOFTWARE.
23ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
24ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston Except as contained in this notice, the name(s) of the above
25ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston copyright holders shall not be used in advertising or otherwise to
26ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston promote the sale, use or other dealings in this Software without
27ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston prior written authorization.
28ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston*/
29ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston#include <assert.h>
30ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston#include "glxclient.h"
31ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston#include "apple_glx.h"
32ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston#include "appledri.h"
33ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston#include "apple_glx_drawable.h"
34ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
35ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic bool surface_make_current(struct apple_glx_context *ac,
36ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                                 struct apple_glx_drawable *d);
37ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
38ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic void surface_destroy(Display * dpy, struct apple_glx_drawable *d);
39ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
40ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
41ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic struct apple_glx_drawable_callbacks callbacks = {
42ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   .type = APPLE_GLX_DRAWABLE_SURFACE,
43ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   .make_current = surface_make_current,
44ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   .destroy = surface_destroy
45ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston};
46ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
47ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic void
48ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonupdate_viewport_and_scissor(Display * dpy, GLXDrawable drawable)
49ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
50ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   Window root;
51ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   int x, y;
52ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   unsigned int width = 0, height = 0, bd, depth;
53ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
54ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth);
55ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
569f2abbee6215d89e48b7fe042f8a905997f5c232Jeremy Huddleston   apple_glapi_oglfw_viewport_scissor(0, 0, width, height);
57ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
58ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
59ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic bool
60ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonsurface_make_current(struct apple_glx_context *ac,
61ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                     struct apple_glx_drawable *d)
62ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
63ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   struct apple_glx_surface *s = &d->types.surface;
64ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   xp_error error;
65ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
66ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   assert(APPLE_GLX_DRAWABLE_SURFACE == d->type);
67ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
68ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   apple_glx_diagnostic("%s: ac->context_obj %p s->surface_id %u\n",
69ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                        __func__, (void *) ac->context_obj, s->surface_id);
70ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
71ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   error = xp_attach_gl_context(ac->context_obj, s->surface_id);
72ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
73ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (error) {
74ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      fprintf(stderr, "error: xp_attach_gl_context returned: %d\n", error);
75ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      return true;
76ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
77ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
78ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
79ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (!ac->made_current) {
80ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      /*
81ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * The first time a new context is made current the glViewport
82ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * and glScissor should be updated.
83ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       */
84ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      update_viewport_and_scissor(ac->drawable->display,
85ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                                  ac->drawable->drawable);
86ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      ac->made_current = true;
87ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
88ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
89ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   apple_glx_diagnostic("%s: drawable 0x%lx\n", __func__, d->drawable);
90ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
91ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   return false;
92ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
93ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
94ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic void
95ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonsurface_destroy(Display * dpy, struct apple_glx_drawable *d)
96ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
97ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   struct apple_glx_surface *s = &d->types.surface;
98ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
99ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   apple_glx_diagnostic("%s: s->surface_id %u\n", __func__, s->surface_id);
100ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
101ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   xp_error error = xp_destroy_surface(s->surface_id);
102ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
103ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (error) {
104ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      fprintf(stderr, "xp_destroy_surface error: %d\n", (int) error);
105ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
106ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
107ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   /*
108ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston    * Check if this surface destroy came from the surface being destroyed
109ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston    * on the server.  If s->pending_destroy is true, then it did, and
110ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston    * we don't want to try to destroy the surface on the server.
111ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston    */
112ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (!s->pending_destroy) {
113ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      /*
114ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * Warning: this causes other routines to be called (potentially)
115ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * from surface_notify_handler.  It's probably best to not have
116ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * any locks at this point locked.
117ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       */
118ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      XAppleDRIDestroySurface(d->display, DefaultScreen(d->display),
119ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                              d->drawable);
120ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
121ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      apple_glx_diagnostic
122ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston         ("%s: destroyed a surface for drawable 0x%lx uid %u\n", __func__,
123ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston          d->drawable, s->uid);
124ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
125ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
126ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
127ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston/* Return true if an error occured. */
128ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonstatic bool
129ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestoncreate_surface(Display * dpy, int screen, struct apple_glx_drawable *d)
130ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
131ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   struct apple_glx_surface *s = &d->types.surface;
132ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   unsigned int key[2];
133ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   xp_client_id id;
134ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
135ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   id = apple_glx_get_client_id();
136ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (0 == id)
137ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      return true;
138ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
139ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   assert(None != d->drawable);
140ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
141ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   s->pending_destroy = false;
142ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
143ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (XAppleDRICreateSurface(dpy, screen, d->drawable, id, key, &s->uid)) {
144ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      xp_error error;
145ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
146ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      error = xp_import_surface(key, &s->surface_id);
147ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
148ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      if (error) {
149ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston         fprintf(stderr, "error: xp_import_surface returned: %d\n", error);
150ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston         return true;
151ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      }
152ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
153ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      apple_glx_diagnostic("%s: created a surface for drawable 0x%lx"
154ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                           " with uid %u\n", __func__, d->drawable, s->uid);
155ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      return false;             /*success */
156ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
157ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
158ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   return true;                 /* unable to create a surface. */
159ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
160ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
161ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston/* Return true if an error occured. */
162ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston/* This returns a referenced object via resultptr. */
163ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonbool
164ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonapple_glx_surface_create(Display * dpy, int screen,
165ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                         GLXDrawable drawable,
166ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                         struct apple_glx_drawable ** resultptr)
167ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
168ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   struct apple_glx_drawable *d;
169ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
170ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (apple_glx_drawable_create(dpy, screen, drawable, &d, &callbacks))
171ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      return true;
172ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
173ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   /* apple_glx_drawable_create creates a locked and referenced object. */
174ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
175ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (create_surface(dpy, screen, d)) {
176ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      d->unlock(d);
177ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      d->destroy(d);
178ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      return true;
179ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
180ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
181ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   *resultptr = d;
182ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
183ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   d->unlock(d);
184ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
185ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   return false;
186ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
187ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
188ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston/*
189ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * All surfaces are reference counted, and surfaces are only created
190ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * when the window is made current.  When all contexts no longer reference
191ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * a surface drawable the apple_glx_drawable gets destroyed, and thus
192ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * its surface is destroyed.
193ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston *
194ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * However we can make the destruction occur a bit sooner by setting
195ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * pending_destroy, which is then checked for in glViewport by
196ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston * apple_glx_context_update.
197ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston */
198ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonvoid
199ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddlestonapple_glx_surface_destroy(unsigned int uid)
200ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston{
201ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   struct apple_glx_drawable *d;
202ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
203ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   d = apple_glx_drawable_find_by_uid(uid, APPLE_GLX_DRAWABLE_REFERENCE
204ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston                                      | APPLE_GLX_DRAWABLE_LOCK);
205ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston
206ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   if (d) {
207ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      d->types.surface.pending_destroy = true;
208ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      d->release(d);
209c60ffd2840036af1ea6f2b6c6e1e9014bb8e2c34Jonas Maebe
210ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston      /*
211ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * We release 2 references to the surface.  One was acquired by
212ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * the find, and the other was leftover from a context, or
213ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * the surface being displayed, so the destroy() will decrease it
214ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * once more.
215ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       *
216ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * If the surface is in a context, it will take one d->destroy(d);
217ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * to actually destroy it when the pending_destroy is processed
218ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       * by a glViewport callback (see apple_glx_context_update()).
219ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston       */
220d65bd195ecbd6623b962a3c98725a484ef2791a8Jeremy Huddleston      if (!d->destroy(d)) {
221d65bd195ecbd6623b962a3c98725a484ef2791a8Jeremy Huddleston          /* apple_glx_drawable_find_by_uid returns a locked drawable */
222d65bd195ecbd6623b962a3c98725a484ef2791a8Jeremy Huddleston          d->unlock(d);
223d65bd195ecbd6623b962a3c98725a484ef2791a8Jeremy Huddleston      }
224ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston   }
225ad503c41557606d15b0420c824369456f6d20a8fJeremy Huddleston}
226