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