/** * Try to create a GLX context of the newest version. */ static GLXContext create_context_with_config(Display *dpy, GLXFBConfig config, Bool coreProfile, Bool es2Profile, Bool direct) { GLXContext ctx = 0; if (coreProfile) { /* Try to create a core profile, starting with the newest version of * GL that we're aware of. If we don't specify the version */ int i; for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) { /* don't bother below GL 3.0 */ if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) return 0; ctx = create_context_flags(dpy, config, gl_versions[i].major, gl_versions[i].minor, 0x0, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, direct); if (ctx) return ctx; } /* couldn't get core profile context */ return 0; } if (es2Profile) { #ifdef GLX_CONTEXT_ES2_PROFILE_BIT_EXT if (extension_supported("GLX_EXT_create_context_es2_profile", glXQueryExtensionsString(dpy, 0))) { ctx = create_context_flags(dpy, config, 2, 0, 0x0, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, direct); return ctx; } #endif return 0; } /* GLX should return a context of the latest GL version that supports * the full profile. */ ctx = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, direct); /* make sure the context is direct, if direct was requested */ if (ctx && direct) { if (!glXIsDirect(dpy, ctx)) { glXDestroyContext(dpy, ctx); return 0; } } return ctx; }
static void init_ocl_device(QSP_ARG_DECL cl_device_id dev_id, Compute_Platform *cpp) { cl_int status; //long param_data[MAX_PARAM_SIZE/sizeof(long)]; // force alignment //char name[LLEN]; static int n_ocl_devs=0; Platform_Device *pdp; CGLContextObj cgl_ctx=NULL; cl_context context; cl_command_queue command_queue; //"stream" in CUDA cl_context_properties props[3]={ CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, 0, // need to put cgl_ctx here 0 }; pdp = create_ocl_device(QSP_ARG dev_id, cpp); if( pdp == NULL ) return; /* Remember this name in case the default is not found */ if( first_ocl_dev_name == NULL ) first_ocl_dev_name = PFDEV_NAME(pdp); /* Compare this name against the default name set in * the environment, if it exists... */ if( default_ocl_dev_name != NULL && ! default_ocl_dev_found ){ if( !strcmp(PFDEV_NAME(pdp),default_ocl_dev_name) ) default_ocl_dev_found=1; } get_extensions(QSP_ARG pdp); SET_OCLDEV_DEV_ID(pdp,dev_id); SET_PFDEV_PLATFORM(pdp,cpp); if( n_ocl_devs >= MAX_OPENCL_DEVICES ){ sprintf(ERROR_STRING,"More than %d OpenCL devices found;" "need to increase MAX_OPENCL_DEVICES and recompile", MAX_OPENCL_DEVICES); error1(ERROR_STRING); } fprintf(stderr,"Setting %s device index to %d\n",PFDEV_NAME(pdp),n_ocl_devs); SET_PFDEV_SERIAL(pdp,n_ocl_devs++); SET_PFDEV_MAX_DIMS(pdp,DEFAULT_PFDEV_MAX_DIMS); // On the new MacBook Pro, with two devices, the Iris_Pro // throws an error at clCreateCommandQueue *iff* we set // the share group property here... Presumably because // that device doesn't handle the display? // We insert a hack below by excluding that device name, // but maybe there is another model where that would be // inappropriate? if( extension_supported(pdp,"cl_APPLE_gl_sharing") && strcmp(PFDEV_NAME(pdp),"Iris_Pro")){ CGLShareGroupObj share_group; cgl_ctx = CGLGetCurrentContext(); if( cgl_ctx != NULL){ // This means that we have an OpenGL window available... share_group = CGLGetShareGroup(cgl_ctx); assert( share_group != NULL ); props[1] = (cl_context_properties) share_group; } else { // If we let this go, it sometimes causes a seg fault // when we try to set the GL window afterwards!? // // But it should not be an error, because we don't know // for sure that we will ever attempt it. // We need to set a flag to prohibit it later... advise("init_ocl_device: OpenCL initialized without an OpenGL context;"); advise("init_ocl_device: Prohibiting OpenGL operations."); prohibit_opengl(); } } // Check for OpenGL capabilities //opengl_check(pdp); #ifdef TAKEN_FROM_DEMO_PROG #if (USE_GL_ATTACHMENTS) printf(SEPARATOR); printf("Using active OpenGL context...\n"); CGLContextObj kCGLContext = CGLGetCurrentContext(); CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); cl_context_properties properties[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup, 0 }; // Create a context from a CGL share group // ComputeContext = clCreateContext(properties, 0, 0, clLogMessagesToStdoutAPPLE, 0, 0); if(!ComputeContext) return -2; #else // ! USE_GL_ATTACHMENTS // Connect to a compute device // err = clGetDeviceIDs(NULL, ComputeDeviceType, 1, &ComputeDeviceId, NULL); if (err != CL_SUCCESS) { printf("Error: Failed to locate compute device!\n"); return EXIT_FAILURE; } // Create a compute context // ComputeContext = clCreateContext(0, 1, &ComputeDeviceId, clLogMessagesToStdoutAPPLE, NULL, &err); if (!ComputeContext) { printf("Error: Failed to create a compute context!\n"); return EXIT_FAILURE; } #endif // ! USE_GL_ATTACHMENTS #endif // TAKEN_FROM_DEMO_PROG //create context on the specified device //if( cgl_ctx != NULL ) //fprintf(stderr,"creating clContext with share properties for %s...\n",PFDEV_NAME(pdp)); if( cgl_ctx == NULL ){ context = clCreateContext( NULL, // cl_context_properties *properties 1, // num_devices &dev_id, // devices NULL, // void *pfn_notify(const char *errinfo, const void *private_info, size_t cb, void *user_data ) NULL, // void *user_data &status // cl_int *errcode_ret ); } else { context = clCreateContext( props, // cl_context_properties *properties 0, // num_devices NULL, // devices clLogMessagesToStdoutAPPLE, // void *pfn_notify(const char *errinfo, const void *private_info, size_t cb, void *user_data ) NULL, // void *user_data &status // cl_int *errcode_ret ); } if( status != CL_SUCCESS ){ report_ocl_error(status, "clCreateContext"); SET_OCLDEV_CTX(pdp,NULL); //return; } // BUG check return value for error SET_OCLDEV_CTX(pdp,context); //create the command_queue (stream) //fprintf(stderr,"clContext = 0x%lx...\n",(long)context); //fprintf(stderr,"init_ocl_device: dev_id = 0x%lx\n",(long)dev_id); // At least once we have gotten an invalid value error here, // after receiving the advisory "OpenCL initialized without an OpenGL context // (which may or may not be relevant). This behavior was not repeatable, // perhaps because of different stack contents??? // The third arg is a properties bit field, with valid values being: // CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE // CL_QUEUE_PROFILING_ENABLE command_queue = clCreateCommandQueue(context, dev_id, 0, &status); if( status != CL_SUCCESS ){ report_ocl_error(status, "clCreateCommandQueue"); SET_OCLDEV_QUEUE(pdp,NULL); //return; } else { SET_OCLDEV_QUEUE(pdp,command_queue); } // set a ready flag? init_ocl_dev_memory(QSP_ARG pdp); curr_pdp = pdp; }
/** * Print interesting OpenGL implementation limits. * \param version 20, 21, 30, 31, 32, etc. */ void print_limits(const char *extensions, const char *oglstring, int version, const struct ext_functions *extfuncs) { struct token_name { GLuint count; GLenum token; const char *name; const char *extension; /* NULL or GL extension name or version string */ }; static const struct token_name limits[] = { { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH", NULL }, { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", NULL }, { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES", NULL }, { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH", "GL_ARB_imaging" }, { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES", NULL }, { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES", NULL }, { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER", NULL }, { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS", NULL }, { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING", NULL }, { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH", NULL }, { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH", NULL }, { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE", NULL }, { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH", NULL }, { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH", NULL }, { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE", NULL }, { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE", NULL }, #if defined(GL_EXT_texture_array) { 1, GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, "GL_MAX_ARRAY_TEXTURE_LAYERS", "GL_EXT_texture_array" }, #endif { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS", NULL }, { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE", NULL }, { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE", NULL }, { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE", NULL }, { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE", NULL }, #if defined(GL_ARB_texture_cube_map) { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB", "GL_ARB_texture_cube_map" }, #endif #if defined(GL_NV_texture_rectangle) { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV", "GL_NV_texture_rectangle" }, #endif #if defined(GL_ARB_multitexture) { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB", "GL_ARB_multitexture" }, #endif #if defined(GL_EXT_texture_lod_bias) { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT", "GL_EXT_texture_lod_bias" }, #endif #if defined(GL_EXT_texture_filter_anisotropic) { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT", "GL_EXT_texture_filter_anisotropic" }, #endif #if defined(GL_ARB_draw_buffers) { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB", "GL_ARB_draw_buffers" }, #endif #if defined(GL_ARB_blend_func_extended) { 1, GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS", "GL_ARB_blend_func_extended" }, #endif #if defined (GL_ARB_framebuffer_object) { 1, GL_MAX_RENDERBUFFER_SIZE, "GL_MAX_RENDERBUFFER_SIZE", "GL_ARB_framebuffer_object" }, { 1, GL_MAX_COLOR_ATTACHMENTS, "GL_MAX_COLOR_ATTACHMENTS", "GL_ARB_framebuffer_object" }, { 1, GL_MAX_SAMPLES, "GL_MAX_SAMPLES", "GL_ARB_framebuffer_object" }, #endif #if defined (GL_EXT_transform_feedback) { 1, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS", "GL_EXT_transform_feedback" }, { 1, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", "GL_EXT_transform_feedback" }, { 1, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", "GL_EXT_transform_feedback", }, { 1, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", "GL_EXT_transform_feedback" }, #endif #if defined (GL_ARB_texture_buffer_object) { 1, GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT", "GL_ARB_texture_buffer_object" }, { 1, GL_MAX_TEXTURE_BUFFER_SIZE, "GL_MAX_TEXTURE_BUFFER_SIZE", "GL_ARB_texture_buffer_object" }, #endif #if defined (GL_ARB_texture_multisample) { 1, GL_MAX_COLOR_TEXTURE_SAMPLES, "GL_MAX_COLOR_TEXTURE_SAMPLES", "GL_ARB_texture_multisample" }, { 1, GL_MAX_DEPTH_TEXTURE_SAMPLES, "GL_MAX_DEPTH_TEXTURE_SAMPLES", "GL_ARB_texture_multisample" }, { 1, GL_MAX_INTEGER_SAMPLES, "GL_MAX_INTEGER_SAMPLES", "GL_ARB_texture_multisample" }, #endif #if defined (GL_ARB_uniform_buffer_object) { 1, GL_MAX_VERTEX_UNIFORM_BLOCKS, "GL_MAX_VERTEX_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, "GL_MAX_FRAGMENT_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_GEOMETRY_UNIFORM_BLOCKS, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS" , "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_UNIFORM_BLOCKS, "GL_MAX_COMBINED_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_UNIFORM_BUFFER_BINDINGS, "GL_MAX_UNIFORM_BUFFER_BINDINGS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_UNIFORM_BLOCK_SIZE, "GL_MAX_UNIFORM_BLOCK_SIZE", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT", "GL_ARB_uniform_buffer_object" }, #endif #if defined (GL_ARB_vertex_attrib_binding) { 1, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "GL_ARB_vertex_attrib_binding" }, { 1, GL_MAX_VERTEX_ATTRIB_BINDINGS, "GL_MAX_VERTEX_ATTRIB_BINDINGS", "GL_ARB_vertex_attrib_binding" }, #endif #if defined(GL_VERSION_4_4) { 1, GL_MAX_VERTEX_ATTRIB_STRIDE, "GL_MAX_VERTEX_ATTRIB_STRIDE", "4.4" }, #endif { 0, (GLenum) 0, NULL, NULL } }; GLint i, max[2]; printf("%s limits:\n", oglstring); for (i = 0; limits[i].count; i++) { if (!limits[i].extension || version_supported(limits[i].extension, version) || extension_supported(limits[i].extension, extensions)) { glGetIntegerv(limits[i].token, max); if (glGetError() == GL_NO_ERROR) { if (limits[i].count == 1) printf(" %s = %d\n", limits[i].name, max[0]); else /* XXX fix if we ever query something with more than 2 values */ printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]); } } } /* these don't fit into the above mechanism, unfortunately */ if (extension_supported("GL_ARB_imaging", extensions)) { extfuncs->GetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max); extfuncs->GetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1); printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]); } if (extension_supported("GL_ARB_texture_compression", extensions)) { GLint i, n; GLint *formats; glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &n); printf(" GL_NUM_COMPRESSED_TEXTURE_FORMATS = %d\n", n); formats = (GLint *) malloc(n * sizeof(GLint)); glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (i = 0; i < n; i++) { printf(" %s\n", enum_name(formats[i])); } free(formats); } #if defined(GL_ARB_vertex_program) if (extension_supported("GL_ARB_vertex_program", extensions)) { print_program_limits(GL_VERTEX_PROGRAM_ARB, extfuncs); } #endif #if defined(GL_ARB_fragment_program) if (extension_supported("GL_ARB_fragment_program", extensions)) { print_program_limits(GL_FRAGMENT_PROGRAM_ARB, extfuncs); } #endif if (extension_supported("GL_ARB_vertex_shader", extensions)) { print_shader_limits(GL_VERTEX_SHADER_ARB); } if (extension_supported("GL_ARB_fragment_shader", extensions)) { print_shader_limits(GL_FRAGMENT_SHADER_ARB); } if (version >= 32) { print_shader_limits(GL_GEOMETRY_SHADER); } }
static struct gbm_context * stereo_prepare_context(struct gbm_dev *dev, const struct gbm_options *options) { struct gbm_context *context; EGLint multiview_view_count = 0; context = xmalloc(sizeof(*context)); context->dev = dev; context->gbm = gbm_create_device(dev->fd); if (context->gbm == NULL) { fprintf(stderr, "error creating GBM device\n"); goto error; } context->edpy = eglGetDisplay((EGLNativeDisplayType) context->gbm); if (context->edpy == EGL_NO_DISPLAY) { fprintf(stderr, "error getting EGL display\n"); goto error_gbm_device; } if (!eglInitialize(context->edpy, NULL, NULL)) { fprintf(stderr, "error intializing EGL display\n"); goto error_gbm_device; } if (!extension_supported(context->edpy, MULTIVIEW_WINDOW_EXTENSION)) { fprintf(stderr, MULTIVIEW_WINDOW_EXTENSION " not supported\n"); goto error_egl_display; } if (create_gbm_surface(context)) goto error_egl_display; if (choose_egl_config(context)) goto error_gbm_surface; if (create_egl_surface(context, options)) goto error_gbm_surface; if (create_egl_context(context)) goto error_egl_surface; if (!eglMakeCurrent(context->edpy, context->egl_surface, context->egl_surface, context->egl_context)) { fprintf(stderr, "failed to make EGL context current\n"); goto error_egl_context; } if ((!eglQueryContext(context->edpy, context->egl_context, EGL_MULTIVIEW_VIEW_COUNT_EXT, &multiview_view_count) || multiview_view_count < 2)) { fprintf(stderr, "EGL created a multiview surface with only %i %s\n", multiview_view_count, multiview_view_count == 1 ? "view" : "views"); goto error_unbind; } return context; error_unbind: eglMakeCurrent(context->edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); error_egl_context: eglDestroyContext(context->edpy, context->egl_context); error_egl_surface: eglDestroySurface(context->edpy, context->egl_surface); error_gbm_surface: gbm_surface_destroy(context->gbm_surface); error_egl_display: eglTerminate(context->edpy); error_gbm_device: gbm_device_destroy(context->gbm); error: free(context); return NULL; }
/** * Try to create a GLX context of the given version with flags/options. * Note: A version number is required in order to get a core profile * (at least w/ NVIDIA). */ static GLXContext create_context_flags(Display *dpy, GLXFBConfig fbconfig, int major, int minor, int contextFlags, int profileMask, Bool direct) { #ifdef GLX_ARB_create_context static PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_func = 0; static Bool firstCall = True; int (*old_handler)(Display *, XErrorEvent *); GLXContext context; int attribs[20]; int n = 0; if (firstCall) { /* See if we have GLX_ARB_create_context_profile and get pointer to * glXCreateContextAttribsARB() function. */ const char *glxExt = glXQueryExtensionsString(dpy, 0); if (extension_supported("GLX_ARB_create_context_profile", glxExt)) { glXCreateContextAttribsARB_func = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB"); } firstCall = False; } if (!glXCreateContextAttribsARB_func) return 0; /* setup attribute array */ if (major) { attribs[n++] = GLX_CONTEXT_MAJOR_VERSION_ARB; attribs[n++] = major; attribs[n++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[n++] = minor; } if (contextFlags) { attribs[n++] = GLX_CONTEXT_FLAGS_ARB; attribs[n++] = contextFlags; } #ifdef GLX_ARB_create_context_profile if (profileMask) { attribs[n++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[n++] = profileMask; } #endif attribs[n++] = 0; /* install X error handler */ old_handler = XSetErrorHandler(create_context_error_handler); CreateContextErrorFlag = False; /* try creating context */ context = glXCreateContextAttribsARB_func(dpy, fbconfig, 0, /* share_context */ direct, attribs); /* restore error handler */ XSetErrorHandler(old_handler); if (CreateContextErrorFlag) context = 0; if (context && direct) { if (!glXIsDirect(dpy, context)) { glXDestroyContext(dpy, context); return 0; } } return context; #else return 0; #endif }