summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/intel/intel_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/intel/intel_context.c')
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c150
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(&region);
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);