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
30848b8605Smrg#include <stdio.h>
31848b8605Smrg#include <stdlib.h>
32848b8605Smrg#include <pthread.h>
33848b8605Smrg#include <fcntl.h>
34848b8605Smrg#include <sys/types.h>
35848b8605Smrg#include <sys/mman.h>
36848b8605Smrg#include <unistd.h>
37848b8605Smrg#include <assert.h>
38848b8605Smrg#include "apple_glx.h"
39848b8605Smrg#include "apple_cgl.h"
40848b8605Smrg#include "apple_visual.h"
41848b8605Smrg#include "apple_glx_drawable.h"
42848b8605Smrg#include "appledri.h"
43848b8605Smrg#include "glxconfig.h"
44848b8605Smrg
45848b8605Smrgstatic bool pixmap_make_current(struct apple_glx_context *ac,
46848b8605Smrg                                struct apple_glx_drawable *d);
47848b8605Smrg
48848b8605Smrgstatic void pixmap_destroy(Display * dpy, struct apple_glx_drawable *d);
49848b8605Smrg
50848b8605Smrgstatic struct apple_glx_drawable_callbacks callbacks = {
51848b8605Smrg   .type = APPLE_GLX_DRAWABLE_PIXMAP,
52848b8605Smrg   .make_current = pixmap_make_current,
53848b8605Smrg   .destroy = pixmap_destroy
54848b8605Smrg};
55848b8605Smrg
56848b8605Smrgstatic bool
57848b8605Smrgpixmap_make_current(struct apple_glx_context *ac,
58848b8605Smrg                    struct apple_glx_drawable *d)
59848b8605Smrg{
60848b8605Smrg   CGLError cglerr;
61848b8605Smrg   struct apple_glx_pixmap *p = &d->types.pixmap;
62848b8605Smrg
63848b8605Smrg   assert(APPLE_GLX_DRAWABLE_PIXMAP == d->type);
64848b8605Smrg
65848b8605Smrg   cglerr = apple_cgl.set_current_context(p->context_obj);
66848b8605Smrg
67848b8605Smrg   if (kCGLNoError != cglerr) {
68848b8605Smrg      fprintf(stderr, "set current context: %s\n",
69848b8605Smrg              apple_cgl.error_string(cglerr));
70848b8605Smrg      return true;
71848b8605Smrg   }
72848b8605Smrg
73848b8605Smrg   cglerr = apple_cgl.set_off_screen(p->context_obj, p->width, p->height,
74848b8605Smrg                                     p->pitch, p->buffer);
75848b8605Smrg
76848b8605Smrg   if (kCGLNoError != cglerr) {
77848b8605Smrg      fprintf(stderr, "set off screen: %s\n", apple_cgl.error_string(cglerr));
78848b8605Smrg
79848b8605Smrg      return true;
80848b8605Smrg   }
81848b8605Smrg
82848b8605Smrg   if (!ac->made_current) {
83848b8605Smrg      apple_glapi_oglfw_viewport_scissor(0, 0, p->width, p->height);
84848b8605Smrg      ac->made_current = true;
85848b8605Smrg   }
86848b8605Smrg
87848b8605Smrg   return false;
88848b8605Smrg}
89848b8605Smrg
90848b8605Smrgstatic void
91848b8605Smrgpixmap_destroy(Display * dpy, struct apple_glx_drawable *d)
92848b8605Smrg{
93848b8605Smrg   struct apple_glx_pixmap *p = &d->types.pixmap;
94848b8605Smrg
95848b8605Smrg   if (p->pixel_format_obj)
96848b8605Smrg      (void) apple_cgl.destroy_pixel_format(p->pixel_format_obj);
97848b8605Smrg
98848b8605Smrg   if (p->context_obj)
99848b8605Smrg      (void) apple_cgl.destroy_context(p->context_obj);
100848b8605Smrg
101848b8605Smrg   XAppleDRIDestroyPixmap(dpy, p->xpixmap);
102848b8605Smrg
103848b8605Smrg   if (p->buffer) {
104848b8605Smrg      if (munmap(p->buffer, p->size))
105848b8605Smrg         perror("munmap");
106848b8605Smrg
107848b8605Smrg      if (-1 == close(p->fd))
108848b8605Smrg         perror("close");
109848b8605Smrg
110848b8605Smrg      if (shm_unlink(p->path))
111848b8605Smrg         perror("shm_unlink");
112848b8605Smrg   }
113848b8605Smrg
114848b8605Smrg   apple_glx_diagnostic("destroyed pixmap buffer for: 0x%lx\n", d->drawable);
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg/* Return true if an error occurred. */
118848b8605Smrgbool
119848b8605Smrgapple_glx_pixmap_create(Display * dpy, int screen, Pixmap pixmap,
120848b8605Smrg                        const void *mode)
121848b8605Smrg{
122848b8605Smrg   struct apple_glx_drawable *d;
123848b8605Smrg   struct apple_glx_pixmap *p;
124848b8605Smrg   bool double_buffered;
125848b8605Smrg   bool uses_stereo;
126848b8605Smrg   CGLError error;
127848b8605Smrg   const struct glx_config *cmodes = mode;
128848b8605Smrg
129848b8605Smrg   if (apple_glx_drawable_create(dpy, screen, pixmap, &d, &callbacks))
130848b8605Smrg      return true;
131848b8605Smrg
132848b8605Smrg   /* d is locked and referenced at this point. */
133848b8605Smrg
134848b8605Smrg   p = &d->types.pixmap;
135848b8605Smrg
136848b8605Smrg   p->xpixmap = pixmap;
137848b8605Smrg   p->buffer = NULL;
138848b8605Smrg
139848b8605Smrg   if (!XAppleDRICreatePixmap(dpy, screen, pixmap,
140848b8605Smrg                              &p->width, &p->height, &p->pitch, &p->bpp,
141848b8605Smrg                              &p->size, p->path, PATH_MAX)) {
142848b8605Smrg      d->unlock(d);
143848b8605Smrg      d->destroy(d);
144848b8605Smrg      return true;
145848b8605Smrg   }
146848b8605Smrg
147848b8605Smrg   p->fd = shm_open(p->path, O_RDWR, 0);
148848b8605Smrg
149848b8605Smrg   if (p->fd < 0) {
150848b8605Smrg      perror("shm_open");
151848b8605Smrg      d->unlock(d);
152848b8605Smrg      d->destroy(d);
153848b8605Smrg      return true;
154848b8605Smrg   }
155848b8605Smrg
156848b8605Smrg   p->buffer = mmap(NULL, p->size, PROT_READ | PROT_WRITE,
157848b8605Smrg                    MAP_FILE | MAP_SHARED, p->fd, 0);
158848b8605Smrg
159848b8605Smrg   if (MAP_FAILED == p->buffer) {
160848b8605Smrg      perror("mmap");
161848b8605Smrg      d->unlock(d);
162848b8605Smrg      d->destroy(d);
163848b8605Smrg      return true;
164848b8605Smrg   }
165848b8605Smrg
166848b8605Smrg   apple_visual_create_pfobj(&p->pixel_format_obj, mode, &double_buffered,
167848b8605Smrg                             &uses_stereo, /*offscreen */ true);
168848b8605Smrg
169848b8605Smrg   error = apple_cgl.create_context(p->pixel_format_obj, NULL,
170848b8605Smrg                                    &p->context_obj);
171848b8605Smrg
172848b8605Smrg   if (kCGLNoError != error) {
173848b8605Smrg      d->unlock(d);
174848b8605Smrg      d->destroy(d);
175848b8605Smrg      return true;
176848b8605Smrg   }
177848b8605Smrg
178848b8605Smrg   p->fbconfigID = cmodes->fbconfigID;
179848b8605Smrg
180848b8605Smrg   d->unlock(d);
181848b8605Smrg
182848b8605Smrg   apple_glx_diagnostic("created: pixmap buffer for 0x%lx\n", d->drawable);
183848b8605Smrg
184848b8605Smrg   return false;
185848b8605Smrg}
186848b8605Smrg
187848b8605Smrgbool
188848b8605Smrgapple_glx_pixmap_query(GLXPixmap pixmap, int attr, unsigned int *value)
189848b8605Smrg{
190848b8605Smrg   struct apple_glx_drawable *d;
191848b8605Smrg   struct apple_glx_pixmap *p;
192848b8605Smrg   bool result = false;
193848b8605Smrg
194848b8605Smrg   d = apple_glx_drawable_find_by_type(pixmap, APPLE_GLX_DRAWABLE_PIXMAP,
195848b8605Smrg                                       APPLE_GLX_DRAWABLE_LOCK);
196848b8605Smrg
197848b8605Smrg   if (d) {
198848b8605Smrg      p = &d->types.pixmap;
199848b8605Smrg
200848b8605Smrg      switch (attr) {
201848b8605Smrg      case GLX_WIDTH:
202848b8605Smrg         *value = p->width;
203848b8605Smrg         result = true;
204848b8605Smrg         break;
205848b8605Smrg
206848b8605Smrg      case GLX_HEIGHT:
207848b8605Smrg         *value = p->height;
208848b8605Smrg         result = true;
209848b8605Smrg         break;
210848b8605Smrg
211848b8605Smrg      case GLX_FBCONFIG_ID:
212848b8605Smrg         *value = p->fbconfigID;
213848b8605Smrg         result = true;
214848b8605Smrg         break;
215848b8605Smrg      }
216848b8605Smrg
217848b8605Smrg      d->unlock(d);
218848b8605Smrg   }
219848b8605Smrg
220848b8605Smrg   return result;
221848b8605Smrg}
222848b8605Smrg
223848b8605Smrg/* Return true if the type is valid for pixmap. */
224848b8605Smrgbool
225848b8605Smrgapple_glx_pixmap_destroy(Display * dpy, GLXPixmap pixmap)
226848b8605Smrg{
227848b8605Smrg   return !apple_glx_drawable_destroy_by_type(dpy, pixmap,
228848b8605Smrg                                              APPLE_GLX_DRAWABLE_PIXMAP);
229848b8605Smrg}
230