glx: Implement GLX_ARB_context_flush_control

This extension allows clients to opt out of the implicit glFlush on
context release, which is quite nice for performance for clients using
multiple contexts.  The server doesn't really need to be aware of the
client's decision, at least for direct contexts, but it does need to not
reject the context attribute out of hand.

This patch won't do anything unless built against a Mesa that defines
the __DRI2_FLUSH_CONTROL extension (and a new enough glxext.h, but
that's been there since 10.3 at least).

Reviewed-by: James Jones <jajones@nvidia.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Adam Jackson 2015-05-19 11:31:25 -04:00
parent 2d7194334a
commit 995ff11422
7 changed files with 57 additions and 2 deletions

View File

@ -87,6 +87,9 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
int minor_version = 0;
uint32_t flags = 0;
uint32_t render_type = GLX_RGBA_TYPE;
#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
uint32_t flush = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
#endif
__GLXcontext *ctx = NULL;
__GLXcontext *shareCtx = NULL;
__GLXscreen *glxScreen;
@ -194,6 +197,15 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
break;
#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
flush = attribs[2 * i + 1];
if (flush != GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB
&& flush != GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB)
return BadValue;
break;
#endif
default:
return BadValue;
}
@ -333,6 +345,9 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
ctx->drawPriv = NULL;
ctx->readPriv = NULL;
ctx->resetNotificationStrategy = reset;
#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
ctx->releaseBehavior = flush;
#endif
/* Add the new context to the various global tables of GLX contexts.
*/

View File

@ -72,6 +72,7 @@ struct extension_info {
static const struct extension_info known_glx_extensions[] = {
/* GLX_ARB_get_proc_address is implemented on the client. */
/* *INDENT-OFF* */
{ GLX(ARB_context_flush_control), VER(0,0), N, },
{ GLX(ARB_create_context), VER(0,0), N, },
{ GLX(ARB_create_context_profile), VER(0,0), N, },
{ GLX(ARB_create_context_robustness), VER(0,0), N, },

View File

@ -36,7 +36,8 @@
enum {
/* GLX_ARB_get_proc_address is implemented on the client. */
ARB_create_context_bit = 0,
ARB_context_flush_control_bit = 0,
ARB_create_context_bit,
ARB_create_context_profile_bit,
ARB_create_context_robustness_bit,
ARB_fbconfig_float_bit,

View File

@ -334,6 +334,19 @@ DoCreateContext(__GLXclientState * cl, GLXContextID gcId,
*/
glxc->resetNotificationStrategy = GLX_NO_RESET_NOTIFICATION_ARB;
#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
/* The GLX_ARB_context_flush_control spec says:
*
* "The default value [for GLX_CONTEXT_RELEASE_BEHAVIOR] is
* CONTEXT_RELEASE_BEHAVIOR_FLUSH, and may in some cases be changed
* using platform-specific context creation extensions."
*
* Without using glXCreateContextAttribsARB, there is no way to specify a
* non-default release behavior.
*/
glxc->releaseBehavior = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
#endif
/* Add the new context to the various global tables of GLX contexts.
*/
if (!__glXAddContext(glxc)) {
@ -626,7 +639,12 @@ DoMakeCurrent(__GLXclientState * cl,
/*
** Flush the previous context if needed.
*/
if (prevglxc->hasUnflushedCommands) {
Bool need_flush = GL_TRUE;
#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
if (prevglxc->releaseBehavior == GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB)
need_flush = GL_FALSE;
#endif
if (prevglxc->hasUnflushedCommands && need_flush) {
if (__glXForceCurrent(cl, tag, (int *) &error)) {
glFlush();
prevglxc->hasUnflushedCommands = GL_FALSE;

View File

@ -108,6 +108,11 @@ struct __GLXcontext {
*/
GLenum resetNotificationStrategy;
/**
* Context release behavior
*/
GLenum releaseBehavior;
/*
** Buffers for feedback and selection.
*/

View File

@ -921,6 +921,13 @@ initializeExtensions(__GLXDRIscreen * screen)
"AIGLX: enabled GLX_ARB_create_context_robustness\n");
}
#ifdef __DRI2_FLUSH_CONTROL
if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) {
__glXEnableExtension(screen->glx_enable_bits,
"GLX_ARB_context_flush_control\n");
}
#endif
/* Ignore unknown extensions */
}
}

View File

@ -424,6 +424,14 @@ initializeExtensions(__GLXDRIscreen * screen)
screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
/* GLX_EXT_texture_from_pixmap is always enabled. */
}
#ifdef __DRI2_FLUSH_CONTROL
if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) {
__glXEnableExtension(screen->glx_enable_bits,
"GLX_ARB_context_flush_control\n");
}
#endif
}
}