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#include <assert.h> 30848b8605Smrg#include "glxclient.h" 31848b8605Smrg#include "apple_glx.h" 32848b8605Smrg#include "appledri.h" 33848b8605Smrg#include "apple_glx_drawable.h" 34848b8605Smrg 35848b8605Smrgstatic bool surface_make_current(struct apple_glx_context *ac, 36848b8605Smrg struct apple_glx_drawable *d); 37848b8605Smrg 38848b8605Smrgstatic void surface_destroy(Display * dpy, struct apple_glx_drawable *d); 39848b8605Smrg 40848b8605Smrg 41848b8605Smrgstatic struct apple_glx_drawable_callbacks callbacks = { 42848b8605Smrg .type = APPLE_GLX_DRAWABLE_SURFACE, 43848b8605Smrg .make_current = surface_make_current, 44848b8605Smrg .destroy = surface_destroy 45848b8605Smrg}; 46848b8605Smrg 47848b8605Smrgstatic void 48848b8605Smrgupdate_viewport_and_scissor(Display * dpy, GLXDrawable drawable) 49848b8605Smrg{ 50848b8605Smrg Window root; 51848b8605Smrg int x, y; 52848b8605Smrg unsigned int width = 0, height = 0, bd, depth; 53848b8605Smrg 54848b8605Smrg XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth); 55848b8605Smrg 56848b8605Smrg apple_glapi_oglfw_viewport_scissor(0, 0, width, height); 57848b8605Smrg} 58848b8605Smrg 59848b8605Smrgstatic bool 60848b8605Smrgsurface_make_current(struct apple_glx_context *ac, 61848b8605Smrg struct apple_glx_drawable *d) 62848b8605Smrg{ 63848b8605Smrg struct apple_glx_surface *s = &d->types.surface; 64848b8605Smrg xp_error error; 65848b8605Smrg 66848b8605Smrg assert(APPLE_GLX_DRAWABLE_SURFACE == d->type); 67848b8605Smrg 68848b8605Smrg apple_glx_diagnostic("%s: ac->context_obj %p s->surface_id %u\n", 69848b8605Smrg __func__, (void *) ac->context_obj, s->surface_id); 70848b8605Smrg 71848b8605Smrg error = xp_attach_gl_context(ac->context_obj, s->surface_id); 72848b8605Smrg 73848b8605Smrg if (error) { 74848b8605Smrg fprintf(stderr, "error: xp_attach_gl_context returned: %d\n", error); 75848b8605Smrg return true; 76848b8605Smrg } 77848b8605Smrg 78848b8605Smrg 79848b8605Smrg if (!ac->made_current) { 80848b8605Smrg /* 81848b8605Smrg * The first time a new context is made current the glViewport 82848b8605Smrg * and glScissor should be updated. 83848b8605Smrg */ 84848b8605Smrg update_viewport_and_scissor(ac->drawable->display, 85848b8605Smrg ac->drawable->drawable); 86848b8605Smrg ac->made_current = true; 87848b8605Smrg } 88848b8605Smrg 89848b8605Smrg apple_glx_diagnostic("%s: drawable 0x%lx\n", __func__, d->drawable); 90848b8605Smrg 91848b8605Smrg return false; 92848b8605Smrg} 93848b8605Smrg 94848b8605Smrgstatic void 95848b8605Smrgsurface_destroy(Display * dpy, struct apple_glx_drawable *d) 96848b8605Smrg{ 97848b8605Smrg struct apple_glx_surface *s = &d->types.surface; 98848b8605Smrg 99848b8605Smrg apple_glx_diagnostic("%s: s->surface_id %u\n", __func__, s->surface_id); 100848b8605Smrg 101848b8605Smrg xp_error error = xp_destroy_surface(s->surface_id); 102848b8605Smrg 103848b8605Smrg if (error) { 104848b8605Smrg fprintf(stderr, "xp_destroy_surface error: %d\n", (int) error); 105848b8605Smrg } 106848b8605Smrg 107848b8605Smrg /* 108848b8605Smrg * Check if this surface destroy came from the surface being destroyed 109848b8605Smrg * on the server. If s->pending_destroy is true, then it did, and 110848b8605Smrg * we don't want to try to destroy the surface on the server. 111848b8605Smrg */ 112848b8605Smrg if (!s->pending_destroy) { 113848b8605Smrg /* 114848b8605Smrg * Warning: this causes other routines to be called (potentially) 115848b8605Smrg * from surface_notify_handler. It's probably best to not have 116848b8605Smrg * any locks at this point locked. 117848b8605Smrg */ 118848b8605Smrg XAppleDRIDestroySurface(d->display, DefaultScreen(d->display), 119848b8605Smrg d->drawable); 120848b8605Smrg 121848b8605Smrg apple_glx_diagnostic 122848b8605Smrg ("%s: destroyed a surface for drawable 0x%lx uid %u\n", __func__, 123848b8605Smrg d->drawable, s->uid); 124848b8605Smrg } 125848b8605Smrg} 126848b8605Smrg 127b8e80941Smrg/* Return true if an error occurred. */ 128848b8605Smrgstatic bool 129848b8605Smrgcreate_surface(Display * dpy, int screen, struct apple_glx_drawable *d) 130848b8605Smrg{ 131848b8605Smrg struct apple_glx_surface *s = &d->types.surface; 132848b8605Smrg unsigned int key[2]; 133848b8605Smrg xp_client_id id; 134848b8605Smrg 135848b8605Smrg id = apple_glx_get_client_id(); 136848b8605Smrg if (0 == id) 137848b8605Smrg return true; 138848b8605Smrg 139848b8605Smrg assert(None != d->drawable); 140848b8605Smrg 141848b8605Smrg s->pending_destroy = false; 142848b8605Smrg 143848b8605Smrg if (XAppleDRICreateSurface(dpy, screen, d->drawable, id, key, &s->uid)) { 144848b8605Smrg xp_error error; 145848b8605Smrg 146848b8605Smrg error = xp_import_surface(key, &s->surface_id); 147848b8605Smrg 148848b8605Smrg if (error) { 149848b8605Smrg fprintf(stderr, "error: xp_import_surface returned: %d\n", error); 150848b8605Smrg return true; 151848b8605Smrg } 152848b8605Smrg 153848b8605Smrg apple_glx_diagnostic("%s: created a surface for drawable 0x%lx" 154848b8605Smrg " with uid %u\n", __func__, d->drawable, s->uid); 155848b8605Smrg return false; /*success */ 156848b8605Smrg } 157848b8605Smrg 158848b8605Smrg return true; /* unable to create a surface. */ 159848b8605Smrg} 160848b8605Smrg 161b8e80941Smrg/* Return true if an error occurred. */ 162848b8605Smrg/* This returns a referenced object via resultptr. */ 163848b8605Smrgbool 164848b8605Smrgapple_glx_surface_create(Display * dpy, int screen, 165848b8605Smrg GLXDrawable drawable, 166848b8605Smrg struct apple_glx_drawable ** resultptr) 167848b8605Smrg{ 168848b8605Smrg struct apple_glx_drawable *d; 169848b8605Smrg 170848b8605Smrg if (apple_glx_drawable_create(dpy, screen, drawable, &d, &callbacks)) 171848b8605Smrg return true; 172848b8605Smrg 173848b8605Smrg /* apple_glx_drawable_create creates a locked and referenced object. */ 174848b8605Smrg 175848b8605Smrg if (create_surface(dpy, screen, d)) { 176848b8605Smrg d->unlock(d); 177848b8605Smrg d->destroy(d); 178848b8605Smrg return true; 179848b8605Smrg } 180848b8605Smrg 181848b8605Smrg *resultptr = d; 182848b8605Smrg 183848b8605Smrg d->unlock(d); 184848b8605Smrg 185848b8605Smrg return false; 186848b8605Smrg} 187848b8605Smrg 188848b8605Smrg/* 189848b8605Smrg * All surfaces are reference counted, and surfaces are only created 190848b8605Smrg * when the window is made current. When all contexts no longer reference 191848b8605Smrg * a surface drawable the apple_glx_drawable gets destroyed, and thus 192848b8605Smrg * its surface is destroyed. 193848b8605Smrg * 194848b8605Smrg * However we can make the destruction occur a bit sooner by setting 195848b8605Smrg * pending_destroy, which is then checked for in glViewport by 196848b8605Smrg * apple_glx_context_update. 197848b8605Smrg */ 198848b8605Smrgvoid 199848b8605Smrgapple_glx_surface_destroy(unsigned int uid) 200848b8605Smrg{ 201848b8605Smrg struct apple_glx_drawable *d; 202848b8605Smrg 203848b8605Smrg d = apple_glx_drawable_find_by_uid(uid, APPLE_GLX_DRAWABLE_REFERENCE 204848b8605Smrg | APPLE_GLX_DRAWABLE_LOCK); 205848b8605Smrg 206848b8605Smrg if (d) { 207848b8605Smrg d->types.surface.pending_destroy = true; 208848b8605Smrg d->release(d); 209848b8605Smrg 210848b8605Smrg /* 211848b8605Smrg * We release 2 references to the surface. One was acquired by 212848b8605Smrg * the find, and the other was leftover from a context, or 213848b8605Smrg * the surface being displayed, so the destroy() will decrease it 214848b8605Smrg * once more. 215848b8605Smrg * 216848b8605Smrg * If the surface is in a context, it will take one d->destroy(d); 217848b8605Smrg * to actually destroy it when the pending_destroy is processed 218848b8605Smrg * by a glViewport callback (see apple_glx_context_update()). 219848b8605Smrg */ 220848b8605Smrg if (!d->destroy(d)) { 221848b8605Smrg /* apple_glx_drawable_find_by_uid returns a locked drawable */ 222848b8605Smrg d->unlock(d); 223848b8605Smrg } 224848b8605Smrg } 225848b8605Smrg} 226