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#include <assert.h> 303464ebd5Sriastradh#include "glxclient.h" 313464ebd5Sriastradh#include "apple_glx.h" 323464ebd5Sriastradh#include "appledri.h" 333464ebd5Sriastradh#include "apple_glx_drawable.h" 343464ebd5Sriastradh 353464ebd5Sriastradhstatic bool surface_make_current(struct apple_glx_context *ac, 363464ebd5Sriastradh struct apple_glx_drawable *d); 373464ebd5Sriastradh 383464ebd5Sriastradhstatic void surface_destroy(Display * dpy, struct apple_glx_drawable *d); 393464ebd5Sriastradh 403464ebd5Sriastradh 413464ebd5Sriastradhstatic struct apple_glx_drawable_callbacks callbacks = { 423464ebd5Sriastradh .type = APPLE_GLX_DRAWABLE_SURFACE, 433464ebd5Sriastradh .make_current = surface_make_current, 443464ebd5Sriastradh .destroy = surface_destroy 453464ebd5Sriastradh}; 463464ebd5Sriastradh 473464ebd5Sriastradhstatic void 483464ebd5Sriastradhupdate_viewport_and_scissor(Display * dpy, GLXDrawable drawable) 493464ebd5Sriastradh{ 503464ebd5Sriastradh Window root; 513464ebd5Sriastradh int x, y; 523464ebd5Sriastradh unsigned int width = 0, height = 0, bd, depth; 533464ebd5Sriastradh 543464ebd5Sriastradh XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth); 553464ebd5Sriastradh 563464ebd5Sriastradh apple_glapi_oglfw_viewport_scissor(0, 0, width, height); 573464ebd5Sriastradh} 583464ebd5Sriastradh 593464ebd5Sriastradhstatic bool 603464ebd5Sriastradhsurface_make_current(struct apple_glx_context *ac, 613464ebd5Sriastradh struct apple_glx_drawable *d) 623464ebd5Sriastradh{ 633464ebd5Sriastradh struct apple_glx_surface *s = &d->types.surface; 643464ebd5Sriastradh xp_error error; 653464ebd5Sriastradh 663464ebd5Sriastradh assert(APPLE_GLX_DRAWABLE_SURFACE == d->type); 673464ebd5Sriastradh 683464ebd5Sriastradh apple_glx_diagnostic("%s: ac->context_obj %p s->surface_id %u\n", 693464ebd5Sriastradh __func__, (void *) ac->context_obj, s->surface_id); 703464ebd5Sriastradh 713464ebd5Sriastradh error = xp_attach_gl_context(ac->context_obj, s->surface_id); 723464ebd5Sriastradh 733464ebd5Sriastradh if (error) { 743464ebd5Sriastradh fprintf(stderr, "error: xp_attach_gl_context returned: %d\n", error); 753464ebd5Sriastradh return true; 763464ebd5Sriastradh } 773464ebd5Sriastradh 783464ebd5Sriastradh 793464ebd5Sriastradh if (!ac->made_current) { 803464ebd5Sriastradh /* 813464ebd5Sriastradh * The first time a new context is made current the glViewport 823464ebd5Sriastradh * and glScissor should be updated. 833464ebd5Sriastradh */ 843464ebd5Sriastradh update_viewport_and_scissor(ac->drawable->display, 853464ebd5Sriastradh ac->drawable->drawable); 863464ebd5Sriastradh ac->made_current = true; 873464ebd5Sriastradh } 883464ebd5Sriastradh 893464ebd5Sriastradh apple_glx_diagnostic("%s: drawable 0x%lx\n", __func__, d->drawable); 903464ebd5Sriastradh 913464ebd5Sriastradh return false; 923464ebd5Sriastradh} 933464ebd5Sriastradh 943464ebd5Sriastradhstatic void 953464ebd5Sriastradhsurface_destroy(Display * dpy, struct apple_glx_drawable *d) 963464ebd5Sriastradh{ 973464ebd5Sriastradh struct apple_glx_surface *s = &d->types.surface; 983464ebd5Sriastradh 993464ebd5Sriastradh apple_glx_diagnostic("%s: s->surface_id %u\n", __func__, s->surface_id); 1003464ebd5Sriastradh 1013464ebd5Sriastradh xp_error error = xp_destroy_surface(s->surface_id); 1023464ebd5Sriastradh 1033464ebd5Sriastradh if (error) { 1043464ebd5Sriastradh fprintf(stderr, "xp_destroy_surface error: %d\n", (int) error); 1053464ebd5Sriastradh } 1063464ebd5Sriastradh 1073464ebd5Sriastradh /* 1083464ebd5Sriastradh * Check if this surface destroy came from the surface being destroyed 1093464ebd5Sriastradh * on the server. If s->pending_destroy is true, then it did, and 1103464ebd5Sriastradh * we don't want to try to destroy the surface on the server. 1113464ebd5Sriastradh */ 1123464ebd5Sriastradh if (!s->pending_destroy) { 1133464ebd5Sriastradh /* 1143464ebd5Sriastradh * Warning: this causes other routines to be called (potentially) 1153464ebd5Sriastradh * from surface_notify_handler. It's probably best to not have 1163464ebd5Sriastradh * any locks at this point locked. 1173464ebd5Sriastradh */ 1183464ebd5Sriastradh XAppleDRIDestroySurface(d->display, DefaultScreen(d->display), 1193464ebd5Sriastradh d->drawable); 1203464ebd5Sriastradh 1213464ebd5Sriastradh apple_glx_diagnostic 1223464ebd5Sriastradh ("%s: destroyed a surface for drawable 0x%lx uid %u\n", __func__, 1233464ebd5Sriastradh d->drawable, s->uid); 1243464ebd5Sriastradh } 1253464ebd5Sriastradh} 1263464ebd5Sriastradh 12701e04c3fSmrg/* Return true if an error occurred. */ 1283464ebd5Sriastradhstatic bool 1293464ebd5Sriastradhcreate_surface(Display * dpy, int screen, struct apple_glx_drawable *d) 1303464ebd5Sriastradh{ 1313464ebd5Sriastradh struct apple_glx_surface *s = &d->types.surface; 1323464ebd5Sriastradh unsigned int key[2]; 1333464ebd5Sriastradh xp_client_id id; 1343464ebd5Sriastradh 1353464ebd5Sriastradh id = apple_glx_get_client_id(); 1363464ebd5Sriastradh if (0 == id) 1373464ebd5Sriastradh return true; 1383464ebd5Sriastradh 1393464ebd5Sriastradh assert(None != d->drawable); 1403464ebd5Sriastradh 1413464ebd5Sriastradh s->pending_destroy = false; 1423464ebd5Sriastradh 1433464ebd5Sriastradh if (XAppleDRICreateSurface(dpy, screen, d->drawable, id, key, &s->uid)) { 1443464ebd5Sriastradh xp_error error; 1453464ebd5Sriastradh 1463464ebd5Sriastradh error = xp_import_surface(key, &s->surface_id); 1473464ebd5Sriastradh 1483464ebd5Sriastradh if (error) { 1493464ebd5Sriastradh fprintf(stderr, "error: xp_import_surface returned: %d\n", error); 1503464ebd5Sriastradh return true; 1513464ebd5Sriastradh } 1523464ebd5Sriastradh 1533464ebd5Sriastradh apple_glx_diagnostic("%s: created a surface for drawable 0x%lx" 1543464ebd5Sriastradh " with uid %u\n", __func__, d->drawable, s->uid); 1553464ebd5Sriastradh return false; /*success */ 1563464ebd5Sriastradh } 1573464ebd5Sriastradh 1583464ebd5Sriastradh return true; /* unable to create a surface. */ 1593464ebd5Sriastradh} 1603464ebd5Sriastradh 16101e04c3fSmrg/* Return true if an error occurred. */ 1623464ebd5Sriastradh/* This returns a referenced object via resultptr. */ 1633464ebd5Sriastradhbool 1643464ebd5Sriastradhapple_glx_surface_create(Display * dpy, int screen, 1653464ebd5Sriastradh GLXDrawable drawable, 1663464ebd5Sriastradh struct apple_glx_drawable ** resultptr) 1673464ebd5Sriastradh{ 1683464ebd5Sriastradh struct apple_glx_drawable *d; 1693464ebd5Sriastradh 1703464ebd5Sriastradh if (apple_glx_drawable_create(dpy, screen, drawable, &d, &callbacks)) 1713464ebd5Sriastradh return true; 1723464ebd5Sriastradh 1733464ebd5Sriastradh /* apple_glx_drawable_create creates a locked and referenced object. */ 1743464ebd5Sriastradh 1753464ebd5Sriastradh if (create_surface(dpy, screen, d)) { 1763464ebd5Sriastradh d->unlock(d); 1773464ebd5Sriastradh d->destroy(d); 1783464ebd5Sriastradh return true; 1793464ebd5Sriastradh } 1803464ebd5Sriastradh 1813464ebd5Sriastradh *resultptr = d; 1823464ebd5Sriastradh 1833464ebd5Sriastradh d->unlock(d); 1843464ebd5Sriastradh 1853464ebd5Sriastradh return false; 1863464ebd5Sriastradh} 1873464ebd5Sriastradh 1883464ebd5Sriastradh/* 1893464ebd5Sriastradh * All surfaces are reference counted, and surfaces are only created 1903464ebd5Sriastradh * when the window is made current. When all contexts no longer reference 1913464ebd5Sriastradh * a surface drawable the apple_glx_drawable gets destroyed, and thus 1923464ebd5Sriastradh * its surface is destroyed. 1933464ebd5Sriastradh * 1943464ebd5Sriastradh * However we can make the destruction occur a bit sooner by setting 1953464ebd5Sriastradh * pending_destroy, which is then checked for in glViewport by 1963464ebd5Sriastradh * apple_glx_context_update. 1973464ebd5Sriastradh */ 1983464ebd5Sriastradhvoid 1993464ebd5Sriastradhapple_glx_surface_destroy(unsigned int uid) 2003464ebd5Sriastradh{ 2013464ebd5Sriastradh struct apple_glx_drawable *d; 2023464ebd5Sriastradh 2033464ebd5Sriastradh d = apple_glx_drawable_find_by_uid(uid, APPLE_GLX_DRAWABLE_REFERENCE 2043464ebd5Sriastradh | APPLE_GLX_DRAWABLE_LOCK); 2053464ebd5Sriastradh 2063464ebd5Sriastradh if (d) { 2073464ebd5Sriastradh d->types.surface.pending_destroy = true; 2083464ebd5Sriastradh d->release(d); 209af69d88dSmrg 2103464ebd5Sriastradh /* 2113464ebd5Sriastradh * We release 2 references to the surface. One was acquired by 2123464ebd5Sriastradh * the find, and the other was leftover from a context, or 2133464ebd5Sriastradh * the surface being displayed, so the destroy() will decrease it 2143464ebd5Sriastradh * once more. 2153464ebd5Sriastradh * 2163464ebd5Sriastradh * If the surface is in a context, it will take one d->destroy(d); 2173464ebd5Sriastradh * to actually destroy it when the pending_destroy is processed 2183464ebd5Sriastradh * by a glViewport callback (see apple_glx_context_update()). 2193464ebd5Sriastradh */ 220af69d88dSmrg if (!d->destroy(d)) { 221af69d88dSmrg /* apple_glx_drawable_find_by_uid returns a locked drawable */ 222af69d88dSmrg d->unlock(d); 223af69d88dSmrg } 2243464ebd5Sriastradh } 2253464ebd5Sriastradh} 226