2 * (C) Copyright IBM Corporation 2002, 2004
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * DRI utility functions.
29 * This module acts as glue between GLX and the actual hardware driver. A DRI
30 * driver doesn't really \e have to use any of this - it's optional. But, some
31 * useful stuff is done here that otherwise would have to be duplicated in most
34 * Basically, these utility functions take care of some of the dirty details of
35 * screen initialization, context creation, context binding, DRM setup, etc.
37 * These functions are compiled into each DRI driver so libGL.so knows nothing
46 #include "../glsl/glsl_parser_extras.h"
48 PUBLIC
const char __dri2ConfigOptions
[] =
50 DRI_CONF_SECTION_PERFORMANCE
51 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
55 static const uint __dri2NConfigOptions
= 1;
57 /*****************************************************************/
58 /** \name Screen handling functions */
59 /*****************************************************************/
63 setupLoaderExtensions(__DRIscreen
*psp
,
64 const __DRIextension
**extensions
)
68 for (i
= 0; extensions
[i
]; i
++) {
69 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
70 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
71 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
72 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
73 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
74 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
79 dri2CreateNewScreen(int scrn
, int fd
,
80 const __DRIextension
**extensions
,
81 const __DRIconfig
***driver_configs
, void *data
)
83 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
85 drmVersionPtr version
;
87 psp
= calloc(1, sizeof(*psp
));
91 setupLoaderExtensions(psp
, extensions
);
93 version
= drmGetVersion(fd
);
95 psp
->drm_version
.major
= version
->version_major
;
96 psp
->drm_version
.minor
= version
->version_minor
;
97 psp
->drm_version
.patch
= version
->version_patchlevel
;
98 drmFreeVersion(version
);
101 psp
->loaderPrivate
= data
;
103 psp
->extensions
= emptyExtensionList
;
107 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
109 *driver_configs
= driDriverAPI
.InitScreen(psp
);
110 if (*driver_configs
== NULL
) {
115 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
, __dri2NConfigOptions
);
116 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
, "dri2");
122 * Destroy the per-screen private information.
125 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
126 * drmClose(), and finally frees \p screenPrivate.
128 static void driDestroyScreen(__DRIscreen
*psp
)
131 /* No interaction with the X-server is possible at this point. This
132 * routine is called after XCloseDisplay, so there is no protocol
133 * stream open to the X-server anymore.
136 _mesa_destroy_shader_compiler();
138 driDriverAPI
.DestroyScreen(psp
);
140 driDestroyOptionCache(&psp
->optionCache
);
141 driDestroyOptionInfo(&psp
->optionInfo
);
147 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
149 return psp
->extensions
;
155 /*****************************************************************/
156 /** \name Context handling functions */
157 /*****************************************************************/
160 static __DRIcontext
*
161 dri2CreateContextAttribs(__DRIscreen
*screen
, int api
,
162 const __DRIconfig
*config
,
163 __DRIcontext
*shared
,
164 unsigned num_attribs
,
165 const uint32_t *attribs
,
169 __DRIcontext
*context
;
170 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
171 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
173 unsigned major_version
= 1;
174 unsigned minor_version
= 0;
177 assert((num_attribs
== 0) || (attribs
!= NULL
));
179 if (!(screen
->api_mask
& (1 << api
))) {
180 *error
= __DRI_CTX_ERROR_BAD_API
;
185 case __DRI_API_OPENGL
:
186 mesa_api
= API_OPENGL
;
189 mesa_api
= API_OPENGLES
;
191 case __DRI_API_GLES2
:
192 mesa_api
= API_OPENGLES2
;
194 case __DRI_API_OPENGL_CORE
:
196 *error
= __DRI_CTX_ERROR_BAD_API
;
200 for (unsigned i
= 0; i
< num_attribs
; i
++) {
201 switch (attribs
[i
* 2]) {
202 case __DRI_CTX_ATTRIB_MAJOR_VERSION
:
203 major_version
= attribs
[i
* 2 + 1];
205 case __DRI_CTX_ATTRIB_MINOR_VERSION
:
206 minor_version
= attribs
[i
* 2 + 1];
208 case __DRI_CTX_ATTRIB_FLAGS
:
209 flags
= attribs
[i
* 2 + 1];
212 /* We can't create a context that satisfies the requirements of an
213 * attribute that we don't understand. Return failure.
215 assert(!"Should not get here.");
216 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
221 /* The EGL_KHR_create_context spec says:
223 * "Flags are only defined for OpenGL context creation, and specifying
224 * a flags value other than zero for other types of contexts,
225 * including OpenGL ES contexts, will generate an error."
227 * The GLX_EXT_create_context_es2_profile specification doesn't say
228 * anything specific about this case. However, none of the known flags
229 * have any meaning in an ES context, so this seems safe.
231 if (mesa_api
!= __DRI_API_OPENGL
232 && mesa_api
!= __DRI_API_OPENGL_CORE
234 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
238 /* There are no forward-compatible contexts before OpenGL 3.0. The
239 * GLX_ARB_create_context spec says:
241 * "Forward-compatible contexts are defined only for OpenGL versions
244 * Moreover, Mesa can't fulfill the requirements of a forward-looking
245 * context. Return failure if a forward-looking context is requested.
247 * In Mesa, a debug context is the same as a regular context.
249 if ((flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0) {
250 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
254 if ((flags
& ~__DRI_CTX_FLAG_DEBUG
) != 0) {
255 *error
= __DRI_CTX_ERROR_UNKNOWN_FLAG
;
259 context
= malloc(sizeof *context
);
261 *error
= __DRI_CTX_ERROR_NO_MEMORY
;
265 context
->loaderPrivate
= data
;
267 context
->driScreenPriv
= screen
;
268 context
->driDrawablePriv
= NULL
;
269 context
->driReadablePriv
= NULL
;
271 if (!driDriverAPI
.CreateContext(mesa_api
, modes
, context
,
272 major_version
, minor_version
,
273 flags
, error
, shareCtx
) ) {
278 *error
= __DRI_CTX_ERROR_SUCCESS
;
282 static __DRIcontext
*
283 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
284 const __DRIconfig
*config
,
285 __DRIcontext
*shared
, void *data
)
289 return dri2CreateContextAttribs(screen
, api
, config
, shared
, 0, NULL
,
293 static __DRIcontext
*
294 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
295 __DRIcontext
*shared
, void *data
)
297 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
298 config
, shared
, data
);
302 * Destroy the per-context private information.
305 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
306 * drmDestroyContext(), and finally frees \p contextPrivate.
309 driDestroyContext(__DRIcontext
*pcp
)
312 driDriverAPI
.DestroyContext(pcp
);
318 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
329 /*****************************************************************/
330 /** \name Context (un)binding functions */
331 /*****************************************************************/
334 static void dri_get_drawable(__DRIdrawable
*pdp
);
335 static void dri_put_drawable(__DRIdrawable
*pdp
);
338 * This function takes both a read buffer and a draw buffer. This is needed
339 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
342 static int driBindContext(__DRIcontext
*pcp
,
347 ** Assume error checking is done properly in glXMakeCurrent before
348 ** calling driUnbindContext.
354 /* Bind the drawable to the context */
355 pcp
->driDrawablePriv
= pdp
;
356 pcp
->driReadablePriv
= prp
;
358 pdp
->driContextPriv
= pcp
;
359 dri_get_drawable(pdp
);
361 if (prp
&& pdp
!= prp
) {
362 dri_get_drawable(prp
);
365 return driDriverAPI
.MakeCurrent(pcp
, pdp
, prp
);
371 * \param scrn the screen.
374 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
377 * This function calls __DriverAPIRec::UnbindContext, and then decrements
378 * __DRIdrawableRec::refcount which must be non-zero for a successful
381 * While casting the opaque private pointers associated with the parameters
382 * into their respective real types it also assures they are not \c NULL.
384 static int driUnbindContext(__DRIcontext
*pcp
)
390 ** Assume error checking is done properly in glXMakeCurrent before
391 ** calling driUnbindContext.
397 pdp
= pcp
->driDrawablePriv
;
398 prp
= pcp
->driReadablePriv
;
400 /* already unbound */
404 driDriverAPI
.UnbindContext(pcp
);
407 if (pdp
->refcount
== 0) {
412 dri_put_drawable(pdp
);
415 if (prp
->refcount
== 0) {
420 dri_put_drawable(prp
);
423 /* XXX this is disabled so that if we call SwapBuffers on an unbound
424 * window we can determine the last context bound to the window and
425 * use that context's lock. (BrianP, 2-Dec-2000)
427 pcp
->driDrawablePriv
= NULL
;
428 pcp
->driReadablePriv
= NULL
;
436 static void dri_get_drawable(__DRIdrawable
*pdp
)
441 static void dri_put_drawable(__DRIdrawable
*pdp
)
448 driDriverAPI
.DestroyBuffer(pdp
);
453 static __DRIdrawable
*
454 dri2CreateNewDrawable(__DRIscreen
*screen
,
455 const __DRIconfig
*config
,
458 __DRIdrawable
*pdraw
;
460 pdraw
= malloc(sizeof *pdraw
);
464 pdraw
->loaderPrivate
= data
;
466 pdraw
->driScreenPriv
= screen
;
467 pdraw
->driContextPriv
= NULL
;
469 pdraw
->lastStamp
= 0;
473 dri_get_drawable(pdraw
);
475 if (!driDriverAPI
.CreateBuffer(screen
, pdraw
, &config
->modes
, GL_FALSE
)) {
480 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
486 driDestroyDrawable(__DRIdrawable
*pdp
)
488 dri_put_drawable(pdp
);
492 dri2AllocateBuffer(__DRIscreen
*screen
,
493 unsigned int attachment
, unsigned int format
,
494 int width
, int height
)
496 return driDriverAPI
.AllocateBuffer(screen
, attachment
, format
,
501 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
503 driDriverAPI
.ReleaseBuffer(screen
, buffer
);
508 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
510 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
513 *val
= driQueryOptionb(&screen
->optionCache
, var
);
519 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
521 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
522 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
525 *val
= driQueryOptioni(&screen
->optionCache
, var
);
531 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
533 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
536 *val
= driQueryOptionf(&screen
->optionCache
, var
);
542 dri2GetAPIMask(__DRIscreen
*screen
)
544 return screen
->api_mask
;
548 /** Core interface */
549 const __DRIcoreExtension driCoreExtension
= {
550 { __DRI_CORE
, __DRI_CORE_VERSION
},
555 driIndexConfigAttrib
,
566 /** DRI2 interface */
567 const __DRIdri2Extension driDRI2Extension
= {
570 dri2CreateNewDrawable
,
571 dri2CreateNewContext
,
573 dri2CreateNewContextForAPI
,
576 dri2CreateContextAttribs
579 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
580 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
587 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
589 drawable
->dri2
.stamp
++;
593 * Check that the gl_framebuffer associated with dPriv is the right size.
594 * Resize the gl_framebuffer if needed.
595 * It's expected that the dPriv->driverPrivate member points to a
596 * gl_framebuffer object.
599 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
601 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
602 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
603 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
604 /* if the driver needs the hw lock for ResizeBuffers, the drawable
605 might have changed again by now */
606 assert(fb
->Width
== dPriv
->w
);
607 assert(fb
->Height
== dPriv
->h
);