• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 /* Must be before OpenGL.framework is included.  Remove once fixed:
31  * <rdar://problem/7872773>
32  */
33 #include <GL/gl.h>
34 #include <GL/glext.h>
35 #define __gltypes_h_ 1
36 
37 /* Must be first for:
38  * <rdar://problem/6953344>
39  */
40 #include "apple_glx_context.h"
41 #include "apple_glx_drawable.h"
42 
43 #include <stdbool.h>
44 #include <stdlib.h>
45 #include <pthread.h>
46 #include <assert.h>
47 #include "glxclient.h"
48 #include "apple_glx.h"
49 #include "glxconfig.h"
50 #include "apple_cgl.h"
51 #include "util/debug.h"
52 
53 /* mesa defines in glew.h, Apple in glext.h.
54  * Due to namespace nightmares, just do it here.
55  */
56 #ifndef GL_TEXTURE_RECTANGLE_EXT
57 #define GL_TEXTURE_RECTANGLE_EXT 0x84F5
58 #endif
59 
60 static bool pbuffer_make_current(struct apple_glx_context *ac,
61                                  struct apple_glx_drawable *d);
62 
63 static void pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d);
64 
65 static struct apple_glx_drawable_callbacks callbacks = {
66    .type = APPLE_GLX_DRAWABLE_PBUFFER,
67    .make_current = pbuffer_make_current,
68    .destroy = pbuffer_destroy
69 };
70 
71 
72 /* Return true if an error occurred. */
73 bool
pbuffer_make_current(struct apple_glx_context * ac,struct apple_glx_drawable * d)74 pbuffer_make_current(struct apple_glx_context *ac,
75                      struct apple_glx_drawable *d)
76 {
77    struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
78    CGLError cglerr;
79 
80    assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
81 
82    cglerr = apple_cgl.set_pbuffer(ac->context_obj, pbuf->buffer_obj, 0, 0, 0);
83 
84    if (kCGLNoError != cglerr) {
85       fprintf(stderr, "set_pbuffer: %s\n", apple_cgl.error_string(cglerr));
86       return true;
87    }
88 
89    if (!ac->made_current) {
90       apple_glapi_oglfw_viewport_scissor(0, 0, pbuf->width, pbuf->height);
91       ac->made_current = true;
92    }
93 
94    apple_glx_diagnostic("made pbuffer drawable 0x%lx current\n", d->drawable);
95 
96    return false;
97 }
98 
99 void
pbuffer_destroy(Display * dpy,struct apple_glx_drawable * d)100 pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d)
101 {
102    struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
103 
104    assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
105 
106    apple_glx_diagnostic("destroying pbuffer for drawable 0x%lx\n",
107                         d->drawable);
108 
109    apple_cgl.destroy_pbuffer(pbuf->buffer_obj);
110    XFreePixmap(dpy, pbuf->xid);
111 }
112 
113 /* Return true if an error occurred. */
114 bool
apple_glx_pbuffer_destroy(Display * dpy,GLXPbuffer pbuf)115 apple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf)
116 {
117    return !apple_glx_drawable_destroy_by_type(dpy, pbuf,
118                                               APPLE_GLX_DRAWABLE_PBUFFER);
119 }
120 
121 /* Return true if an error occurred. */
122 bool
apple_glx_pbuffer_create(Display * dpy,GLXFBConfig config,int width,int height,int * errorcode,GLXPbuffer * result)123 apple_glx_pbuffer_create(Display * dpy, GLXFBConfig config,
124                          int width, int height, int *errorcode,
125                          GLXPbuffer * result)
126 {
127    struct apple_glx_drawable *d;
128    struct apple_glx_pbuffer *pbuf = NULL;
129    CGLError err;
130    Window root;
131    int screen;
132    Pixmap xid;
133    struct glx_config *modes = (struct glx_config *) config;
134 
135    root = DefaultRootWindow(dpy);
136    screen = DefaultScreen(dpy);
137 
138    /*
139     * This pixmap is only used for a persistent XID.
140     * The XC-MISC extension cleans up XIDs and reuses them transparently,
141     * so we need to retain a server-side reference.
142     */
143    xid = XCreatePixmap(dpy, root, (unsigned int) 1,
144                        (unsigned int) 1, DefaultDepth(dpy, screen));
145 
146    if (None == xid) {
147       *errorcode = BadAlloc;
148       return true;
149    }
150 
151    if (apple_glx_drawable_create(dpy, screen, xid, &d, &callbacks)) {
152       *errorcode = BadAlloc;
153       return true;
154    }
155 
156    /* The lock is held in d from create onward. */
157    pbuf = &d->types.pbuffer;
158 
159    pbuf->xid = xid;
160    pbuf->width = width;
161    pbuf->height = height;
162 
163    err = apple_cgl.create_pbuffer(width, height, GL_TEXTURE_RECTANGLE_EXT,
164                                   (modes->alphaBits > 0) ? GL_RGBA : GL_RGB,
165                                   0, &pbuf->buffer_obj);
166 
167    if (kCGLNoError != err) {
168       d->unlock(d);
169       d->destroy(d);
170       *errorcode = BadMatch;
171       return true;
172    }
173 
174    pbuf->fbconfigID = modes->fbconfigID;
175 
176    pbuf->event_mask = 0;
177 
178    *result = pbuf->xid;
179 
180    d->unlock(d);
181 
182    return false;
183 }
184 
185 
186 
187 /* Return true if an error occurred. */
188 static bool
get_max_size(int * widthresult,int * heightresult)189 get_max_size(int *widthresult, int *heightresult)
190 {
191    CGLContextObj oldcontext;
192    GLint ar[2];
193 
194    oldcontext = apple_cgl.get_current_context();
195 
196    if (!oldcontext) {
197       /*
198        * There is no current context, so we need to make one in order
199        * to call glGetInteger.
200        */
201       CGLPixelFormatObj pfobj;
202       CGLError err;
203       CGLPixelFormatAttribute attr[10];
204       int c = 0;
205       GLint vsref = 0;
206       CGLContextObj newcontext;
207 
208       attr[c++] = kCGLPFAColorSize;
209       attr[c++] = 32;
210       attr[c++] = 0;
211 
212       err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref);
213       if (kCGLNoError != err) {
214             DebugMessageF("choose_pixel_format error in %s: %s\n", __func__,
215                           apple_cgl.error_string(err));
216 
217          return true;
218       }
219 
220 
221       err = apple_cgl.create_context(pfobj, NULL, &newcontext);
222 
223       if (kCGLNoError != err) {
224          DebugMessageF("create_context error in %s: %s\n", __func__,
225                        apple_cgl.error_string(err));
226 
227          apple_cgl.destroy_pixel_format(pfobj);
228 
229          return true;
230       }
231 
232       err = apple_cgl.set_current_context(newcontext);
233 
234       if (kCGLNoError != err) {
235          DebugMessageF("set_current_context error in %s: %s\n", __func__,
236                        apple_cgl.error_string(err));
237          return true;
238       }
239 
240 
241       glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
242 
243       apple_cgl.set_current_context(oldcontext);
244       apple_cgl.destroy_context(newcontext);
245       apple_cgl.destroy_pixel_format(pfobj);
246    }
247    else {
248       /* We have a valid context. */
249 
250       glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
251    }
252 
253    *widthresult = ar[0];
254    *heightresult = ar[1];
255 
256    return false;
257 }
258 
259 bool
apple_glx_pbuffer_query(GLXPbuffer p,int attr,unsigned int * value)260 apple_glx_pbuffer_query(GLXPbuffer p, int attr, unsigned int *value)
261 {
262    bool result = false;
263    struct apple_glx_drawable *d;
264    struct apple_glx_pbuffer *pbuf;
265 
266    d = apple_glx_drawable_find_by_type(p, APPLE_GLX_DRAWABLE_PBUFFER,
267                                        APPLE_GLX_DRAWABLE_LOCK);
268 
269    if (d) {
270       pbuf = &d->types.pbuffer;
271 
272       switch (attr) {
273       case GLX_WIDTH:
274          *value = pbuf->width;
275          result = true;
276          break;
277 
278       case GLX_HEIGHT:
279          *value = pbuf->height;
280          result = true;
281          break;
282 
283       case GLX_PRESERVED_CONTENTS:
284          *value = true;
285          result = true;
286          break;
287 
288       case GLX_LARGEST_PBUFFER:{
289             int width, height;
290             if (get_max_size(&width, &height)) {
291                fprintf(stderr, "internal error: "
292                        "unable to find the largest pbuffer!\n");
293             }
294             else {
295                *value = width;
296                result = true;
297             }
298          }
299          break;
300 
301       case GLX_FBCONFIG_ID:
302          *value = pbuf->fbconfigID;
303          result = true;
304          break;
305       }
306 
307       d->unlock(d);
308    }
309 
310    return result;
311 }
312 
313 bool
apple_glx_pbuffer_set_event_mask(GLXDrawable drawable,unsigned long mask)314 apple_glx_pbuffer_set_event_mask(GLXDrawable drawable, unsigned long mask)
315 {
316    struct apple_glx_drawable *d;
317    bool result = false;
318 
319    d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
320                                        APPLE_GLX_DRAWABLE_LOCK);
321 
322    if (d) {
323       d->types.pbuffer.event_mask = mask;
324       result = true;
325       d->unlock(d);
326    }
327 
328    return result;
329 }
330 
331 bool
apple_glx_pbuffer_get_event_mask(GLXDrawable drawable,unsigned long * mask)332 apple_glx_pbuffer_get_event_mask(GLXDrawable drawable, unsigned long *mask)
333 {
334    struct apple_glx_drawable *d;
335    bool result = false;
336 
337    d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
338                                        APPLE_GLX_DRAWABLE_LOCK);
339    if (d) {
340       *mask = d->types.pbuffer.event_mask;
341       result = true;
342       d->unlock(d);
343    }
344 
345    return result;
346 }
347