summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2010-08-02 04:17:03 +0200
committerJerome Glisse <jglisse@redhat.com>2010-08-02 13:29:44 -0400
commit646d2e9fbc41bf49075013009e9583bec4a51168 (patch)
treee85b296ce4e1736cda0282d82f0297e9b06ab77e
parent3d39f56a8721ec6aa6d00965b7740fc8cb5edaae (diff)
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>
-rw-r--r--src/mesa/drivers/dri/r200/r200_swtcl.c2
-rw-r--r--src/mesa/drivers/dri/r200/r200_tcl.c2
-rw-r--r--src/mesa/drivers/dri/r300/r300_render.c2
-rw-r--r--src/mesa/drivers/dri/r600/r700_clear.c3
-rw-r--r--src/mesa/drivers/dri/r600/r700_render.c4
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common.c15
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.c49
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h1
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_pixel_read.c3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c17
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tcl.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex_copy.c6
13 files changed, 98 insertions, 10 deletions
diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c
index 262fe3cddee..dbf4ad477db 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.c
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.c
@@ -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) {
diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c
index d43e14581e9..4ae0f304918 100644
--- a/src/mesa/drivers/dri/r200/r200_tcl.c
+++ b/src/mesa/drivers/dri/r200/r200_tcl.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index bb8f91491f5..cf89ab7ec3d 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r600/r700_clear.c b/src/mesa/drivers/dri/r600/r700_clear.c
index 09c48565b68..d1008f28b9b 100644
--- a/src/mesa/drivers/dri/r600/r700_clear.c
+++ b/src/mesa/drivers/dri/r600/r700_clear.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c
index 1929b7cc129..316a0943f4e 100644
--- a/src/mesa/drivers/dri/r600/r700_render.c
+++ b/src/mesa/drivers/dri/r600/r700_render.c
@@ -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.
*/
diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c
index 13f1f0611b8..c1a660af3d0 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common.c
@@ -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);
}
}
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 5a7d52c4d2f..f76c49eada3 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -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)) {
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 5156c5d0d0a..ec773cfa522 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -614,5 +614,6 @@ GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv);
extern void radeonDestroyContext(__DRIcontext * driContextPriv);
+void radeon_prepare_render(radeonContextPtr radeon);
#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
index dadb8002c7d..fb741173ca8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
+++ b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
@@ -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;
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 82107cc6aeb..d3d7b216baa 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -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;
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
index f2fcb46688a..67be466c3f8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
@@ -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++)
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
index ea796e1a45f..5e1718f9dfc 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -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 );
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
index 29fd31ac23f..4cb0bb60c85 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
@@ -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)) {