Example #1
0
/**
 * 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;
}
Example #2
0
File: ocl.c Project: nasa/QuIP
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);
   }
}
Example #4
0
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;
}
Example #5
0
/**
 * 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
}