diff options
Diffstat (limited to 'src/glx/apple/apple_glx_pixmap.c')
-rw-r--r-- | src/glx/apple/apple_glx_pixmap.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/glx/apple/apple_glx_pixmap.c b/src/glx/apple/apple_glx_pixmap.c new file mode 100644 index 00000000000..af1791afb70 --- /dev/null +++ b/src/glx/apple/apple_glx_pixmap.c @@ -0,0 +1,230 @@ +/* + Copyright (c) 2009 Apple Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#include <assert.h> +#include "apple_glx.h" +#include "apple_cgl.h" +#include "apple_visual.h" +#include "apple_glx_drawable.h" +#include "appledri.h" +#include "glcontextmodes.h" + +static bool pixmap_make_current(struct apple_glx_context *ac, + struct apple_glx_drawable *d); + +static void pixmap_destroy(Display * dpy, struct apple_glx_drawable *d); + +static struct apple_glx_drawable_callbacks callbacks = { + .type = APPLE_GLX_DRAWABLE_PIXMAP, + .make_current = pixmap_make_current, + .destroy = pixmap_destroy +}; + +static bool +pixmap_make_current(struct apple_glx_context *ac, + struct apple_glx_drawable *d) +{ + CGLError cglerr; + struct apple_glx_pixmap *p = &d->types.pixmap; + + assert(APPLE_GLX_DRAWABLE_PIXMAP == d->type); + + cglerr = apple_cgl.set_current_context(p->context_obj); + + if (kCGLNoError != cglerr) { + fprintf(stderr, "set current context: %s\n", + apple_cgl.error_string(cglerr)); + return true; + } + + cglerr = apple_cgl.set_off_screen(p->context_obj, p->width, p->height, + p->pitch, p->buffer); + + if (kCGLNoError != cglerr) { + fprintf(stderr, "set off screen: %s\n", apple_cgl.error_string(cglerr)); + + return true; + } + + if (!ac->made_current) { + glViewport(0, 0, p->width, p->height); + glScissor(0, 0, p->width, p->height); + ac->made_current = true; + } + + return false; +} + +static void +pixmap_destroy(Display * dpy, struct apple_glx_drawable *d) +{ + struct apple_glx_pixmap *p = &d->types.pixmap; + + if (p->pixel_format_obj) + (void) apple_cgl.destroy_pixel_format(p->pixel_format_obj); + + if (p->context_obj) + (void) apple_cgl.destroy_context(p->context_obj); + + XAppleDRIDestroyPixmap(dpy, p->xpixmap); + + if (p->buffer) { + if (munmap(p->buffer, p->size)) + perror("munmap"); + + if (-1 == close(p->fd)) + perror("close"); + + if (shm_unlink(p->path)) + perror("shm_unlink"); + } + + apple_glx_diagnostic("destroyed pixmap buffer for: 0x%lx\n", d->drawable); +} + +/* Return true if an error occurred. */ +bool +apple_glx_pixmap_create(Display * dpy, int screen, Pixmap pixmap, + const void *mode) +{ + struct apple_glx_drawable *d; + struct apple_glx_pixmap *p; + bool double_buffered; + bool uses_stereo; + CGLError error; + const __GLcontextModes *cmodes = mode; + + if (apple_glx_drawable_create(dpy, screen, pixmap, &d, &callbacks)) + return true; + + /* d is locked and referenced at this point. */ + + p = &d->types.pixmap; + + p->xpixmap = pixmap; + p->buffer = NULL; + + if (!XAppleDRICreatePixmap(dpy, screen, pixmap, + &p->width, &p->height, &p->pitch, &p->bpp, + &p->size, p->path, PATH_MAX)) { + d->unlock(d); + d->destroy(d); + return true; + } + + p->fd = shm_open(p->path, O_RDWR, 0); + + if (p->fd < 0) { + perror("shm_open"); + d->unlock(d); + d->destroy(d); + return true; + } + + p->buffer = mmap(NULL, p->size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, p->fd, 0); + + if (MAP_FAILED == p->buffer) { + perror("mmap"); + d->unlock(d); + d->destroy(d); + return true; + } + + apple_visual_create_pfobj(&p->pixel_format_obj, mode, &double_buffered, + &uses_stereo, /*offscreen */ true); + + error = apple_cgl.create_context(p->pixel_format_obj, NULL, + &p->context_obj); + + if (kCGLNoError != error) { + d->unlock(d); + d->destroy(d); + return true; + } + + p->fbconfigID = cmodes->fbconfigID; + + d->unlock(d); + + apple_glx_diagnostic("created: pixmap buffer for 0x%lx\n", d->drawable); + + return false; +} + +bool +apple_glx_pixmap_query(GLXPixmap pixmap, int attr, unsigned int *value) +{ + struct apple_glx_drawable *d; + struct apple_glx_pixmap *p; + bool result = false; + + d = apple_glx_drawable_find_by_type(pixmap, APPLE_GLX_DRAWABLE_PIXMAP, + APPLE_GLX_DRAWABLE_LOCK); + + if (d) { + p = &d->types.pixmap; + + switch (attr) { + case GLX_WIDTH: + *value = p->width; + result = true; + break; + + case GLX_HEIGHT: + *value = p->height; + result = true; + break; + + case GLX_FBCONFIG_ID: + *value = p->fbconfigID; + result = true; + break; + } + + d->unlock(d); + } + + return result; +} + +/* Return true if the type is valid for pixmap. */ +bool +apple_glx_pixmap_destroy(Display * dpy, GLXPixmap pixmap) +{ + return !apple_glx_drawable_destroy_by_type(dpy, pixmap, + APPLE_GLX_DRAWABLE_PIXMAP); +} |