From d449627829e1a4a3250a1a723af2f4e3cd5fd194 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 17 Feb 2010 21:17:55 -0500 Subject: [PATCH] intel: Implement the DRI2 invalidate function properly This uses a stamp mechanisms to mark the DRI drawable as invalid. Instead of immediately updating the buffers we just bump the drawable stamp and call out to DRI2GetBuffers "later". "Later" used to be at LOCK_HARDWARE time, and this patch brings back callouts at the points where we used to call LOCK_HARDWARE. A new function, intel_prepare_render(), is called where we used to call LOCK_HARDWARE, and if the buffers are invalid, we call out to DRI2GetBuffers there. This lets us invalidate buffers only when notified instead of on every glViewport() call. If the loader calls the DRI invalidate entrypoint, we disable viewport triggered buffer invalidation. Additionally, we can clean up the old viewport mechanism a bit, since we can just invalidate the buffers and not worry about reentrancy and whatnot. --- src/mesa/drivers/dri/common/dri_util.c | 2 + src/mesa/drivers/dri/common/dri_util.h | 5 ++ src/mesa/drivers/dri/i965/brw_draw.c | 2 + src/mesa/drivers/dri/intel/intel_blit.c | 4 ++ src/mesa/drivers/dri/intel/intel_buffers.c | 22 +++--- src/mesa/drivers/dri/intel/intel_context.c | 71 ++++++++++--------- src/mesa/drivers/dri/intel/intel_context.h | 1 + .../drivers/dri/intel/intel_pixel_bitmap.c | 2 + src/mesa/drivers/dri/intel/intel_pixel_copy.c | 2 + src/mesa/drivers/dri/intel/intel_pixel_read.c | 3 + src/mesa/drivers/dri/intel/intel_regions.c | 3 + src/mesa/drivers/dri/intel/intel_screen.c | 1 - src/mesa/drivers/dri/intel/intel_span.c | 1 + src/mesa/drivers/dri/intel/intel_tex_copy.c | 1 + src/mesa/drivers/dri/intel/intel_tex_image.c | 5 +- .../drivers/dri/intel/intel_tex_subimage.c | 2 + 16 files changed, 79 insertions(+), 48 deletions(-) diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index b891fca2b1c..58a94b58682 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -585,6 +585,8 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, pcp->driDrawablePriv = NULL; pcp->loaderPrivate = data; + pcp->dri2.draw_stamp = 0; + pcp->dri2.read_stamp = 0; /* When the first context is created for a screen, initialize a "dummy" * context. */ diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 8f0cd4cf9d8..2eadb9ac8c5 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -422,6 +422,11 @@ struct __DRIcontextRec { * The loaders's private context data. This structure is opaque. */ void *loaderPrivate; + + struct { + int draw_stamp; + int read_stamp; + } dri2; }; /** diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index d510d767f97..976249091e9 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -337,6 +337,8 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, * so can't access it earlier. */ + intel_prepare_render(intel); + for (i = 0; i < nr_prims; i++) { uint32_t hw_prim; diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 1fd07e8b82e..5a60a17500e 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -115,6 +115,8 @@ intelEmitCopyBlit(struct intel_context *intel, break; } while (pass < 2); + intel_prepare_render(intel); + if (pass >= 2) { dri_bo_map(dst_buffer, GL_TRUE); dri_bo_map(src_buffer, GL_FALSE); @@ -241,6 +243,8 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask) GLuint buf; all = (cw == fb->Width && ch == fb->Height); + intel_prepare_render(intel); + /* Loop over all renderbuffers */ for (buf = 0; buf < BUFFER_COUNT && mask; buf++) { const GLbitfield bufBit = 1 << buf; diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c index 2f03e450051..b10693050a9 100644 --- a/src/mesa/drivers/dri/intel/intel_buffers.c +++ b/src/mesa/drivers/dri/intel/intel_buffers.c @@ -271,13 +271,12 @@ intelDrawBuffer(GLcontext * ctx, GLenum mode) intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || (mode == GL_FRONT); - /* If we weren't front-buffer rendering before but we are now, make sure - * that the front-buffer has actually been allocated. + /* If we weren't front-buffer rendering before but we are now, + * invalidate our DRI drawable so we'll ask for new buffers + * (including the fake front) before we start rendering again. */ - if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) { - intel_update_renderbuffers(intel->driContext, - intel->driContext->driDrawablePriv); - } + if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) + dri2InvalidateDrawable(intel->driContext->driDrawablePriv); } intel_draw_buffer(ctx, ctx->DrawBuffer); @@ -295,13 +294,12 @@ intelReadBuffer(GLcontext * ctx, GLenum mode) intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT) || (mode == GL_FRONT); - /* If we weren't front-buffer reading before but we are now, make sure - * that the front-buffer has actually been allocated. + /* If we weren't front-buffer reading before but we are now, + * invalidate our DRI drawable so we'll ask for new buffers + * (including the fake front) before we start reading again. */ - if (!was_front_buffer_reading && intel->is_front_buffer_reading) { - intel_update_renderbuffers(intel->driContext, - intel->driContext->driDrawablePriv); - } + if (!was_front_buffer_reading && intel->is_front_buffer_reading) + dri2InvalidateDrawable(intel->driContext->driReadablePriv); } if (ctx->ReadBuffer == ctx->DrawBuffer) { diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 81d5a32476c..8f37fb82c1a 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -197,6 +197,15 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) unsigned int attachments[10]; const char *region_name; + /* If we're rendering to the fake front buffer, make sure all the + * pending drawing has landed on the real front buffer. Otherwise + * when we eventually get to DRI2GetBuffersWithFormat the stale + * real front buffer contents will get copied to the new fake front + * buffer. + */ + if (intel->is_front_buffer_rendering) + intel_flush(&intel->ctx, GL_FALSE); + if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); @@ -370,37 +379,41 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) drawable->lastStamp = drawable->dri2.stamp; } +void +intel_prepare_render(struct intel_context *intel) +{ + __DRIcontext *driContext = intel->driContext; + __DRIdrawable *drawable; + + drawable = intel->driDrawable; + if (drawable->dri2.stamp != driContext->dri2.draw_stamp) { + if (drawable->lastStamp != drawable->dri2.stamp) + intel_update_renderbuffers(driContext, drawable); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + driContext->dri2.draw_stamp = drawable->dri2.stamp; + } + + drawable = intel->driReadDrawable; + if (drawable->dri2.stamp != driContext->dri2.read_stamp) { + if (drawable->lastStamp != drawable->dri2.stamp) + intel_update_renderbuffers(driContext, drawable); + driContext->dri2.read_stamp = drawable->dri2.stamp; + } +} + void intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) { struct intel_context *intel = intel_context(ctx); __DRIcontext *driContext = intel->driContext; - void (*old_viewport)(GLcontext *ctx, GLint x, GLint y, - GLsizei w, GLsizei h); - - if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { - /* If we're rendering to the fake front buffer, make sure all the pending - * drawing has landed on the real front buffer. Otherwise when we - * eventually get to DRI2GetBuffersWithFormat the stale real front - * buffer contents will get copied to the new fake front buffer. - */ - if (intel->is_front_buffer_rendering) { - intel_flush(ctx, GL_FALSE); - } - intel_update_renderbuffers(driContext, driContext->driDrawablePriv); - if (driContext->driDrawablePriv != driContext->driReadablePriv) - intel_update_renderbuffers(driContext, driContext->driReadablePriv); + if (!intel->using_dri2_swapbuffers && + !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + dri2InvalidateDrawable(driContext->driDrawablePriv); + dri2InvalidateDrawable(driContext->driReadablePriv); } - - old_viewport = ctx->Driver.Viewport; - ctx->Driver.Viewport = NULL; - intel->driDrawable = driContext->driDrawablePriv; - intel_draw_buffer(ctx, intel->ctx.DrawBuffer); - ctx->Driver.Viewport = old_viewport; } - static const struct dri_debug_control debug_control[] = { { "tex", DEBUG_TEXTURE}, { "state", DEBUG_STATE}, @@ -860,22 +873,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv, if (driContextPriv) { struct gl_framebuffer *fb = driDrawPriv->driverPrivate; struct gl_framebuffer *readFb = driReadPriv->driverPrivate; - - intel_update_renderbuffers(driContextPriv, driDrawPriv); - if (driDrawPriv != driReadPriv) - intel_update_renderbuffers(driContextPriv, driReadPriv); - - /* set GLframebuffer size to match window, if needed */ - driUpdateFramebufferSize(&intel->ctx, driDrawPriv); - - if (driReadPriv != driDrawPriv) { - driUpdateFramebufferSize(&intel->ctx, driReadPriv); - } _mesa_make_current(&intel->ctx, fb, readFb); intel->driReadDrawable = driReadPriv; intel->driDrawable = driDrawPriv; - intel_draw_buffer(&intel->ctx, fb); + driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; + driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } else { _mesa_make_current(NULL, NULL, NULL); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index 0f0a194b3f5..da5d901abf9 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -454,6 +454,7 @@ void intel_viewport(GLcontext * ctx, GLint x, GLint y, void intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable); +void intel_prepare_render(struct intel_context *intel); void i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region, uint32_t buffer_id); diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c index 1e517650b7a..eabfbf4af94 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c @@ -234,6 +234,8 @@ do_blit_bitmap( GLcontext *ctx, if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return GL_FALSE; + intel_prepare_render(intel); + /* Clip to buffer bounds and scissor. */ if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index 87c293d8b07..f4f3fd6d889 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -138,6 +138,8 @@ do_blit_copypixels(GLcontext * ctx, intelFlush(&intel->ctx); + intel_prepare_render(intel); + /* XXX: We fail to handle different inversion between read and draw framebuffer. */ /* Clip to destination buffer. */ diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c index a98e8e16c24..514a17e2aa3 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_read.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c @@ -132,6 +132,8 @@ do_blit_readpixels(GLcontext * ctx, return GL_TRUE; } + intel_prepare_render(intel); + all = (width * height * src->cpp == dst->Base.Size && x == 0 && dst_offset == 0); @@ -172,6 +174,7 @@ intelReadPixels(GLcontext * ctx, fprintf(stderr, "%s\n", __FUNCTION__); intelFlush(ctx); + intel_prepare_render(intel_context(ctx)); if (do_blit_readpixels (ctx, x, y, width, height, format, type, pack, pixels)) diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index 881653ff01f..62b4ce61e44 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -378,6 +378,8 @@ intel_region_data(struct intel_context *intel, intel_region_cow(intel, dst); } + intel_prepare_render(intel); + _mesa_copy_rect(intel_region_map(intel, dst) + dst_offset, dst->cpp, dst->pitch, @@ -500,6 +502,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region) /* Now blit from the texture buffer to the new buffer: */ + intel_prepare_render(intel); ok = intelEmitCopyBlit(intel, region->cpp, region->pitch, pbo->buffer, 0, region->tiling, diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 8eed8ee7375..5e23aa8a1d6 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -129,7 +129,6 @@ intelDRI2Invalidate(__DRIdrawable *drawable) intel->using_dri2_swapbuffers = GL_TRUE; dri2InvalidateDrawable(drawable); - intel_update_renderbuffers(intel->driContext, drawable); } static const struct __DRI2flushExtensionRec intelFlushExtension = { diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index d925cb9997f..97bb97265fb 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -498,6 +498,7 @@ intelSpanRenderStart(GLcontext * ctx) GLuint i; intelFlush(&intel->ctx); + intel_prepare_render(intel); for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { if (ctx->Texture.Unit[i]._ReallyEnabled) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index d67451cf8ec..13b8bcfa86c 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -109,6 +109,7 @@ do_copy_texsubimage(struct intel_context *intel, } /* intelFlush(ctx); */ + intel_prepare_render(intel); { drm_intel_bo *dst_bo = intel_region_buffer(intel, intelImage->mt->region, diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index bc4e5c61367..aefd0b97d0c 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -240,6 +240,7 @@ try_pbo_upload(struct intel_context *intel, if (drm_intel_bo_references(intel->batch->buf, dst_buffer)) intelFlush(&intel->ctx); + intel_prepare_render(intel); { dri_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ); @@ -472,6 +473,8 @@ intelTexImage(GLcontext * ctx, pixels, unpack, "glTexImage"); } + intel_prepare_render(intel); + if (intelImage->mt) { if (pixels != NULL) { /* Flush any queued rendering with the texture before mapping. */ @@ -748,7 +751,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, if (!intelObj) return; - if (dPriv->lastStamp != *dPriv->pStamp) + if (dPriv->lastStamp != dPriv->dri2.stamp) intel_update_renderbuffers(pDRICtx, dPriv); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c index 7f1dc890220..c35d2e87573 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c +++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c @@ -72,6 +72,8 @@ intelTexSubimage(GLcontext * ctx, if (!pixels) return; + intel_prepare_render(intel); + /* Map buffer if necessary. Need to lock to prevent other contexts * from uploading the buffer under us. */ -- 2.30.2