diff options
Diffstat (limited to 'src/glx/apple/apple_glx_pbuffer.c')
-rw-r--r-- | src/glx/apple/apple_glx_pbuffer.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/src/glx/apple/apple_glx_pbuffer.c b/src/glx/apple/apple_glx_pbuffer.c new file mode 100644 index 00000000000..3dfdc54763a --- /dev/null +++ b/src/glx/apple/apple_glx_pbuffer.c @@ -0,0 +1,330 @@ +/* + 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 <stdlib.h> +#include <pthread.h> +#include <assert.h> +#include "apple_glx.h" +#include "glcontextmodes.h" +#include "apple_glx_context.h" +#include "apple_glx_drawable.h" +#include "apple_cgl.h" + +static bool pbuffer_make_current(struct apple_glx_context *ac, + struct apple_glx_drawable *d); + +static void pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d); + +static struct apple_glx_drawable_callbacks callbacks = { + .type = APPLE_GLX_DRAWABLE_PBUFFER, + .make_current = pbuffer_make_current, + .destroy = pbuffer_destroy +}; + + +/* Return true if an error occurred. */ +bool +pbuffer_make_current(struct apple_glx_context *ac, + struct apple_glx_drawable *d) +{ + struct apple_glx_pbuffer *pbuf = &d->types.pbuffer; + CGLError cglerr; + + assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type); + + cglerr = apple_cgl.set_pbuffer(ac->context_obj, pbuf->buffer_obj, 0, 0, 0); + + if (kCGLNoError != cglerr) { + fprintf(stderr, "set_pbuffer: %s\n", apple_cgl.error_string(cglerr)); + return true; + } + + if (!ac->made_current) { + glViewport(0, 0, pbuf->width, pbuf->height); + glScissor(0, 0, pbuf->width, pbuf->height); + ac->made_current = true; + } + + apple_glx_diagnostic("made pbuffer drawable 0x%lx current\n", d->drawable); + + return false; +} + +void +pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d) +{ + struct apple_glx_pbuffer *pbuf = &d->types.pbuffer; + + assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type); + + apple_glx_diagnostic("destroying pbuffer for drawable 0x%lx\n", + d->drawable); + + apple_cgl.destroy_pbuffer(pbuf->buffer_obj); + XFreePixmap(dpy, pbuf->xid); +} + +/* Return true if an error occurred. */ +bool +apple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf) +{ + return !apple_glx_drawable_destroy_by_type(dpy, pbuf, + APPLE_GLX_DRAWABLE_PBUFFER); +} + +/* Return true if an error occurred. */ +bool +apple_glx_pbuffer_create(Display * dpy, GLXFBConfig config, + int width, int height, int *errorcode, + GLXPbuffer * result) +{ + struct apple_glx_drawable *d; + struct apple_glx_pbuffer *pbuf = NULL; + CGLError err; + Window root; + int screen; + Pixmap xid; + __GLcontextModes *modes = (__GLcontextModes *) config; + + root = DefaultRootWindow(dpy); + screen = DefaultScreen(dpy); + + /* + * This pixmap is only used for a persistent XID. + * The XC-MISC extension cleans up XIDs and reuses them transparently, + * so we need to retain a server-side reference. + */ + xid = XCreatePixmap(dpy, root, (unsigned int) 1, + (unsigned int) 1, DefaultDepth(dpy, screen)); + + if (None == xid) { + *errorcode = BadAlloc; + return true; + } + + if (apple_glx_drawable_create(dpy, screen, xid, &d, &callbacks)) { + *errorcode = BadAlloc; + return true; + } + + /* The lock is held in d from create onward. */ + pbuf = &d->types.pbuffer; + + pbuf->xid = xid; + pbuf->width = width; + pbuf->height = height; + + err = apple_cgl.create_pbuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, + (modes->alphaBits > 0) ? GL_RGBA : GL_RGB, + 0, &pbuf->buffer_obj); + + if (kCGLNoError != err) { + d->unlock(d); + d->destroy(d); + *errorcode = BadMatch; + return true; + } + + pbuf->fbconfigID = modes->fbconfigID; + + pbuf->event_mask = 0; + + *result = pbuf->xid; + + d->unlock(d); + + return false; +} + + + +/* Return true if an error occurred. */ +static bool +get_max_size(int *widthresult, int *heightresult) +{ + CGLContextObj oldcontext; + GLint ar[2]; + + oldcontext = apple_cgl.get_current_context(); + + if (!oldcontext) { + /* + * There is no current context, so we need to make one in order + * to call glGetInteger. + */ + CGLPixelFormatObj pfobj; + CGLError err; + CGLPixelFormatAttribute attr[10]; + int c = 0; + GLint vsref = 0; + CGLContextObj newcontext; + + attr[c++] = kCGLPFAColorSize; + attr[c++] = 32; + attr[c++] = 0; + + err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref); + if (kCGLNoError != err) { + if (getenv("LIBGL_DIAGNOSTIC")) { + printf("choose_pixel_format error in %s: %s\n", __func__, + apple_cgl.error_string(err)); + } + + return true; + } + + + err = apple_cgl.create_context(pfobj, NULL, &newcontext); + + if (kCGLNoError != err) { + if (getenv("LIBGL_DIAGNOSTIC")) { + printf("create_context error in %s: %s\n", __func__, + apple_cgl.error_string(err)); + } + + apple_cgl.destroy_pixel_format(pfobj); + + return true; + } + + err = apple_cgl.set_current_context(newcontext); + + if (kCGLNoError != err) { + printf("set_current_context error in %s: %s\n", __func__, + apple_cgl.error_string(err)); + return true; + } + + + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar); + + apple_cgl.set_current_context(oldcontext); + apple_cgl.destroy_context(newcontext); + apple_cgl.destroy_pixel_format(pfobj); + } + else { + /* We have a valid context. */ + + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar); + } + + *widthresult = ar[0]; + *heightresult = ar[1]; + + return false; +} + +bool +apple_glx_pbuffer_query(GLXPbuffer p, int attr, unsigned int *value) +{ + bool result = false; + struct apple_glx_drawable *d; + struct apple_glx_pbuffer *pbuf; + + d = apple_glx_drawable_find_by_type(p, APPLE_GLX_DRAWABLE_PBUFFER, + APPLE_GLX_DRAWABLE_LOCK); + + if (d) { + pbuf = &d->types.pbuffer; + + switch (attr) { + case GLX_WIDTH: + *value = pbuf->width; + result = true; + break; + + case GLX_HEIGHT: + *value = pbuf->height; + result = true; + break; + + case GLX_PRESERVED_CONTENTS: + *value = true; + result = true; + break; + + case GLX_LARGEST_PBUFFER:{ + int width, height; + if (get_max_size(&width, &height)) { + fprintf(stderr, "internal error: " + "unable to find the largest pbuffer!\n"); + } + else { + *value = width; + result = true; + } + } + break; + + case GLX_FBCONFIG_ID: + *value = pbuf->fbconfigID; + result = true; + break; + } + + d->unlock(d); + } + + return result; +} + +bool +apple_glx_pbuffer_set_event_mask(GLXDrawable drawable, unsigned long mask) +{ + struct apple_glx_drawable *d; + bool result = false; + + d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER, + APPLE_GLX_DRAWABLE_LOCK); + + if (d) { + d->types.pbuffer.event_mask = mask; + result = true; + d->unlock(d); + } + + return result; +} + +bool +apple_glx_pbuffer_get_event_mask(GLXDrawable drawable, unsigned long *mask) +{ + struct apple_glx_drawable *d; + bool result = false; + + d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER, + APPLE_GLX_DRAWABLE_LOCK); + if (d) { + *mask = d->types.pbuffer.event_mask; + result = true; + d->unlock(d); + } + + return result; +} |