intel: flush old context before binding new context
[mesa.git] / src / mesa / drivers / dri / intel / intel_context.c
index 4abb525f78e3755fbf63cc37c2b858225ddd33c8..ddb0550f77d217e4e23838753e2f4912357a989c 100644 (file)
@@ -38,6 +38,7 @@
 #include "swrast_setup/swrast_setup.h"
 #include "tnl/tnl.h"
 #include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
 
 #include "i830_dri.h"
 
@@ -161,6 +162,9 @@ intelGetString(GLcontext * ctx, GLenum name)
       case PCI_CHIP_G41_G:
          chipset = "Intel(R) G41";
          break;
+      case PCI_CHIP_B43_G:
+         chipset = "Intel(R) B43";
+         break;
       case PCI_CHIP_ILD_G:
          chipset = "Intel(R) IGDNG_D";
          break;
@@ -503,7 +507,8 @@ intel_flush(GLcontext *ctx, GLboolean needs_mi_flush)
 
       if (screen->dri2.loader &&
           (screen->dri2.loader->base.version >= 2)
-         && (screen->dri2.loader->flushFrontBuffer != NULL)) {
+         && (screen->dri2.loader->flushFrontBuffer != NULL) &&
+          intel->driDrawable && intel->driDrawable->loaderPrivate) {
         (*screen->dri2.loader->flushFrontBuffer)(intel->driDrawable,
                                                  intel->driDrawable->loaderPrivate);
 
@@ -513,7 +518,7 @@ intel_flush(GLcontext *ctx, GLboolean needs_mi_flush)
          * 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) {
+        if (!intel->is_front_buffer_rendering) {
            intel->front_buffer_dirty = GL_FALSE;
         }
       }
@@ -529,7 +534,27 @@ intelFlush(GLcontext * ctx)
 static void
 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->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;
+   }
 }
 
 void
@@ -577,6 +602,7 @@ intelInitDriverFunctions(struct dd_function_table *functions)
    intelInitBufferFuncs(functions);
    intelInitPixelFuncs(functions);
    intelInitBufferObjectFuncs(functions);
+   intel_init_syncobj_functions(functions);
 }
 
 
@@ -619,6 +645,10 @@ intelInitContext(struct intel_context *intel,
       intel->maxBatchSize = BATCH_SZ;
 
    intel->bufmgr = intelScreen->bufmgr;
+
+   if (0) /* for debug */
+      drm_intel_bufmgr_set_debug(intel->bufmgr, 1);
+
    intel->ttm = intelScreen->ttm;
    if (intel->ttm) {
       int bo_reuse_mode;
@@ -692,6 +722,8 @@ intelInitContext(struct intel_context *intel,
    _swrast_allow_pixel_fog(ctx, GL_FALSE);
    _swrast_allow_vertex_fog(ctx, GL_TRUE);
 
+   _mesa_meta_init(ctx);
+
    intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
    intel->hw_stipple = 1;
 
@@ -752,7 +784,7 @@ intelInitContext(struct intel_context *intel,
    if (intel->use_texture_tiling &&
        !intel->intelScreen->kernel_exec_fencing) {
       fprintf(stderr, "No kernel support for execution fencing, "
-             "disabling texture tiling");
+             "disabling texture tiling\n");
       intel->use_texture_tiling = GL_FALSE;
    }
    intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z");
@@ -795,6 +827,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
 
       INTEL_FIREVERTICES(intel);
 
+      _mesa_meta_free(&intel->ctx);
+
       meta_destroy_metaops(&intel->meta);
 
       intel->vtbl.destroy(intel);
@@ -805,7 +839,7 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
       _vbo_DestroyContext(&intel->ctx);
 
       _swrast_DestroyContext(&intel->ctx);
-      intel->Fallback = 0;      /* don't call _swrast_Flush later */
+      intel->Fallback = 0x0;      /* don't call _swrast_Flush later */
 
       intel_batchbuffer_free(intel->batch);
       intel->batch = NULL;
@@ -814,6 +848,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
       intel->prim.vb = NULL;
       dri_bo_unreference(intel->prim.vb_bo);
       intel->prim.vb_bo = NULL;
+      dri_bo_unreference(intel->first_post_swapbuffers_batch);
+      intel->first_post_swapbuffers_batch = NULL;
 
       if (release_texture_heaps) {
          /* Nothing is currently done here to free texture heaps;
@@ -891,6 +927,14 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
 GLboolean
 intelUnbindContext(__DRIcontextPrivate * driContextPriv)
 {
+   struct intel_context *intel =
+      (struct intel_context *) driContextPriv->driverPrivate;
+
+   /* Deassociate the context with the drawables.
+    */
+   intel->driDrawable = NULL;
+   intel->driReadDrawable = NULL;
+
    return GL_TRUE;
 }
 
@@ -900,10 +944,23 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
                  __DRIdrawablePrivate * driReadPriv)
 {
    __DRIscreenPrivate *psp = driDrawPriv->driScreenPriv;
+   struct intel_context *intel;
+   GET_CURRENT_CONTEXT(curCtx);
+
+   if (driContextPriv)
+      intel = (struct intel_context *) driContextPriv->driverPrivate;
+   else
+      intel = NULL;
+
+   /* According to the glXMakeCurrent() man page: "Pending commands to
+    * the previous context, if any, are flushed before it is released."
+    * But only flush if we're actually changing contexts.
+    */
+   if (intel_context(curCtx) && intel_context(curCtx) != intel) {
+      _mesa_flush(curCtx);
+   }
 
    if (driContextPriv) {
-      struct intel_context *intel =
-         (struct intel_context *) driContextPriv->driverPrivate;
       struct intel_framebuffer *intel_fb =
         (struct intel_framebuffer *) driDrawPriv->driverPrivate;
       GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;
@@ -949,41 +1006,35 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
 
       _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb);
 
-      /* The drawbuffer won't always be updated by _mesa_make_current: 
-       */
-      if (intel->ctx.DrawBuffer == &intel_fb->Base) {
-
-        if (intel->driReadDrawable != driReadPriv)
-           intel->driReadDrawable = driReadPriv;
-
-        if (intel->driDrawable != driDrawPriv) {
-           if (driDrawPriv->swap_interval == (unsigned)-1) {
-              int i;
-
-              driDrawPriv->vblFlags = (intel->intelScreen->irq_active != 0)
-                 ? driGetDefaultVBlankFlags(&intel->optionCache)
-                : VBLANK_FLAG_NO_IRQ;
-
-              /* Prevent error printf if one crtc is disabled, this will
-               * be properly calculated in intelWindowMoved() next.
-               */
-               driDrawPriv->vblFlags = intelFixupVblank(intel, driDrawPriv);
-
-              (*psp->systemTime->getUST) (&intel_fb->swap_ust);
-              driDrawableInitVBlank(driDrawPriv);
-              intel_fb->vbl_waited = driDrawPriv->vblSeq;
-
-              for (i = 0; i < 2; i++) {
-                 if (intel_fb->color_rb[i])
-                    intel_fb->color_rb[i]->vbl_pending = driDrawPriv->vblSeq;
-              }
-           }
-           intel->driDrawable = driDrawPriv;
-           intelWindowMoved(intel);
-        }
+      intel->driReadDrawable = driReadPriv;
+
+      if (intel->driDrawable != driDrawPriv) {
+         if (driDrawPriv->swap_interval == (unsigned)-1) {
+            int i;
+
+            driDrawPriv->vblFlags = (intel->intelScreen->irq_active != 0)
+               ? driGetDefaultVBlankFlags(&intel->optionCache)
+               : VBLANK_FLAG_NO_IRQ;
+
+            /* Prevent error printf if one crtc is disabled, this will
+             * be properly calculated in intelWindowMoved() next.
+             */
+            driDrawPriv->vblFlags = intelFixupVblank(intel, driDrawPriv);
 
-        intel_draw_buffer(&intel->ctx, &intel_fb->Base);
+            (*psp->systemTime->getUST) (&intel_fb->swap_ust);
+            driDrawableInitVBlank(driDrawPriv);
+            intel_fb->vbl_waited = driDrawPriv->vblSeq;
+
+            for (i = 0; i < 2; i++) {
+               if (intel_fb->color_rb[i])
+                  intel_fb->color_rb[i]->vbl_pending = driDrawPriv->vblSeq;
+            }
+         }
+         intel->driDrawable = driDrawPriv;
+         intelWindowMoved(intel);
       }
+
+      intel_draw_buffer(&intel->ctx, &intel_fb->Base);
    }
    else {
       _mesa_make_current(NULL, NULL, NULL);