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