1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci Copyright (c) 2009 Apple Inc.
3bf215546Sopenharmony_ci
4bf215546Sopenharmony_ci Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci obtaining a copy of this software and associated documentation files
6bf215546Sopenharmony_ci (the "Software"), to deal in the Software without restriction,
7bf215546Sopenharmony_ci including without limitation the rights to use, copy, modify, merge,
8bf215546Sopenharmony_ci publish, distribute, sublicense, and/or sell copies of the Software,
9bf215546Sopenharmony_ci and to permit persons to whom the Software is furnished to do so,
10bf215546Sopenharmony_ci subject to the following conditions:
11bf215546Sopenharmony_ci
12bf215546Sopenharmony_ci The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci
15bf215546Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
19bf215546Sopenharmony_ci HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20bf215546Sopenharmony_ci WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22bf215546Sopenharmony_ci DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci Except as contained in this notice, the name(s) of the above
25bf215546Sopenharmony_ci copyright holders shall not be used in advertising or otherwise to
26bf215546Sopenharmony_ci promote the sale, use or other dealings in this Software without
27bf215546Sopenharmony_ci prior written authorization.
28bf215546Sopenharmony_ci*/
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci/* Must be before OpenGL.framework is included.  Remove once fixed:
31bf215546Sopenharmony_ci * <rdar://problem/7872773>
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci#include <GL/gl.h>
34bf215546Sopenharmony_ci#include <GL/glext.h>
35bf215546Sopenharmony_ci#define __gltypes_h_ 1
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci/* Must be first for:
38bf215546Sopenharmony_ci * <rdar://problem/6953344>
39bf215546Sopenharmony_ci */
40bf215546Sopenharmony_ci#include "apple_glx_context.h"
41bf215546Sopenharmony_ci#include "apple_glx_drawable.h"
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#include <stdbool.h>
44bf215546Sopenharmony_ci#include <stdlib.h>
45bf215546Sopenharmony_ci#include <pthread.h>
46bf215546Sopenharmony_ci#include <assert.h>
47bf215546Sopenharmony_ci#include "glxclient.h"
48bf215546Sopenharmony_ci#include "apple_glx.h"
49bf215546Sopenharmony_ci#include "glxconfig.h"
50bf215546Sopenharmony_ci#include "apple_cgl.h"
51bf215546Sopenharmony_ci#include "util/debug.h"
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci/* mesa defines in glew.h, Apple in glext.h.
54bf215546Sopenharmony_ci * Due to namespace nightmares, just do it here.
55bf215546Sopenharmony_ci */
56bf215546Sopenharmony_ci#ifndef GL_TEXTURE_RECTANGLE_EXT
57bf215546Sopenharmony_ci#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
58bf215546Sopenharmony_ci#endif
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistatic bool pbuffer_make_current(struct apple_glx_context *ac,
61bf215546Sopenharmony_ci                                 struct apple_glx_drawable *d);
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_cistatic void pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistatic struct apple_glx_drawable_callbacks callbacks = {
66bf215546Sopenharmony_ci   .type = APPLE_GLX_DRAWABLE_PBUFFER,
67bf215546Sopenharmony_ci   .make_current = pbuffer_make_current,
68bf215546Sopenharmony_ci   .destroy = pbuffer_destroy
69bf215546Sopenharmony_ci};
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci/* Return true if an error occurred. */
73bf215546Sopenharmony_cibool
74bf215546Sopenharmony_cipbuffer_make_current(struct apple_glx_context *ac,
75bf215546Sopenharmony_ci                     struct apple_glx_drawable *d)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
78bf215546Sopenharmony_ci   CGLError cglerr;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   cglerr = apple_cgl.set_pbuffer(ac->context_obj, pbuf->buffer_obj, 0, 0, 0);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   if (kCGLNoError != cglerr) {
85bf215546Sopenharmony_ci      fprintf(stderr, "set_pbuffer: %s\n", apple_cgl.error_string(cglerr));
86bf215546Sopenharmony_ci      return true;
87bf215546Sopenharmony_ci   }
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   if (!ac->made_current) {
90bf215546Sopenharmony_ci      apple_glapi_oglfw_viewport_scissor(0, 0, pbuf->width, pbuf->height);
91bf215546Sopenharmony_ci      ac->made_current = true;
92bf215546Sopenharmony_ci   }
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   apple_glx_diagnostic("made pbuffer drawable 0x%lx current\n", d->drawable);
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   return false;
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_civoid
100bf215546Sopenharmony_cipbuffer_destroy(Display * dpy, struct apple_glx_drawable *d)
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   apple_glx_diagnostic("destroying pbuffer for drawable 0x%lx\n",
107bf215546Sopenharmony_ci                        d->drawable);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   apple_cgl.destroy_pbuffer(pbuf->buffer_obj);
110bf215546Sopenharmony_ci   XFreePixmap(dpy, pbuf->xid);
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci/* Return true if an error occurred. */
114bf215546Sopenharmony_cibool
115bf215546Sopenharmony_ciapple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf)
116bf215546Sopenharmony_ci{
117bf215546Sopenharmony_ci   return !apple_glx_drawable_destroy_by_type(dpy, pbuf,
118bf215546Sopenharmony_ci                                              APPLE_GLX_DRAWABLE_PBUFFER);
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci/* Return true if an error occurred. */
122bf215546Sopenharmony_cibool
123bf215546Sopenharmony_ciapple_glx_pbuffer_create(Display * dpy, GLXFBConfig config,
124bf215546Sopenharmony_ci                         int width, int height, int *errorcode,
125bf215546Sopenharmony_ci                         GLXPbuffer * result)
126bf215546Sopenharmony_ci{
127bf215546Sopenharmony_ci   struct apple_glx_drawable *d;
128bf215546Sopenharmony_ci   struct apple_glx_pbuffer *pbuf = NULL;
129bf215546Sopenharmony_ci   CGLError err;
130bf215546Sopenharmony_ci   Window root;
131bf215546Sopenharmony_ci   int screen;
132bf215546Sopenharmony_ci   Pixmap xid;
133bf215546Sopenharmony_ci   struct glx_config *modes = (struct glx_config *) config;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   root = DefaultRootWindow(dpy);
136bf215546Sopenharmony_ci   screen = DefaultScreen(dpy);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   /*
139bf215546Sopenharmony_ci    * This pixmap is only used for a persistent XID.
140bf215546Sopenharmony_ci    * The XC-MISC extension cleans up XIDs and reuses them transparently,
141bf215546Sopenharmony_ci    * so we need to retain a server-side reference.
142bf215546Sopenharmony_ci    */
143bf215546Sopenharmony_ci   xid = XCreatePixmap(dpy, root, (unsigned int) 1,
144bf215546Sopenharmony_ci                       (unsigned int) 1, DefaultDepth(dpy, screen));
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   if (None == xid) {
147bf215546Sopenharmony_ci      *errorcode = BadAlloc;
148bf215546Sopenharmony_ci      return true;
149bf215546Sopenharmony_ci   }
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   if (apple_glx_drawable_create(dpy, screen, xid, &d, &callbacks)) {
152bf215546Sopenharmony_ci      *errorcode = BadAlloc;
153bf215546Sopenharmony_ci      return true;
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   /* The lock is held in d from create onward. */
157bf215546Sopenharmony_ci   pbuf = &d->types.pbuffer;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   pbuf->xid = xid;
160bf215546Sopenharmony_ci   pbuf->width = width;
161bf215546Sopenharmony_ci   pbuf->height = height;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   err = apple_cgl.create_pbuffer(width, height, GL_TEXTURE_RECTANGLE_EXT,
164bf215546Sopenharmony_ci                                  (modes->alphaBits > 0) ? GL_RGBA : GL_RGB,
165bf215546Sopenharmony_ci                                  0, &pbuf->buffer_obj);
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   if (kCGLNoError != err) {
168bf215546Sopenharmony_ci      d->unlock(d);
169bf215546Sopenharmony_ci      d->destroy(d);
170bf215546Sopenharmony_ci      *errorcode = BadMatch;
171bf215546Sopenharmony_ci      return true;
172bf215546Sopenharmony_ci   }
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   pbuf->fbconfigID = modes->fbconfigID;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   pbuf->event_mask = 0;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   *result = pbuf->xid;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   d->unlock(d);
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   return false;
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci/* Return true if an error occurred. */
188bf215546Sopenharmony_cistatic bool
189bf215546Sopenharmony_ciget_max_size(int *widthresult, int *heightresult)
190bf215546Sopenharmony_ci{
191bf215546Sopenharmony_ci   CGLContextObj oldcontext;
192bf215546Sopenharmony_ci   GLint ar[2];
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   oldcontext = apple_cgl.get_current_context();
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   if (!oldcontext) {
197bf215546Sopenharmony_ci      /*
198bf215546Sopenharmony_ci       * There is no current context, so we need to make one in order
199bf215546Sopenharmony_ci       * to call glGetInteger.
200bf215546Sopenharmony_ci       */
201bf215546Sopenharmony_ci      CGLPixelFormatObj pfobj;
202bf215546Sopenharmony_ci      CGLError err;
203bf215546Sopenharmony_ci      CGLPixelFormatAttribute attr[10];
204bf215546Sopenharmony_ci      int c = 0;
205bf215546Sopenharmony_ci      GLint vsref = 0;
206bf215546Sopenharmony_ci      CGLContextObj newcontext;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci      attr[c++] = kCGLPFAColorSize;
209bf215546Sopenharmony_ci      attr[c++] = 32;
210bf215546Sopenharmony_ci      attr[c++] = 0;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci      err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref);
213bf215546Sopenharmony_ci      if (kCGLNoError != err) {
214bf215546Sopenharmony_ci            DebugMessageF("choose_pixel_format error in %s: %s\n", __func__,
215bf215546Sopenharmony_ci                          apple_cgl.error_string(err));
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci         return true;
218bf215546Sopenharmony_ci      }
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci      err = apple_cgl.create_context(pfobj, NULL, &newcontext);
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci      if (kCGLNoError != err) {
224bf215546Sopenharmony_ci         DebugMessageF("create_context error in %s: %s\n", __func__,
225bf215546Sopenharmony_ci                       apple_cgl.error_string(err));
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci         apple_cgl.destroy_pixel_format(pfobj);
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci         return true;
230bf215546Sopenharmony_ci      }
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci      err = apple_cgl.set_current_context(newcontext);
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci      if (kCGLNoError != err) {
235bf215546Sopenharmony_ci         DebugMessageF("set_current_context error in %s: %s\n", __func__,
236bf215546Sopenharmony_ci                       apple_cgl.error_string(err));
237bf215546Sopenharmony_ci         return true;
238bf215546Sopenharmony_ci      }
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci      glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci      apple_cgl.set_current_context(oldcontext);
244bf215546Sopenharmony_ci      apple_cgl.destroy_context(newcontext);
245bf215546Sopenharmony_ci      apple_cgl.destroy_pixel_format(pfobj);
246bf215546Sopenharmony_ci   }
247bf215546Sopenharmony_ci   else {
248bf215546Sopenharmony_ci      /* We have a valid context. */
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci      glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
251bf215546Sopenharmony_ci   }
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   *widthresult = ar[0];
254bf215546Sopenharmony_ci   *heightresult = ar[1];
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   return false;
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_cibool
260bf215546Sopenharmony_ciapple_glx_pbuffer_query(GLXPbuffer p, int attr, unsigned int *value)
261bf215546Sopenharmony_ci{
262bf215546Sopenharmony_ci   bool result = false;
263bf215546Sopenharmony_ci   struct apple_glx_drawable *d;
264bf215546Sopenharmony_ci   struct apple_glx_pbuffer *pbuf;
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   d = apple_glx_drawable_find_by_type(p, APPLE_GLX_DRAWABLE_PBUFFER,
267bf215546Sopenharmony_ci                                       APPLE_GLX_DRAWABLE_LOCK);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   if (d) {
270bf215546Sopenharmony_ci      pbuf = &d->types.pbuffer;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci      switch (attr) {
273bf215546Sopenharmony_ci      case GLX_WIDTH:
274bf215546Sopenharmony_ci         *value = pbuf->width;
275bf215546Sopenharmony_ci         result = true;
276bf215546Sopenharmony_ci         break;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci      case GLX_HEIGHT:
279bf215546Sopenharmony_ci         *value = pbuf->height;
280bf215546Sopenharmony_ci         result = true;
281bf215546Sopenharmony_ci         break;
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci      case GLX_PRESERVED_CONTENTS:
284bf215546Sopenharmony_ci         *value = true;
285bf215546Sopenharmony_ci         result = true;
286bf215546Sopenharmony_ci         break;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci      case GLX_LARGEST_PBUFFER:{
289bf215546Sopenharmony_ci            int width, height;
290bf215546Sopenharmony_ci            if (get_max_size(&width, &height)) {
291bf215546Sopenharmony_ci               fprintf(stderr, "internal error: "
292bf215546Sopenharmony_ci                       "unable to find the largest pbuffer!\n");
293bf215546Sopenharmony_ci            }
294bf215546Sopenharmony_ci            else {
295bf215546Sopenharmony_ci               *value = width;
296bf215546Sopenharmony_ci               result = true;
297bf215546Sopenharmony_ci            }
298bf215546Sopenharmony_ci         }
299bf215546Sopenharmony_ci         break;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci      case GLX_FBCONFIG_ID:
302bf215546Sopenharmony_ci         *value = pbuf->fbconfigID;
303bf215546Sopenharmony_ci         result = true;
304bf215546Sopenharmony_ci         break;
305bf215546Sopenharmony_ci      }
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci      d->unlock(d);
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   return result;
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_cibool
314bf215546Sopenharmony_ciapple_glx_pbuffer_set_event_mask(GLXDrawable drawable, unsigned long mask)
315bf215546Sopenharmony_ci{
316bf215546Sopenharmony_ci   struct apple_glx_drawable *d;
317bf215546Sopenharmony_ci   bool result = false;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
320bf215546Sopenharmony_ci                                       APPLE_GLX_DRAWABLE_LOCK);
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   if (d) {
323bf215546Sopenharmony_ci      d->types.pbuffer.event_mask = mask;
324bf215546Sopenharmony_ci      result = true;
325bf215546Sopenharmony_ci      d->unlock(d);
326bf215546Sopenharmony_ci   }
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   return result;
329bf215546Sopenharmony_ci}
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_cibool
332bf215546Sopenharmony_ciapple_glx_pbuffer_get_event_mask(GLXDrawable drawable, unsigned long *mask)
333bf215546Sopenharmony_ci{
334bf215546Sopenharmony_ci   struct apple_glx_drawable *d;
335bf215546Sopenharmony_ci   bool result = false;
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
338bf215546Sopenharmony_ci                                       APPLE_GLX_DRAWABLE_LOCK);
339bf215546Sopenharmony_ci   if (d) {
340bf215546Sopenharmony_ci      *mask = d->types.pbuffer.event_mask;
341bf215546Sopenharmony_ci      result = true;
342bf215546Sopenharmony_ci      d->unlock(d);
343bf215546Sopenharmony_ci   }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   return result;
346bf215546Sopenharmony_ci}
347