diff options
Diffstat (limited to 'src/mesa/drivers/dri/intel/intel_context.c')
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_context.c | 150 |
1 files changed, 89 insertions, 61 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 8ee9a292a1..05d4998654 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -177,6 +177,30 @@ intelGetString(GLcontext * ctx, GLenum name) } } +static void +intel_flush_front(GLcontext *ctx) +{ + struct intel_context *intel = intel_context(ctx); + __DRIcontext *driContext = intel->driContext; + __DRIscreen *const screen = intel->intelScreen->driScrnPriv; + + if ((ctx->DrawBuffer->Name == 0) && intel->front_buffer_dirty) { + if (screen->dri2.loader && + (screen->dri2.loader->base.version >= 2) + && (screen->dri2.loader->flushFrontBuffer != NULL) && + driContext->driDrawablePriv && + driContext->driDrawablePriv->loaderPrivate) { + (*screen->dri2.loader->flushFrontBuffer)(driContext->driDrawablePriv, + driContext->driDrawablePriv->loaderPrivate); + + /* We set the dirty bit in intel_prepare_render() if we're + * front buffer rendering once we get there. + */ + intel->front_buffer_dirty = GL_FALSE; + } + } +} + static unsigned intel_bits_per_pixel(const struct intel_renderbuffer *rb) { @@ -203,8 +227,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) * 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->is_front_buffer_rendering) { + intel_flush(&intel->ctx); + intel_flush_front(&intel->ctx); + } /* 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 @@ -362,7 +388,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) if (buffers[i].attachment == __DRI_BUFFER_DEPTH) depth_region = region; - intel_renderbuffer_set_region(rb, region); + intel_renderbuffer_set_region(intel, rb, region); intel_region_release(®ion); if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) { @@ -374,7 +400,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) continue; intel_region_reference(&stencil_region, region); - intel_renderbuffer_set_region(rb, stencil_region); + intel_renderbuffer_set_region(intel, rb, stencil_region); intel_region_release(&stencil_region); } } @@ -383,6 +409,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) driUpdateFramebufferSize(&intel->ctx, drawable); } +/** + * intel_prepare_render should be called anywhere that curent read/drawbuffer + * state is required. + */ void intel_prepare_render(struct intel_context *intel) { @@ -403,16 +433,47 @@ intel_prepare_render(struct intel_context *intel) intel_update_renderbuffers(driContext, drawable); 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 (intel->is_front_buffer_rendering) + intel->front_buffer_dirty = GL_TRUE; + + /* Wait for the swapbuffers before the one we just emitted, so we + * don't get too many swaps outstanding for apps that are GPU-heavy + * but not CPU-heavy. + * + * We're using intelDRI2Flush (called from the loader before + * swapbuffer) and glFlush (for front buffer rendering) as the + * indicator that a frame is done and then throttle when we get + * here as we prepare to render the next frame. At this point for + * round trips for swap/copy and getting new buffers are done and + * we'll spend less time waiting on the GPU. + * + * Unfortunately, we don't have a handle to the batch containing + * the swap, and getting our hands on that doesn't seem worth it, + * so we just us the first batch we emitted after the last swap. + */ + if (intel->need_throttle && intel->first_post_swapbuffers_batch) { + drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); + drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); + intel->first_post_swapbuffers_batch = NULL; + intel->need_throttle = GL_FALSE; + } } -void +static void intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) { struct intel_context *intel = intel_context(ctx); __DRIcontext *driContext = intel->driContext; - if (!intel->using_dri2_swapbuffers && - !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + if (intel->saved_viewport) + intel->saved_viewport(ctx, x, y, w, h); + + if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { dri2InvalidateDrawable(driContext->driDrawablePriv); dri2InvalidateDrawable(driContext->driReadablePriv); } @@ -431,12 +492,12 @@ static const struct dri_debug_control debug_control[] = { { "buf", DEBUG_BUFMGR}, { "reg", DEBUG_REGION}, { "fbo", DEBUG_FBO}, - { "lock", DEBUG_LOCK}, + { "gs", DEBUG_GS}, { "sync", DEBUG_SYNC}, { "prim", DEBUG_PRIMS }, { "vert", DEBUG_VERTS }, { "dri", DEBUG_DRI }, - { "dma", DEBUG_DMA }, + { "sf", DEBUG_SF }, { "san", DEBUG_SANITY }, { "sleep", DEBUG_SLEEP }, { "stats", DEBUG_STATS }, @@ -447,6 +508,7 @@ static const struct dri_debug_control debug_control[] = { { "glsl_force", DEBUG_GLSL_FORCE }, { "urb", DEBUG_URB }, { "vs", DEBUG_VS }, + { "clip", DEBUG_CLIP }, { NULL, 0 } }; @@ -469,10 +531,9 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state) } void -intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) +intel_flush(GLcontext *ctx) { struct intel_context *intel = intel_context(ctx); - __DRIcontext *driContext = intel->driContext; if (intel->Fallback) _swrast_flush(ctx); @@ -482,35 +543,6 @@ intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) if (intel->batch->map != intel->batch->ptr) intel_batchbuffer_flush(intel->batch); - - if ((ctx->DrawBuffer->Name == 0) && intel->front_buffer_dirty) { - __DRIscreen *const screen = intel->intelScreen->driScrnPriv; - - if (screen->dri2.loader && - (screen->dri2.loader->base.version >= 2) - && (screen->dri2.loader->flushFrontBuffer != NULL) && - driContext->driDrawablePriv && - driContext->driDrawablePriv->loaderPrivate) { - (*screen->dri2.loader->flushFrontBuffer)(driContext->driDrawablePriv, - driContext->driDrawablePriv->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. - */ - if (!intel->is_front_buffer_rendering) { - intel->front_buffer_dirty = GL_FALSE; - } - } - } -} - -void -intelFlush(GLcontext * ctx) -{ - intel_flush(ctx, GL_FALSE); } static void @@ -518,26 +550,9 @@ intel_glFlush(GLcontext *ctx) { struct intel_context *intel = intel_context(ctx); - intel_flush(ctx, GL_TRUE); - - /* We're using glFlush as an indicator that a frame is done, which is - * what DRI2 does before calling SwapBuffers (and means we should catch - * people doing front-buffer rendering, as well).. - * - * Wait for the swapbuffers before the one we just emitted, so we don't - * get too many swaps outstanding for apps that are GPU-heavy but not - * CPU-heavy. - * - * Unfortunately, we don't have a handle to the batch containing the swap, - * and getting our hands on that doesn't seem worth it, so we just us the - * first batch we emitted after the last swap. - */ - if (!intel->using_dri2_swapbuffers && - intel->first_post_swapbuffers_batch != NULL) { - drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); - drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); - intel->first_post_swapbuffers_batch = NULL; - } + intel_flush(ctx); + intel_flush_front(ctx); + intel->need_throttle = GL_TRUE; } void @@ -546,7 +561,8 @@ intelFinish(GLcontext * ctx) struct gl_framebuffer *fb = ctx->DrawBuffer; int i; - intelFlush(ctx); + intel_flush(ctx); + intel_flush_front(ctx); for (i = 0; i < fb->_NumColorDrawBuffers; i++) { struct intel_renderbuffer *irb; @@ -602,6 +618,12 @@ intelInitContext(struct intel_context *intel, if (intelScreen->bufmgr == NULL) return GL_FALSE; + /* Can't rely on invalidate events, fall back to glViewport hack */ + if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { + intel->saved_viewport = functions->Viewport; + functions->Viewport = intel_viewport; + } + if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx, functions, (void *) intel)) { printf("%s: failed to init mesa context\n", __FUNCTION__); @@ -886,6 +908,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv, driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; intel_prepare_render(intel); _mesa_make_current(&intel->ctx, fb, readFb); + + /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer + * is NULL at that point. We can't call _mesa_makecurrent() + * first, since we need the buffer size for the initial + * viewport. So just call intel_draw_buffer() again here. */ + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); } else { _mesa_make_current(NULL, NULL, NULL); |