13464ebd5Sriastradh/*
23464ebd5Sriastradh Copyright (c) 2009 Apple Inc.
33464ebd5Sriastradh
43464ebd5Sriastradh Permission is hereby granted, free of charge, to any person
53464ebd5Sriastradh obtaining a copy of this software and associated documentation files
63464ebd5Sriastradh (the "Software"), to deal in the Software without restriction,
73464ebd5Sriastradh including without limitation the rights to use, copy, modify, merge,
83464ebd5Sriastradh publish, distribute, sublicense, and/or sell copies of the Software,
93464ebd5Sriastradh and to permit persons to whom the Software is furnished to do so,
103464ebd5Sriastradh subject to the following conditions:
113464ebd5Sriastradh
123464ebd5Sriastradh The above copyright notice and this permission notice shall be
133464ebd5Sriastradh included in all copies or substantial portions of the Software.
143464ebd5Sriastradh
153464ebd5Sriastradh THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
163464ebd5Sriastradh EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
173464ebd5Sriastradh MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
183464ebd5Sriastradh NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
193464ebd5Sriastradh HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
203464ebd5Sriastradh WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
213464ebd5Sriastradh OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
223464ebd5Sriastradh DEALINGS IN THE SOFTWARE.
233464ebd5Sriastradh
243464ebd5Sriastradh Except as contained in this notice, the name(s) of the above
253464ebd5Sriastradh copyright holders shall not be used in advertising or otherwise to
263464ebd5Sriastradh promote the sale, use or other dealings in this Software without
273464ebd5Sriastradh prior written authorization.
283464ebd5Sriastradh*/
293464ebd5Sriastradh
303464ebd5Sriastradh#include <stdio.h>
313464ebd5Sriastradh#include <stdlib.h>
323464ebd5Sriastradh#include <pthread.h>
333464ebd5Sriastradh#include <fcntl.h>
343464ebd5Sriastradh#include <sys/types.h>
353464ebd5Sriastradh#include <sys/mman.h>
363464ebd5Sriastradh#include <unistd.h>
373464ebd5Sriastradh#include <assert.h>
383464ebd5Sriastradh#include "apple_glx.h"
393464ebd5Sriastradh#include "apple_cgl.h"
403464ebd5Sriastradh#include "apple_visual.h"
413464ebd5Sriastradh#include "apple_glx_drawable.h"
423464ebd5Sriastradh#include "appledri.h"
433464ebd5Sriastradh#include "glxconfig.h"
443464ebd5Sriastradh
453464ebd5Sriastradhstatic bool pixmap_make_current(struct apple_glx_context *ac,
463464ebd5Sriastradh                                struct apple_glx_drawable *d);
473464ebd5Sriastradh
483464ebd5Sriastradhstatic void pixmap_destroy(Display * dpy, struct apple_glx_drawable *d);
493464ebd5Sriastradh
503464ebd5Sriastradhstatic struct apple_glx_drawable_callbacks callbacks = {
513464ebd5Sriastradh   .type = APPLE_GLX_DRAWABLE_PIXMAP,
523464ebd5Sriastradh   .make_current = pixmap_make_current,
533464ebd5Sriastradh   .destroy = pixmap_destroy
543464ebd5Sriastradh};
553464ebd5Sriastradh
563464ebd5Sriastradhstatic bool
573464ebd5Sriastradhpixmap_make_current(struct apple_glx_context *ac,
583464ebd5Sriastradh                    struct apple_glx_drawable *d)
593464ebd5Sriastradh{
603464ebd5Sriastradh   CGLError cglerr;
613464ebd5Sriastradh   struct apple_glx_pixmap *p = &d->types.pixmap;
623464ebd5Sriastradh
633464ebd5Sriastradh   assert(APPLE_GLX_DRAWABLE_PIXMAP == d->type);
643464ebd5Sriastradh
653464ebd5Sriastradh   cglerr = apple_cgl.set_current_context(p->context_obj);
663464ebd5Sriastradh
673464ebd5Sriastradh   if (kCGLNoError != cglerr) {
683464ebd5Sriastradh      fprintf(stderr, "set current context: %s\n",
693464ebd5Sriastradh              apple_cgl.error_string(cglerr));
703464ebd5Sriastradh      return true;
713464ebd5Sriastradh   }
723464ebd5Sriastradh
733464ebd5Sriastradh   cglerr = apple_cgl.set_off_screen(p->context_obj, p->width, p->height,
743464ebd5Sriastradh                                     p->pitch, p->buffer);
753464ebd5Sriastradh
763464ebd5Sriastradh   if (kCGLNoError != cglerr) {
773464ebd5Sriastradh      fprintf(stderr, "set off screen: %s\n", apple_cgl.error_string(cglerr));
783464ebd5Sriastradh
793464ebd5Sriastradh      return true;
803464ebd5Sriastradh   }
813464ebd5Sriastradh
823464ebd5Sriastradh   if (!ac->made_current) {
833464ebd5Sriastradh      apple_glapi_oglfw_viewport_scissor(0, 0, p->width, p->height);
843464ebd5Sriastradh      ac->made_current = true;
853464ebd5Sriastradh   }
863464ebd5Sriastradh
873464ebd5Sriastradh   return false;
883464ebd5Sriastradh}
893464ebd5Sriastradh
903464ebd5Sriastradhstatic void
913464ebd5Sriastradhpixmap_destroy(Display * dpy, struct apple_glx_drawable *d)
923464ebd5Sriastradh{
933464ebd5Sriastradh   struct apple_glx_pixmap *p = &d->types.pixmap;
943464ebd5Sriastradh
953464ebd5Sriastradh   if (p->pixel_format_obj)
963464ebd5Sriastradh      (void) apple_cgl.destroy_pixel_format(p->pixel_format_obj);
973464ebd5Sriastradh
983464ebd5Sriastradh   if (p->context_obj)
993464ebd5Sriastradh      (void) apple_cgl.destroy_context(p->context_obj);
1003464ebd5Sriastradh
1013464ebd5Sriastradh   XAppleDRIDestroyPixmap(dpy, p->xpixmap);
1023464ebd5Sriastradh
1033464ebd5Sriastradh   if (p->buffer) {
1043464ebd5Sriastradh      if (munmap(p->buffer, p->size))
1053464ebd5Sriastradh         perror("munmap");
1063464ebd5Sriastradh
1073464ebd5Sriastradh      if (-1 == close(p->fd))
1083464ebd5Sriastradh         perror("close");
1093464ebd5Sriastradh
1103464ebd5Sriastradh      if (shm_unlink(p->path))
1113464ebd5Sriastradh         perror("shm_unlink");
1123464ebd5Sriastradh   }
1133464ebd5Sriastradh
1143464ebd5Sriastradh   apple_glx_diagnostic("destroyed pixmap buffer for: 0x%lx\n", d->drawable);
1153464ebd5Sriastradh}
1163464ebd5Sriastradh
1173464ebd5Sriastradh/* Return true if an error occurred. */
1183464ebd5Sriastradhbool
1193464ebd5Sriastradhapple_glx_pixmap_create(Display * dpy, int screen, Pixmap pixmap,
1203464ebd5Sriastradh                        const void *mode)
1213464ebd5Sriastradh{
1223464ebd5Sriastradh   struct apple_glx_drawable *d;
1233464ebd5Sriastradh   struct apple_glx_pixmap *p;
1243464ebd5Sriastradh   bool double_buffered;
1253464ebd5Sriastradh   bool uses_stereo;
1263464ebd5Sriastradh   CGLError error;
1273464ebd5Sriastradh   const struct glx_config *cmodes = mode;
1283464ebd5Sriastradh
1293464ebd5Sriastradh   if (apple_glx_drawable_create(dpy, screen, pixmap, &d, &callbacks))
1303464ebd5Sriastradh      return true;
1313464ebd5Sriastradh
1323464ebd5Sriastradh   /* d is locked and referenced at this point. */
1333464ebd5Sriastradh
1343464ebd5Sriastradh   p = &d->types.pixmap;
1353464ebd5Sriastradh
1363464ebd5Sriastradh   p->xpixmap = pixmap;
1373464ebd5Sriastradh   p->buffer = NULL;
1383464ebd5Sriastradh
1393464ebd5Sriastradh   if (!XAppleDRICreatePixmap(dpy, screen, pixmap,
1403464ebd5Sriastradh                              &p->width, &p->height, &p->pitch, &p->bpp,
1413464ebd5Sriastradh                              &p->size, p->path, PATH_MAX)) {
1423464ebd5Sriastradh      d->unlock(d);
1433464ebd5Sriastradh      d->destroy(d);
1443464ebd5Sriastradh      return true;
1453464ebd5Sriastradh   }
1463464ebd5Sriastradh
1473464ebd5Sriastradh   p->fd = shm_open(p->path, O_RDWR, 0);
1483464ebd5Sriastradh
1493464ebd5Sriastradh   if (p->fd < 0) {
1503464ebd5Sriastradh      perror("shm_open");
1513464ebd5Sriastradh      d->unlock(d);
1523464ebd5Sriastradh      d->destroy(d);
1533464ebd5Sriastradh      return true;
1543464ebd5Sriastradh   }
1553464ebd5Sriastradh
1563464ebd5Sriastradh   p->buffer = mmap(NULL, p->size, PROT_READ | PROT_WRITE,
1573464ebd5Sriastradh                    MAP_FILE | MAP_SHARED, p->fd, 0);
1583464ebd5Sriastradh
1593464ebd5Sriastradh   if (MAP_FAILED == p->buffer) {
1603464ebd5Sriastradh      perror("mmap");
1613464ebd5Sriastradh      d->unlock(d);
1623464ebd5Sriastradh      d->destroy(d);
1633464ebd5Sriastradh      return true;
1643464ebd5Sriastradh   }
1653464ebd5Sriastradh
1663464ebd5Sriastradh   apple_visual_create_pfobj(&p->pixel_format_obj, mode, &double_buffered,
1673464ebd5Sriastradh                             &uses_stereo, /*offscreen */ true);
1683464ebd5Sriastradh
1693464ebd5Sriastradh   error = apple_cgl.create_context(p->pixel_format_obj, NULL,
1703464ebd5Sriastradh                                    &p->context_obj);
1713464ebd5Sriastradh
1723464ebd5Sriastradh   if (kCGLNoError != error) {
1733464ebd5Sriastradh      d->unlock(d);
1743464ebd5Sriastradh      d->destroy(d);
1753464ebd5Sriastradh      return true;
1763464ebd5Sriastradh   }
1773464ebd5Sriastradh
1783464ebd5Sriastradh   p->fbconfigID = cmodes->fbconfigID;
1793464ebd5Sriastradh
1803464ebd5Sriastradh   d->unlock(d);
1813464ebd5Sriastradh
1823464ebd5Sriastradh   apple_glx_diagnostic("created: pixmap buffer for 0x%lx\n", d->drawable);
1833464ebd5Sriastradh
1843464ebd5Sriastradh   return false;
1853464ebd5Sriastradh}
1863464ebd5Sriastradh
1873464ebd5Sriastradhbool
1883464ebd5Sriastradhapple_glx_pixmap_query(GLXPixmap pixmap, int attr, unsigned int *value)
1893464ebd5Sriastradh{
1903464ebd5Sriastradh   struct apple_glx_drawable *d;
1913464ebd5Sriastradh   struct apple_glx_pixmap *p;
1923464ebd5Sriastradh   bool result = false;
1933464ebd5Sriastradh
1943464ebd5Sriastradh   d = apple_glx_drawable_find_by_type(pixmap, APPLE_GLX_DRAWABLE_PIXMAP,
1953464ebd5Sriastradh                                       APPLE_GLX_DRAWABLE_LOCK);
1963464ebd5Sriastradh
1973464ebd5Sriastradh   if (d) {
1983464ebd5Sriastradh      p = &d->types.pixmap;
1993464ebd5Sriastradh
2003464ebd5Sriastradh      switch (attr) {
2013464ebd5Sriastradh      case GLX_WIDTH:
2023464ebd5Sriastradh         *value = p->width;
2033464ebd5Sriastradh         result = true;
2043464ebd5Sriastradh         break;
2053464ebd5Sriastradh
2063464ebd5Sriastradh      case GLX_HEIGHT:
2073464ebd5Sriastradh         *value = p->height;
2083464ebd5Sriastradh         result = true;
2093464ebd5Sriastradh         break;
2103464ebd5Sriastradh
2113464ebd5Sriastradh      case GLX_FBCONFIG_ID:
2123464ebd5Sriastradh         *value = p->fbconfigID;
2133464ebd5Sriastradh         result = true;
2143464ebd5Sriastradh         break;
2153464ebd5Sriastradh      }
2163464ebd5Sriastradh
2173464ebd5Sriastradh      d->unlock(d);
2183464ebd5Sriastradh   }
2193464ebd5Sriastradh
2203464ebd5Sriastradh   return result;
2213464ebd5Sriastradh}
2223464ebd5Sriastradh
2233464ebd5Sriastradh/* Return true if the type is valid for pixmap. */
2243464ebd5Sriastradhbool
2253464ebd5Sriastradhapple_glx_pixmap_destroy(Display * dpy, GLXPixmap pixmap)
2263464ebd5Sriastradh{
2273464ebd5Sriastradh   return !apple_glx_drawable_destroy_by_type(dpy, pixmap,
2283464ebd5Sriastradh                                              APPLE_GLX_DRAWABLE_PIXMAP);
2293464ebd5Sriastradh}
230