summaryrefslogtreecommitdiffstats
path: root/src/glx/apple/apple_glx_pixmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glx/apple/apple_glx_pixmap.c')
-rw-r--r--src/glx/apple/apple_glx_pixmap.c230
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);
+}