1848b8605Smrg/*
2848b8605Smrg Copyright (c) 2009 Apple Inc.
3848b8605Smrg
4848b8605Smrg Permission is hereby granted, free of charge, to any person
5848b8605Smrg obtaining a copy of this software and associated documentation files
6848b8605Smrg (the "Software"), to deal in the Software without restriction,
7848b8605Smrg including without limitation the rights to use, copy, modify, merge,
8848b8605Smrg publish, distribute, sublicense, and/or sell copies of the Software,
9848b8605Smrg and to permit persons to whom the Software is furnished to do so,
10848b8605Smrg subject to the following conditions:
11848b8605Smrg
12848b8605Smrg The above copyright notice and this permission notice shall be
13848b8605Smrg included in all copies or substantial portions of the Software.
14848b8605Smrg
15848b8605Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16848b8605Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17848b8605Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18848b8605Smrg NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
19848b8605Smrg HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20848b8605Smrg WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21848b8605Smrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22848b8605Smrg DEALINGS IN THE SOFTWARE.
23848b8605Smrg
24848b8605Smrg Except as contained in this notice, the name(s) of the above
25848b8605Smrg copyright holders shall not be used in advertising or otherwise to
26848b8605Smrg promote the sale, use or other dealings in this Software without
27848b8605Smrg prior written authorization.
28848b8605Smrg*/
29848b8605Smrg#include <assert.h>
30848b8605Smrg#include "glxclient.h"
31848b8605Smrg#include "apple_glx.h"
32848b8605Smrg#include "appledri.h"
33848b8605Smrg#include "apple_glx_drawable.h"
34848b8605Smrg
35848b8605Smrgstatic bool surface_make_current(struct apple_glx_context *ac,
36848b8605Smrg                                 struct apple_glx_drawable *d);
37848b8605Smrg
38848b8605Smrgstatic void surface_destroy(Display * dpy, struct apple_glx_drawable *d);
39848b8605Smrg
40848b8605Smrg
41848b8605Smrgstatic struct apple_glx_drawable_callbacks callbacks = {
42848b8605Smrg   .type = APPLE_GLX_DRAWABLE_SURFACE,
43848b8605Smrg   .make_current = surface_make_current,
44848b8605Smrg   .destroy = surface_destroy
45848b8605Smrg};
46848b8605Smrg
47848b8605Smrgstatic void
48848b8605Smrgupdate_viewport_and_scissor(Display * dpy, GLXDrawable drawable)
49848b8605Smrg{
50848b8605Smrg   Window root;
51848b8605Smrg   int x, y;
52848b8605Smrg   unsigned int width = 0, height = 0, bd, depth;
53848b8605Smrg
54848b8605Smrg   XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth);
55848b8605Smrg
56848b8605Smrg   apple_glapi_oglfw_viewport_scissor(0, 0, width, height);
57848b8605Smrg}
58848b8605Smrg
59848b8605Smrgstatic bool
60848b8605Smrgsurface_make_current(struct apple_glx_context *ac,
61848b8605Smrg                     struct apple_glx_drawable *d)
62848b8605Smrg{
63848b8605Smrg   struct apple_glx_surface *s = &d->types.surface;
64848b8605Smrg   xp_error error;
65848b8605Smrg
66848b8605Smrg   assert(APPLE_GLX_DRAWABLE_SURFACE == d->type);
67848b8605Smrg
68848b8605Smrg   apple_glx_diagnostic("%s: ac->context_obj %p s->surface_id %u\n",
69848b8605Smrg                        __func__, (void *) ac->context_obj, s->surface_id);
70848b8605Smrg
71848b8605Smrg   error = xp_attach_gl_context(ac->context_obj, s->surface_id);
72848b8605Smrg
73848b8605Smrg   if (error) {
74848b8605Smrg      fprintf(stderr, "error: xp_attach_gl_context returned: %d\n", error);
75848b8605Smrg      return true;
76848b8605Smrg   }
77848b8605Smrg
78848b8605Smrg
79848b8605Smrg   if (!ac->made_current) {
80848b8605Smrg      /*
81848b8605Smrg       * The first time a new context is made current the glViewport
82848b8605Smrg       * and glScissor should be updated.
83848b8605Smrg       */
84848b8605Smrg      update_viewport_and_scissor(ac->drawable->display,
85848b8605Smrg                                  ac->drawable->drawable);
86848b8605Smrg      ac->made_current = true;
87848b8605Smrg   }
88848b8605Smrg
89848b8605Smrg   apple_glx_diagnostic("%s: drawable 0x%lx\n", __func__, d->drawable);
90848b8605Smrg
91848b8605Smrg   return false;
92848b8605Smrg}
93848b8605Smrg
94848b8605Smrgstatic void
95848b8605Smrgsurface_destroy(Display * dpy, struct apple_glx_drawable *d)
96848b8605Smrg{
97848b8605Smrg   struct apple_glx_surface *s = &d->types.surface;
98848b8605Smrg
99848b8605Smrg   apple_glx_diagnostic("%s: s->surface_id %u\n", __func__, s->surface_id);
100848b8605Smrg
101848b8605Smrg   xp_error error = xp_destroy_surface(s->surface_id);
102848b8605Smrg
103848b8605Smrg   if (error) {
104848b8605Smrg      fprintf(stderr, "xp_destroy_surface error: %d\n", (int) error);
105848b8605Smrg   }
106848b8605Smrg
107848b8605Smrg   /*
108848b8605Smrg    * Check if this surface destroy came from the surface being destroyed
109848b8605Smrg    * on the server.  If s->pending_destroy is true, then it did, and
110848b8605Smrg    * we don't want to try to destroy the surface on the server.
111848b8605Smrg    */
112848b8605Smrg   if (!s->pending_destroy) {
113848b8605Smrg      /*
114848b8605Smrg       * Warning: this causes other routines to be called (potentially)
115848b8605Smrg       * from surface_notify_handler.  It's probably best to not have
116848b8605Smrg       * any locks at this point locked.
117848b8605Smrg       */
118848b8605Smrg      XAppleDRIDestroySurface(d->display, DefaultScreen(d->display),
119848b8605Smrg                              d->drawable);
120848b8605Smrg
121848b8605Smrg      apple_glx_diagnostic
122848b8605Smrg         ("%s: destroyed a surface for drawable 0x%lx uid %u\n", __func__,
123848b8605Smrg          d->drawable, s->uid);
124848b8605Smrg   }
125848b8605Smrg}
126848b8605Smrg
127b8e80941Smrg/* Return true if an error occurred. */
128848b8605Smrgstatic bool
129848b8605Smrgcreate_surface(Display * dpy, int screen, struct apple_glx_drawable *d)
130848b8605Smrg{
131848b8605Smrg   struct apple_glx_surface *s = &d->types.surface;
132848b8605Smrg   unsigned int key[2];
133848b8605Smrg   xp_client_id id;
134848b8605Smrg
135848b8605Smrg   id = apple_glx_get_client_id();
136848b8605Smrg   if (0 == id)
137848b8605Smrg      return true;
138848b8605Smrg
139848b8605Smrg   assert(None != d->drawable);
140848b8605Smrg
141848b8605Smrg   s->pending_destroy = false;
142848b8605Smrg
143848b8605Smrg   if (XAppleDRICreateSurface(dpy, screen, d->drawable, id, key, &s->uid)) {
144848b8605Smrg      xp_error error;
145848b8605Smrg
146848b8605Smrg      error = xp_import_surface(key, &s->surface_id);
147848b8605Smrg
148848b8605Smrg      if (error) {
149848b8605Smrg         fprintf(stderr, "error: xp_import_surface returned: %d\n", error);
150848b8605Smrg         return true;
151848b8605Smrg      }
152848b8605Smrg
153848b8605Smrg      apple_glx_diagnostic("%s: created a surface for drawable 0x%lx"
154848b8605Smrg                           " with uid %u\n", __func__, d->drawable, s->uid);
155848b8605Smrg      return false;             /*success */
156848b8605Smrg   }
157848b8605Smrg
158848b8605Smrg   return true;                 /* unable to create a surface. */
159848b8605Smrg}
160848b8605Smrg
161b8e80941Smrg/* Return true if an error occurred. */
162848b8605Smrg/* This returns a referenced object via resultptr. */
163848b8605Smrgbool
164848b8605Smrgapple_glx_surface_create(Display * dpy, int screen,
165848b8605Smrg                         GLXDrawable drawable,
166848b8605Smrg                         struct apple_glx_drawable ** resultptr)
167848b8605Smrg{
168848b8605Smrg   struct apple_glx_drawable *d;
169848b8605Smrg
170848b8605Smrg   if (apple_glx_drawable_create(dpy, screen, drawable, &d, &callbacks))
171848b8605Smrg      return true;
172848b8605Smrg
173848b8605Smrg   /* apple_glx_drawable_create creates a locked and referenced object. */
174848b8605Smrg
175848b8605Smrg   if (create_surface(dpy, screen, d)) {
176848b8605Smrg      d->unlock(d);
177848b8605Smrg      d->destroy(d);
178848b8605Smrg      return true;
179848b8605Smrg   }
180848b8605Smrg
181848b8605Smrg   *resultptr = d;
182848b8605Smrg
183848b8605Smrg   d->unlock(d);
184848b8605Smrg
185848b8605Smrg   return false;
186848b8605Smrg}
187848b8605Smrg
188848b8605Smrg/*
189848b8605Smrg * All surfaces are reference counted, and surfaces are only created
190848b8605Smrg * when the window is made current.  When all contexts no longer reference
191848b8605Smrg * a surface drawable the apple_glx_drawable gets destroyed, and thus
192848b8605Smrg * its surface is destroyed.
193848b8605Smrg *
194848b8605Smrg * However we can make the destruction occur a bit sooner by setting
195848b8605Smrg * pending_destroy, which is then checked for in glViewport by
196848b8605Smrg * apple_glx_context_update.
197848b8605Smrg */
198848b8605Smrgvoid
199848b8605Smrgapple_glx_surface_destroy(unsigned int uid)
200848b8605Smrg{
201848b8605Smrg   struct apple_glx_drawable *d;
202848b8605Smrg
203848b8605Smrg   d = apple_glx_drawable_find_by_uid(uid, APPLE_GLX_DRAWABLE_REFERENCE
204848b8605Smrg                                      | APPLE_GLX_DRAWABLE_LOCK);
205848b8605Smrg
206848b8605Smrg   if (d) {
207848b8605Smrg      d->types.surface.pending_destroy = true;
208848b8605Smrg      d->release(d);
209848b8605Smrg
210848b8605Smrg      /*
211848b8605Smrg       * We release 2 references to the surface.  One was acquired by
212848b8605Smrg       * the find, and the other was leftover from a context, or
213848b8605Smrg       * the surface being displayed, so the destroy() will decrease it
214848b8605Smrg       * once more.
215848b8605Smrg       *
216848b8605Smrg       * If the surface is in a context, it will take one d->destroy(d);
217848b8605Smrg       * to actually destroy it when the pending_destroy is processed
218848b8605Smrg       * by a glViewport callback (see apple_glx_context_update()).
219848b8605Smrg       */
220848b8605Smrg      if (!d->destroy(d)) {
221848b8605Smrg          /* apple_glx_drawable_find_by_uid returns a locked drawable */
222848b8605Smrg          d->unlock(d);
223848b8605Smrg      }
224848b8605Smrg   }
225848b8605Smrg}
226