1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci Copyright (c) 2009 Apple Inc. 3bf215546Sopenharmony_ci 4bf215546Sopenharmony_ci Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci obtaining a copy of this software and associated documentation files 6bf215546Sopenharmony_ci (the "Software"), to deal in the Software without restriction, 7bf215546Sopenharmony_ci including without limitation the rights to use, copy, modify, merge, 8bf215546Sopenharmony_ci publish, distribute, sublicense, and/or sell copies of the Software, 9bf215546Sopenharmony_ci and to permit persons to whom the Software is furnished to do so, 10bf215546Sopenharmony_ci subject to the following conditions: 11bf215546Sopenharmony_ci 12bf215546Sopenharmony_ci The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci 15bf215546Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 19bf215546Sopenharmony_ci HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20bf215546Sopenharmony_ci WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21bf215546Sopenharmony_ci OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22bf215546Sopenharmony_ci DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci Except as contained in this notice, the name(s) of the above 25bf215546Sopenharmony_ci copyright holders shall not be used in advertising or otherwise to 26bf215546Sopenharmony_ci promote the sale, use or other dealings in this Software without 27bf215546Sopenharmony_ci prior written authorization. 28bf215546Sopenharmony_ci*/ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci/* Must be before OpenGL.framework is included. Remove once fixed: 31bf215546Sopenharmony_ci * <rdar://problem/7872773> 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci#include <GL/gl.h> 34bf215546Sopenharmony_ci#include <GL/glext.h> 35bf215546Sopenharmony_ci#define __gltypes_h_ 1 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/* Must be first for: 38bf215546Sopenharmony_ci * <rdar://problem/6953344> 39bf215546Sopenharmony_ci */ 40bf215546Sopenharmony_ci#include "apple_glx_context.h" 41bf215546Sopenharmony_ci#include "apple_glx_drawable.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#include <stdbool.h> 44bf215546Sopenharmony_ci#include <stdlib.h> 45bf215546Sopenharmony_ci#include <pthread.h> 46bf215546Sopenharmony_ci#include <assert.h> 47bf215546Sopenharmony_ci#include "glxclient.h" 48bf215546Sopenharmony_ci#include "apple_glx.h" 49bf215546Sopenharmony_ci#include "glxconfig.h" 50bf215546Sopenharmony_ci#include "apple_cgl.h" 51bf215546Sopenharmony_ci#include "util/debug.h" 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci/* mesa defines in glew.h, Apple in glext.h. 54bf215546Sopenharmony_ci * Due to namespace nightmares, just do it here. 55bf215546Sopenharmony_ci */ 56bf215546Sopenharmony_ci#ifndef GL_TEXTURE_RECTANGLE_EXT 57bf215546Sopenharmony_ci#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 58bf215546Sopenharmony_ci#endif 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic bool pbuffer_make_current(struct apple_glx_context *ac, 61bf215546Sopenharmony_ci struct apple_glx_drawable *d); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic void pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_cistatic struct apple_glx_drawable_callbacks callbacks = { 66bf215546Sopenharmony_ci .type = APPLE_GLX_DRAWABLE_PBUFFER, 67bf215546Sopenharmony_ci .make_current = pbuffer_make_current, 68bf215546Sopenharmony_ci .destroy = pbuffer_destroy 69bf215546Sopenharmony_ci}; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci/* Return true if an error occurred. */ 73bf215546Sopenharmony_cibool 74bf215546Sopenharmony_cipbuffer_make_current(struct apple_glx_context *ac, 75bf215546Sopenharmony_ci struct apple_glx_drawable *d) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci struct apple_glx_pbuffer *pbuf = &d->types.pbuffer; 78bf215546Sopenharmony_ci CGLError cglerr; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci cglerr = apple_cgl.set_pbuffer(ac->context_obj, pbuf->buffer_obj, 0, 0, 0); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci if (kCGLNoError != cglerr) { 85bf215546Sopenharmony_ci fprintf(stderr, "set_pbuffer: %s\n", apple_cgl.error_string(cglerr)); 86bf215546Sopenharmony_ci return true; 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci if (!ac->made_current) { 90bf215546Sopenharmony_ci apple_glapi_oglfw_viewport_scissor(0, 0, pbuf->width, pbuf->height); 91bf215546Sopenharmony_ci ac->made_current = true; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci apple_glx_diagnostic("made pbuffer drawable 0x%lx current\n", d->drawable); 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci return false; 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_civoid 100bf215546Sopenharmony_cipbuffer_destroy(Display * dpy, struct apple_glx_drawable *d) 101bf215546Sopenharmony_ci{ 102bf215546Sopenharmony_ci struct apple_glx_pbuffer *pbuf = &d->types.pbuffer; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci apple_glx_diagnostic("destroying pbuffer for drawable 0x%lx\n", 107bf215546Sopenharmony_ci d->drawable); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci apple_cgl.destroy_pbuffer(pbuf->buffer_obj); 110bf215546Sopenharmony_ci XFreePixmap(dpy, pbuf->xid); 111bf215546Sopenharmony_ci} 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci/* Return true if an error occurred. */ 114bf215546Sopenharmony_cibool 115bf215546Sopenharmony_ciapple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf) 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci return !apple_glx_drawable_destroy_by_type(dpy, pbuf, 118bf215546Sopenharmony_ci APPLE_GLX_DRAWABLE_PBUFFER); 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci/* Return true if an error occurred. */ 122bf215546Sopenharmony_cibool 123bf215546Sopenharmony_ciapple_glx_pbuffer_create(Display * dpy, GLXFBConfig config, 124bf215546Sopenharmony_ci int width, int height, int *errorcode, 125bf215546Sopenharmony_ci GLXPbuffer * result) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci struct apple_glx_drawable *d; 128bf215546Sopenharmony_ci struct apple_glx_pbuffer *pbuf = NULL; 129bf215546Sopenharmony_ci CGLError err; 130bf215546Sopenharmony_ci Window root; 131bf215546Sopenharmony_ci int screen; 132bf215546Sopenharmony_ci Pixmap xid; 133bf215546Sopenharmony_ci struct glx_config *modes = (struct glx_config *) config; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci root = DefaultRootWindow(dpy); 136bf215546Sopenharmony_ci screen = DefaultScreen(dpy); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* 139bf215546Sopenharmony_ci * This pixmap is only used for a persistent XID. 140bf215546Sopenharmony_ci * The XC-MISC extension cleans up XIDs and reuses them transparently, 141bf215546Sopenharmony_ci * so we need to retain a server-side reference. 142bf215546Sopenharmony_ci */ 143bf215546Sopenharmony_ci xid = XCreatePixmap(dpy, root, (unsigned int) 1, 144bf215546Sopenharmony_ci (unsigned int) 1, DefaultDepth(dpy, screen)); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (None == xid) { 147bf215546Sopenharmony_ci *errorcode = BadAlloc; 148bf215546Sopenharmony_ci return true; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if (apple_glx_drawable_create(dpy, screen, xid, &d, &callbacks)) { 152bf215546Sopenharmony_ci *errorcode = BadAlloc; 153bf215546Sopenharmony_ci return true; 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci /* The lock is held in d from create onward. */ 157bf215546Sopenharmony_ci pbuf = &d->types.pbuffer; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci pbuf->xid = xid; 160bf215546Sopenharmony_ci pbuf->width = width; 161bf215546Sopenharmony_ci pbuf->height = height; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci err = apple_cgl.create_pbuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, 164bf215546Sopenharmony_ci (modes->alphaBits > 0) ? GL_RGBA : GL_RGB, 165bf215546Sopenharmony_ci 0, &pbuf->buffer_obj); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (kCGLNoError != err) { 168bf215546Sopenharmony_ci d->unlock(d); 169bf215546Sopenharmony_ci d->destroy(d); 170bf215546Sopenharmony_ci *errorcode = BadMatch; 171bf215546Sopenharmony_ci return true; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci pbuf->fbconfigID = modes->fbconfigID; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci pbuf->event_mask = 0; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci *result = pbuf->xid; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci d->unlock(d); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci return false; 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci/* Return true if an error occurred. */ 188bf215546Sopenharmony_cistatic bool 189bf215546Sopenharmony_ciget_max_size(int *widthresult, int *heightresult) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci CGLContextObj oldcontext; 192bf215546Sopenharmony_ci GLint ar[2]; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci oldcontext = apple_cgl.get_current_context(); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci if (!oldcontext) { 197bf215546Sopenharmony_ci /* 198bf215546Sopenharmony_ci * There is no current context, so we need to make one in order 199bf215546Sopenharmony_ci * to call glGetInteger. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_ci CGLPixelFormatObj pfobj; 202bf215546Sopenharmony_ci CGLError err; 203bf215546Sopenharmony_ci CGLPixelFormatAttribute attr[10]; 204bf215546Sopenharmony_ci int c = 0; 205bf215546Sopenharmony_ci GLint vsref = 0; 206bf215546Sopenharmony_ci CGLContextObj newcontext; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci attr[c++] = kCGLPFAColorSize; 209bf215546Sopenharmony_ci attr[c++] = 32; 210bf215546Sopenharmony_ci attr[c++] = 0; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref); 213bf215546Sopenharmony_ci if (kCGLNoError != err) { 214bf215546Sopenharmony_ci DebugMessageF("choose_pixel_format error in %s: %s\n", __func__, 215bf215546Sopenharmony_ci apple_cgl.error_string(err)); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci return true; 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci err = apple_cgl.create_context(pfobj, NULL, &newcontext); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci if (kCGLNoError != err) { 224bf215546Sopenharmony_ci DebugMessageF("create_context error in %s: %s\n", __func__, 225bf215546Sopenharmony_ci apple_cgl.error_string(err)); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci apple_cgl.destroy_pixel_format(pfobj); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci return true; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci err = apple_cgl.set_current_context(newcontext); 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci if (kCGLNoError != err) { 235bf215546Sopenharmony_ci DebugMessageF("set_current_context error in %s: %s\n", __func__, 236bf215546Sopenharmony_ci apple_cgl.error_string(err)); 237bf215546Sopenharmony_ci return true; 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci apple_cgl.set_current_context(oldcontext); 244bf215546Sopenharmony_ci apple_cgl.destroy_context(newcontext); 245bf215546Sopenharmony_ci apple_cgl.destroy_pixel_format(pfobj); 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci else { 248bf215546Sopenharmony_ci /* We have a valid context. */ 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar); 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci *widthresult = ar[0]; 254bf215546Sopenharmony_ci *heightresult = ar[1]; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci return false; 257bf215546Sopenharmony_ci} 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_cibool 260bf215546Sopenharmony_ciapple_glx_pbuffer_query(GLXPbuffer p, int attr, unsigned int *value) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci bool result = false; 263bf215546Sopenharmony_ci struct apple_glx_drawable *d; 264bf215546Sopenharmony_ci struct apple_glx_pbuffer *pbuf; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci d = apple_glx_drawable_find_by_type(p, APPLE_GLX_DRAWABLE_PBUFFER, 267bf215546Sopenharmony_ci APPLE_GLX_DRAWABLE_LOCK); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci if (d) { 270bf215546Sopenharmony_ci pbuf = &d->types.pbuffer; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci switch (attr) { 273bf215546Sopenharmony_ci case GLX_WIDTH: 274bf215546Sopenharmony_ci *value = pbuf->width; 275bf215546Sopenharmony_ci result = true; 276bf215546Sopenharmony_ci break; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci case GLX_HEIGHT: 279bf215546Sopenharmony_ci *value = pbuf->height; 280bf215546Sopenharmony_ci result = true; 281bf215546Sopenharmony_ci break; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci case GLX_PRESERVED_CONTENTS: 284bf215546Sopenharmony_ci *value = true; 285bf215546Sopenharmony_ci result = true; 286bf215546Sopenharmony_ci break; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci case GLX_LARGEST_PBUFFER:{ 289bf215546Sopenharmony_ci int width, height; 290bf215546Sopenharmony_ci if (get_max_size(&width, &height)) { 291bf215546Sopenharmony_ci fprintf(stderr, "internal error: " 292bf215546Sopenharmony_ci "unable to find the largest pbuffer!\n"); 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci else { 295bf215546Sopenharmony_ci *value = width; 296bf215546Sopenharmony_ci result = true; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci break; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci case GLX_FBCONFIG_ID: 302bf215546Sopenharmony_ci *value = pbuf->fbconfigID; 303bf215546Sopenharmony_ci result = true; 304bf215546Sopenharmony_ci break; 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci d->unlock(d); 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci return result; 311bf215546Sopenharmony_ci} 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_cibool 314bf215546Sopenharmony_ciapple_glx_pbuffer_set_event_mask(GLXDrawable drawable, unsigned long mask) 315bf215546Sopenharmony_ci{ 316bf215546Sopenharmony_ci struct apple_glx_drawable *d; 317bf215546Sopenharmony_ci bool result = false; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER, 320bf215546Sopenharmony_ci APPLE_GLX_DRAWABLE_LOCK); 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci if (d) { 323bf215546Sopenharmony_ci d->types.pbuffer.event_mask = mask; 324bf215546Sopenharmony_ci result = true; 325bf215546Sopenharmony_ci d->unlock(d); 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci return result; 329bf215546Sopenharmony_ci} 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_cibool 332bf215546Sopenharmony_ciapple_glx_pbuffer_get_event_mask(GLXDrawable drawable, unsigned long *mask) 333bf215546Sopenharmony_ci{ 334bf215546Sopenharmony_ci struct apple_glx_drawable *d; 335bf215546Sopenharmony_ci bool result = false; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER, 338bf215546Sopenharmony_ci APPLE_GLX_DRAWABLE_LOCK); 339bf215546Sopenharmony_ci if (d) { 340bf215546Sopenharmony_ci *mask = d->types.pbuffer.event_mask; 341bf215546Sopenharmony_ci result = true; 342bf215546Sopenharmony_ci d->unlock(d); 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci return result; 346bf215546Sopenharmony_ci} 347