radeon: Add DRI2 flush extension support, so we synchronize properly.

When a DRI2 swap buffer is pending we need to make sure we
have the flush extension so radeon doesn't resume rendering to
or reading from the not yet blitted front buffer.

This fixes:

https://bugs.freedesktop.org/show_bug.cgi?id=28341
https://bugs.freedesktop.org/show_bug.cgi?id=28410

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
This commit is contained in:
Mario Kleiner 2010-08-02 04:17:03 +02:00 committed by Jerome Glisse
parent 3d39f56a87
commit 646d2e9fbc
13 changed files with 98 additions and 10 deletions

View file

@ -612,6 +612,8 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
radeon_prepare_render(&rmesa->radeon);
if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
/* need to disable perspective-correct texturing for point sprites */
if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {

View file

@ -264,6 +264,8 @@ void r200TclPrimitive( GLcontext *ctx,
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE;
radeon_prepare_render(&rmesa->radeon);
if (newprim != rmesa->tcl.hw_primitive ||
!discrete_prim[hw_prim&0xf]) {
/* need to disable perspective-correct texturing for point sprites */

View file

@ -327,6 +327,8 @@ void r300RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim)
BATCH_LOCALS(&rmesa->radeon);
int type, num_verts;
radeon_prepare_render(&rmesa->radeon);
type = r300PrimitiveType(rmesa, prim);
num_verts = r300NumVerts(rmesa, end - start, prim);

View file

@ -48,6 +48,7 @@ static GLboolean r700ClearFast(context_t *context, GLbitfield mask)
void r700Clear(GLcontext * ctx, GLbitfield mask)
{
context_t *context = R700_CONTEXT(ctx);
radeonContextPtr radeon = &context->radeon;
__DRIdrawable *dPriv = radeon_get_drawable(&context->radeon);
const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask[0]);
GLbitfield swrast_mask = 0, tri_mask = 0;
@ -60,6 +61,8 @@ void r700Clear(GLcontext * ctx, GLbitfield mask)
context->radeon.front_buffer_dirty = GL_TRUE;
}
radeon_prepare_render(radeon);
if( GL_TRUE == r700ClearFast(context, mask) )
{
return;

View file

@ -977,6 +977,10 @@ static void r700DrawPrims(GLcontext *ctx,
{
GLboolean retval = GL_FALSE;
context_t *context = R700_CONTEXT(ctx);
radeonContextPtr radeon = &context->radeon;
radeon_prepare_render(radeon);
/* This check should get folded into just the places that
* min/max index are really needed.
*/

View file

@ -708,7 +708,6 @@ void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
radeon->front_cliprects = GL_TRUE;
radeon->front_buffer_dirty = GL_TRUE;
} else {
rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
radeon->front_cliprects = GL_FALSE;
@ -1132,17 +1131,13 @@ flush_front:
if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
&& (screen->dri2.loader->flushFrontBuffer != NULL)) {
__DRIdrawable * drawable = radeon_get_drawable(radeon);
(*screen->dri2.loader->flushFrontBuffer)(drawable, drawable->loaderPrivate);
/* Only clear the dirty bit if front-buffer rendering is no longer
* enabled. This is done so that the dirty bit can only be set in
* glDrawBuffer. Otherwise the dirty bit would have to be set at
* each of N places that do rendering. This has worse performances,
* but it is much easier to get correct.
/* We set the dirty bit in radeon_prepare_render() if we're
* front buffer rendering once we get there.
*/
if (!radeon->is_front_buffer_rendering) {
radeon->front_buffer_dirty = GL_FALSE;
}
radeon->front_buffer_dirty = GL_FALSE;
(*screen->dri2.loader->flushFrontBuffer)(drawable, drawable->loaderPrivate);
}
}
}

View file

@ -493,6 +493,50 @@ radeon_bits_per_pixel(const struct radeon_renderbuffer *rb)
return _mesa_get_format_bytes(rb->base.Format) * 8;
}
/*
* Check if drawable has been invalidated by dri2InvalidateDrawable().
* Update renderbuffers if so. This prevents a client from accessing
* a backbuffer that has a swap pending but not yet completed.
*
* See intel_prepare_render for equivalent code in intel driver.
*
*/
void radeon_prepare_render(radeonContextPtr radeon)
{
__DRIcontext *driContext = radeon->dri.context;
__DRIdrawable *drawable;
__DRIscreen *screen;
screen = driContext->driScreenPriv;
if (!screen->dri2.loader)
return;
drawable = driContext->driDrawablePriv;
if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
if (drawable->lastStamp != drawable->dri2.stamp)
radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
/* Intel driver does the equivalent of this, no clue if it is needed:
* radeon_draw_buffer(radeon->glCtx, &(drawable->driverPrivate)->base);
*/
driContext->dri2.draw_stamp = drawable->dri2.stamp;
}
drawable = driContext->driReadablePriv;
if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
if (drawable->lastStamp != drawable->dri2.stamp)
radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
driContext->dri2.read_stamp = drawable->dri2.stamp;
}
/* If we're currently rendering to the front buffer, the rendering
* that will happen next will probably dirty the front buffer. So
* mark it as dirty here.
*/
if (radeon->is_front_buffer_rendering)
radeon->front_buffer_dirty = GL_TRUE;
}
void
radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
GLboolean front_only)
@ -514,6 +558,11 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
screen = context->driScreenPriv;
radeon = (radeonContextPtr) context->driverPrivate;
/* Set this up front, so that in case our buffers get invalidated
* while we're getting new buffers, we don't clobber the stamp and
* thus ignore the invalidate. */
drawable->lastStamp = drawable->dri2.stamp;
if (screen->dri2.loader
&& (screen->dri2.loader->base.version > 2)
&& (screen->dri2.loader->getBuffersWithFormat != NULL)) {

View file

@ -614,5 +614,6 @@ GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv);
extern void radeonDestroyContext(__DRIcontext * driContextPriv);
void radeon_prepare_render(radeonContextPtr radeon);
#endif

View file

@ -179,6 +179,9 @@ radeonReadPixels(GLcontext * ctx,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
radeon_prepare_render(radeon);
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;

View file

@ -376,6 +376,21 @@ static const __DRItexBufferExtension r600TexBufferExtension = {
};
#endif
static void
radeonDRI2Flush(__DRIdrawable *drawable)
{
radeonContextPtr rmesa;
rmesa = (radeonContextPtr) drawable->driContextPriv->driverPrivate;
radeonFlush(rmesa->glCtx);
}
static const struct __DRI2flushExtensionRec radeonFlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
radeonDRI2Flush,
dri2InvalidateDrawable,
};
static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
{
screen->device_id = device_id;
@ -1379,6 +1394,8 @@ radeonCreateScreen2(__DRIscreen *sPriv)
screen->extensions[i++] = &r600TexBufferExtension.base;
#endif
screen->extensions[i++] = &radeonFlushExtension.base;
screen->extensions[i++] = NULL;
sPriv->extensions = screen->extensions;

View file

@ -408,6 +408,8 @@ static GLboolean radeon_run_render( GLcontext *ctx,
!radeon_dma_validate_render( ctx, VB ))
return GL_TRUE;
radeon_prepare_render(&rmesa->radeon);
tnl->Driver.Render.Start( ctx );
for (i = 0 ; i < VB->PrimitiveCount ; i++)

View file

@ -252,6 +252,8 @@ void radeonTclPrimitive( GLcontext *ctx,
GLuint se_cntl;
GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
radeon_prepare_render(&rmesa->radeon);
if (newprim != rmesa->tcl.hw_primitive ||
!discrete_prim[hw_prim&0xf]) {
RADEON_NEWPRIM( rmesa );

View file

@ -153,6 +153,9 @@ radeonCopyTexImage2D(GLcontext *ctx, GLenum target, GLint level,
_mesa_select_tex_image(ctx, texObj, target, level);
int srcx, srcy, dstx, dsty;
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
radeon_prepare_render(radeon);
if (border)
goto fail;
@ -202,6 +205,9 @@ radeonCopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level);
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
radeon_prepare_render(radeon);
if (!do_copy_texsubimage(ctx, target, level,
radeon_tex_obj(texObj), (radeon_texture_image *)texImage,
xoffset, yoffset, x, y, width, height)) {