i965: Drop intel_context.c's texture format set up for this driver.
[mesa.git] / src / mesa / drivers / dri / intel / intel_context.c
index 4516db20ffcc595e9f7d1746f583bc57e150b8c0..4973b247c88ea7c0a443c83ec25132b1dd6652de 100644 (file)
@@ -33,6 +33,7 @@
 #include "main/framebuffer.h"
 #include "main/imports.h"
 #include "main/points.h"
+#include "main/renderbuffer.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "intel_fbo.h"
 #include "intel_bufmgr.h"
 #include "intel_screen.h"
+#include "intel_mipmap_tree.h"
 
-#include "drirenderbuffer.h"
 #include "utils.h"
-
+#include "../glsl/ralloc.h"
 
 #ifndef INTEL_DEBUG
 int INTEL_DEBUG = (0);
@@ -216,7 +217,7 @@ intel_flush_front(struct gl_context *ctx)
         /* 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;
+        intel->front_buffer_dirty = false;
       }
    }
 }
@@ -227,20 +228,59 @@ intel_bits_per_pixel(const struct intel_renderbuffer *rb)
    return _mesa_get_format_bytes(rb->Base.Format) * 8;
 }
 
+static void
+intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
+                                            __DRIdrawable *drawable,
+                                            __DRIbuffer **buffers,
+                                            int *count);
+
+static void
+intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
+                                             __DRIdrawable *drawable,
+                                             __DRIbuffer *buffer,
+                                             struct intel_renderbuffer *rb,
+                                             const char *buffer_name);
+
+static void
+intel_query_dri2_buffers_with_separate_stencil(struct intel_context *intel,
+                                              __DRIdrawable *drawable,
+                                              __DRIbuffer **buffers,
+                                              unsigned **attachments,
+                                              int *count);
+
+static void
+intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
+                                               __DRIdrawable *drawable,
+                                               __DRIbuffer *buffer,
+                                               struct intel_renderbuffer *rb,
+                                               const char *buffer_name);
+static void
+intel_verify_dri2_has_hiz(struct intel_context *intel,
+                         __DRIdrawable *drawable,
+                         __DRIbuffer **buffers,
+                         unsigned **attachments,
+                         int *count);
+
 void
 intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 {
    struct gl_framebuffer *fb = drawable->driverPrivate;
    struct intel_renderbuffer *rb;
-   struct intel_region *region, *depth_region;
    struct intel_context *intel = context->driverPrivate;
-   struct intel_renderbuffer *front_rb, *back_rb, *depth_rb, *stencil_rb;
    __DRIbuffer *buffers = NULL;
-   __DRIscreen *screen;
+   unsigned *attachments = NULL;
    int i, count;
-   unsigned int attachments[10];
    const char *region_name;
 
+   bool try_separate_stencil =
+      intel->has_separate_stencil &&
+      intel->intelScreen->dri2_has_hiz != INTEL_DRI2_HAS_HIZ_FALSE &&
+      intel->intelScreen->driScrnPriv->dri2.loader != NULL &&
+      intel->intelScreen->driScrnPriv->dri2.loader->base.version > 2 &&
+      intel->intelScreen->driScrnPriv->dri2.loader->getBuffersWithFormat != NULL;
+
+   assert(!intel->must_use_separate_stencil || try_separate_stencil);
+
    /* 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
@@ -260,86 +300,17 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
-   screen = intel->intelScreen->driScrnPriv;
-
-   if (screen->dri2.loader
-       && (screen->dri2.loader->base.version > 2)
-       && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
-
-      front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
-      back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
-      depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
-      stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
-
-      i = 0;
-      if ((intel->is_front_buffer_rendering ||
-          intel->is_front_buffer_reading ||
-          !back_rb) && front_rb) {
-        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
-        attachments[i++] = intel_bits_per_pixel(front_rb);
-      }
-
-      if (back_rb) {
-        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
-        attachments[i++] = intel_bits_per_pixel(back_rb);
-      }
-
-      if ((depth_rb != NULL) && (stencil_rb != NULL)) {
-        attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
-        attachments[i++] = intel_bits_per_pixel(depth_rb);
-      } else if (depth_rb != NULL) {
-        attachments[i++] = __DRI_BUFFER_DEPTH;
-        attachments[i++] = intel_bits_per_pixel(depth_rb);
-      } else if (stencil_rb != NULL) {
-        attachments[i++] = __DRI_BUFFER_STENCIL;
-        attachments[i++] = intel_bits_per_pixel(stencil_rb);
-      }
-
-      buffers =
-        (*screen->dri2.loader->getBuffersWithFormat)(drawable,
-                                                     &drawable->w,
-                                                     &drawable->h,
-                                                     attachments, i / 2,
-                                                     &count,
-                                                     drawable->loaderPrivate);
-   } else if (screen->dri2.loader) {
-      i = 0;
-      if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT))
-        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
-      if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
-        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
-      if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
-        attachments[i++] = __DRI_BUFFER_DEPTH;
-      if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
-        attachments[i++] = __DRI_BUFFER_STENCIL;
-
-      buffers = (*screen->dri2.loader->getBuffers)(drawable,
-                                                  &drawable->w,
-                                                  &drawable->h,
-                                                  attachments, i,
-                                                  &count,
-                                                  drawable->loaderPrivate);
+   if (try_separate_stencil) {
+      intel_query_dri2_buffers_with_separate_stencil(intel, drawable, &buffers,
+                                                    &attachments, &count);
+   } else {
+      intel_query_dri2_buffers_no_separate_stencil(intel, drawable, &buffers,
+                                                  &count);
    }
 
    if (buffers == NULL)
       return;
 
-   drawable->x = 0;
-   drawable->y = 0;
-   drawable->backX = 0;
-   drawable->backY = 0;
-   drawable->numClipRects = 1;
-   drawable->pClipRects[0].x1 = 0;
-   drawable->pClipRects[0].y1 = 0;
-   drawable->pClipRects[0].x2 = drawable->w;
-   drawable->pClipRects[0].y2 = drawable->h;
-   drawable->numBackClipRects = 1;
-   drawable->pBackClipRects[0].x1 = 0;
-   drawable->pBackClipRects[0].y1 = 0;
-   drawable->pBackClipRects[0].x2 = drawable->w;
-   drawable->pBackClipRects[0].y2 = drawable->h;
-
-   depth_region = NULL;
    for (i = 0; i < count; i++) {
        switch (buffers[i].attachment) {
        case __DRI_BUFFER_FRONT_LEFT:
@@ -362,6 +333,12 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
           region_name = "dri2 depth buffer";
           break;
 
+       case __DRI_BUFFER_HIZ:
+          /* The hiz region resides in the depth renderbuffer. */
+          rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+          region_name = "dri2 hiz buffer";
+          break;
+
        case __DRI_BUFFER_DEPTH_STENCIL:
           rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
           region_name = "dri2 depth / stencil buffer";
@@ -380,53 +357,26 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
           return;
        }
 
-       if (rb == NULL)
-         continue;
-
-       if (rb->region && rb->region->name == buffers[i].name)
-            continue;
-
-       if (unlikely(INTEL_DEBUG & DEBUG_DRI))
-         fprintf(stderr,
-                 "attaching buffer %d, at %d, cpp %d, pitch %d\n",
-                 buffers[i].name, buffers[i].attachment,
-                 buffers[i].cpp, buffers[i].pitch);
-       
-       if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) {
-         if (unlikely(INTEL_DEBUG & DEBUG_DRI))
-            fprintf(stderr, "(reusing depth buffer as stencil)\n");
-         intel_region_reference(&region, depth_region);
+       if (try_separate_stencil) {
+        intel_process_dri2_buffer_with_separate_stencil(intel, drawable,
+                                                        &buffers[i], rb,
+                                                        region_name);
+       } else {
+        intel_process_dri2_buffer_no_separate_stencil(intel, drawable,
+                                                      &buffers[i], rb,
+                                                      region_name);
        }
-       else
-          region = intel_region_alloc_for_handle(intel->intelScreen,
-                                                buffers[i].cpp,
-                                                drawable->w,
-                                                drawable->h,
-                                                buffers[i].pitch / buffers[i].cpp,
-                                                buffers[i].name,
-                                                region_name);
-
-       if (buffers[i].attachment == __DRI_BUFFER_DEPTH)
-         depth_region = region;
-
-       intel_renderbuffer_set_region(intel, rb, region);
-       intel_region_release(&region);
-
-       if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
-         rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
-         if (rb != NULL) {
-            struct intel_region *stencil_region = NULL;
-
-            if (rb->region && rb->region->name == buffers[i].name)
-                  continue;
+   }
 
-            intel_region_reference(&stencil_region, region);
-            intel_renderbuffer_set_region(intel, rb, stencil_region);
-            intel_region_release(&stencil_region);
-         }
-       }
+   if (try_separate_stencil
+       && intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN) {
+      intel_verify_dri2_has_hiz(intel, drawable, &buffers, &attachments,
+                               &count);
    }
 
+   if (attachments)
+      free(attachments);
+
    driUpdateFramebufferSize(&intel->ctx, drawable);
 }
 
@@ -444,7 +394,7 @@ intel_prepare_render(struct intel_context *intel)
    if (drawable && 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);
+      intel_draw_buffer(&intel->ctx);
       driContext->dri2.draw_stamp = drawable->dri2.stamp;
    }
 
@@ -460,7 +410,7 @@ intel_prepare_render(struct intel_context *intel)
     * mark it as dirty here.
     */
    if (intel->is_front_buffer_rendering)
-      intel->front_buffer_dirty = GL_TRUE;
+      intel->front_buffer_dirty = 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
@@ -481,7 +431,7 @@ intel_prepare_render(struct intel_context *intel)
       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;
+      intel->need_throttle = false;
    }
 }
 
@@ -523,8 +473,6 @@ static const struct dri_debug_control debug_control[] = {
    { "sleep", DEBUG_SLEEP },
    { "stats", DEBUG_STATS },
    { "tile",  DEBUG_TILE },
-   { "sing",  DEBUG_SINGLE_THREAD },
-   { "thre",  DEBUG_SINGLE_THREAD },
    { "wm",    DEBUG_WM },
    { "urb",   DEBUG_URB },
    { "vs",    DEBUG_VS },
@@ -539,10 +487,7 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
     struct intel_context *intel = intel_context(ctx);
 
    _swrast_InvalidateState(ctx, new_state);
-   _swsetup_InvalidateState(ctx, new_state);
    _vbo_InvalidateState(ctx, new_state);
-   _tnl_InvalidateState(ctx, new_state);
-   _tnl_invalidate_vertex_state(ctx, new_state);
 
    intel->NewGLState |= new_state;
 
@@ -551,7 +496,7 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
 }
 
 void
-intel_flush(struct gl_context *ctx)
+intel_flush_rendering_to_batch(struct gl_context *ctx)
 {
    struct intel_context *intel = intel_context(ctx);
 
@@ -560,6 +505,14 @@ intel_flush(struct gl_context *ctx)
 
    if (intel->gen < 4)
       INTEL_FIREVERTICES(intel);
+}
+
+void
+intel_flush(struct gl_context *ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   intel_flush_rendering_to_batch(ctx);
 
    if (intel->batch.used)
       intel_batchbuffer_flush(intel);
@@ -573,29 +526,19 @@ intel_glFlush(struct gl_context *ctx)
    intel_flush(ctx);
    intel_flush_front(ctx);
    if (intel->is_front_buffer_rendering)
-      intel->need_throttle = GL_TRUE;
+      intel->need_throttle = true;
 }
 
 void
 intelFinish(struct gl_context * ctx)
 {
-   struct gl_framebuffer *fb = ctx->DrawBuffer;
-   int i;
+   struct intel_context *intel = intel_context(ctx);
 
    intel_flush(ctx);
    intel_flush_front(ctx);
 
-   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
-       struct intel_renderbuffer *irb;
-
-       irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
-
-       if (irb && irb->region && irb->region->buffer)
-         drm_intel_bo_wait_rendering(irb->region->buffer);
-   }
-   if (fb->_DepthBuffer) {
-      /* XXX: Wait on buffer idle */
-   }
+   if (intel->batch.last_bo)
+      drm_intel_bo_wait_rendering(intel->batch.last_bo);
 }
 
 void
@@ -620,8 +563,7 @@ intelInitDriverFunctions(struct dd_function_table *functions)
    intel_init_syncobj_functions(functions);
 }
 
-
-GLboolean
+bool
 intelInitContext(struct intel_context *intel,
                 int api,
                  const struct gl_config * mesaVis,
@@ -632,13 +574,13 @@ intelInitContext(struct intel_context *intel,
    struct gl_context *ctx = &intel->ctx;
    struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate;
    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
-   struct intel_screen *intelScreen = sPriv->private;
+   struct intel_screen *intelScreen = sPriv->driverPrivate;
    int bo_reuse_mode;
    struct gl_config visual;
 
    /* we can't do anything without a connection to the device */
    if (intelScreen->bufmgr == NULL)
-      return GL_FALSE;
+      return false;
 
    /* Can't rely on invalidate events, fall back to glViewport hack */
    if (!driContextPriv->driScreenPriv->dri2.useInvalidate) {
@@ -654,7 +596,7 @@ intelInitContext(struct intel_context *intel,
    if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx,
                                  functions, (void *) intel)) {
       printf("%s: failed to init mesa context\n", __FUNCTION__);
-      return GL_FALSE;
+      return false;
    }
 
    driContextPriv->driverPrivate = intel;
@@ -662,48 +604,49 @@ intelInitContext(struct intel_context *intel,
    intel->driContext = driContextPriv;
    intel->driFd = sPriv->fd;
 
-   intel->has_xrgb_textures = GL_TRUE;
    intel->gen = intelScreen->gen;
-   if (IS_GEN7(intel->intelScreen->deviceID)) {
-      intel->needs_ff_sync = GL_TRUE;
-      intel->has_luminance_srgb = GL_TRUE;
-   } else if (IS_GEN6(intel->intelScreen->deviceID)) {
-      intel->needs_ff_sync = GL_TRUE;
-      intel->has_luminance_srgb = GL_TRUE;
-   } else if (IS_GEN5(intel->intelScreen->deviceID)) {
-      intel->needs_ff_sync = GL_TRUE;
-      intel->has_luminance_srgb = GL_TRUE;
-   } else if (IS_965(intel->intelScreen->deviceID)) {
-      if (IS_G4X(intel->intelScreen->deviceID)) {
-         intel->has_luminance_srgb = GL_TRUE;
-         intel->is_g4x = GL_TRUE;
-      }
-   } else if (IS_9XX(intel->intelScreen->deviceID)) {
-      if (IS_945(intel->intelScreen->deviceID)) {
-        intel->is_945 = GL_TRUE;
-      }
-   } else {
-      if (intel->intelScreen->deviceID == PCI_CHIP_I830_M ||
-         intel->intelScreen->deviceID == PCI_CHIP_845_G) {
-        intel->has_xrgb_textures = GL_FALSE;
-      }
+
+   const int devID = intelScreen->deviceID;
+
+   if (IS_SNB_GT1(devID) || IS_IVB_GT1(devID))
+      intel->gt = 1;
+   else if (IS_SNB_GT2(devID) || IS_IVB_GT2(devID))
+      intel->gt = 2;
+   else
+      intel->gt = 0;
+
+   if (IS_G4X(devID)) {
+      intel->is_g4x = true;
+   } else if (IS_945(devID)) {
+      intel->is_945 = true;
+   }
+
+   if (intel->gen >= 5) {
+      intel->needs_ff_sync = true;
    }
 
+   intel->has_separate_stencil = intel->intelScreen->hw_has_separate_stencil;
+   intel->must_use_separate_stencil = intel->intelScreen->hw_must_use_separate_stencil;
+   intel->has_hiz = intel->intelScreen->hw_has_hiz;
+
    memset(&ctx->TextureFormatSupported, 0,
          sizeof(ctx->TextureFormatSupported));
-   ctx->TextureFormatSupported[MESA_FORMAT_ARGB8888] = GL_TRUE;
-   if (intel->has_xrgb_textures)
-      ctx->TextureFormatSupported[MESA_FORMAT_XRGB8888] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_ARGB4444] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_ARGB1555] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RGB565] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_L8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_A8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_I8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_AL88] = GL_TRUE;
-   if (intel->gen >= 4)
-      ctx->TextureFormatSupported[MESA_FORMAT_AL1616] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_S8_Z24] = GL_TRUE;
+   ctx->TextureFormatSupported[MESA_FORMAT_ARGB8888] = true;
+   if (devID != PCI_CHIP_I830_M && devID != PCI_CHIP_845_G)
+      ctx->TextureFormatSupported[MESA_FORMAT_XRGB8888] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_ARGB4444] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_ARGB1555] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGB565] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_L8] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_A8] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_I8] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_AL88] = true;
+
+   /* Depth and stencil */
+   ctx->TextureFormatSupported[MESA_FORMAT_S8_Z24] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_X8_Z24] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_S8] = intel->has_separate_stencil;
+
    /*
     * This was disabled in initial FBO enabling to avoid combinations
     * of depth+stencil that wouldn't work together.  We since decided
@@ -711,68 +654,23 @@ intelInitContext(struct intel_context *intel,
     * combo that actually works, so this can probably be re-enabled.
     */
    /*
-   ctx->TextureFormatSupported[MESA_FORMAT_Z16] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_Z24] = GL_TRUE;
+   ctx->TextureFormatSupported[MESA_FORMAT_Z16] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_Z24] = true;
    */
 
    /* ctx->Extensions.MESA_ycbcr_texture */
-   ctx->TextureFormatSupported[MESA_FORMAT_YCBCR] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_YCBCR_REV] = GL_TRUE;
+   ctx->TextureFormatSupported[MESA_FORMAT_YCBCR] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_YCBCR_REV] = true;
 
    /* GL_3DFX_texture_compression_FXT1 */
-   ctx->TextureFormatSupported[MESA_FORMAT_RGB_FXT1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_FXT1] = GL_TRUE;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGB_FXT1] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_FXT1] = true;
 
    /* GL_EXT_texture_compression_s3tc */
-   ctx->TextureFormatSupported[MESA_FORMAT_RGB_DXT1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT3] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT5] = GL_TRUE;
-
-#ifndef I915
-   /* GL_ARB_texture_compression_rgtc */
-   ctx->TextureFormatSupported[MESA_FORMAT_RED_RGTC1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_RED_RGTC1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RG_RGTC2] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_RG_RGTC2] = GL_TRUE;
-
-   /* GL_ARB_texture_rg */
-   ctx->TextureFormatSupported[MESA_FORMAT_R8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_R16] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RG88] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RG1616] = GL_TRUE;
-
-   /* GL_MESA_texture_signed_rgba / GL_EXT_texture_snorm */
-   ctx->TextureFormatSupported[MESA_FORMAT_DUDV8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_RGBA8888_REV] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_R8] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_RG88_REV] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_R16] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_GR1616] = GL_TRUE;
-
-   /* GL_EXT_texture_sRGB */
-   ctx->TextureFormatSupported[MESA_FORMAT_SARGB8] = GL_TRUE;
-   if (intel->gen >= 5 || intel->is_g4x)
-      ctx->TextureFormatSupported[MESA_FORMAT_SRGB_DXT1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT1] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT3] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT5] = GL_TRUE;
-   if (intel->has_luminance_srgb) {
-      ctx->TextureFormatSupported[MESA_FORMAT_SL8] = GL_TRUE;
-      ctx->TextureFormatSupported[MESA_FORMAT_SLA8] = GL_TRUE;
-   }
-
-#ifdef TEXTURE_FLOAT_ENABLED
-   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_RG_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_R_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_INTENSITY_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_LUMINANCE_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_ALPHA_FLOAT32] = GL_TRUE;
-   ctx->TextureFormatSupported[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32] = GL_TRUE;
-#endif
-
-#endif /* !I915 */
+   ctx->TextureFormatSupported[MESA_FORMAT_RGB_DXT1] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT1] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT3] = true;
+   ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT5] = true;
 
    driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
                        sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915");
@@ -828,13 +726,18 @@ intelInitContext(struct intel_context *intel,
 
    ctx->Const.MaxSamples = 1.0;
 
+   if (intel->gen >= 6)
+      ctx->Const.MaxClipPlanes = 8;
+
+   ctx->Const.StripTextureBorder = GL_TRUE;
+
    /* reinitialize the context point state.
     * It depend on constants in __struct gl_contextRec::Const
     */
    _mesa_init_point(ctx);
 
    if (intel->gen >= 4) {
-      ctx->Const.sRGBCapable = GL_TRUE;
+      ctx->Const.sRGBCapable = true;
       if (MAX_WIDTH > 8192)
         ctx->Const.MaxRenderbufferSize = 8192;
    } else {
@@ -849,8 +752,8 @@ intelInitContext(struct intel_context *intel,
    _swsetup_CreateContext(ctx);
  
    /* Configure swrast to match hardware characteristics: */
-   _swrast_allow_pixel_fog(ctx, GL_FALSE);
-   _swrast_allow_vertex_fog(ctx, GL_TRUE);
+   _swrast_allow_pixel_fog(ctx, false);
+   _swrast_allow_vertex_fog(ctx, true);
 
    _mesa_meta_init(ctx);
 
@@ -881,6 +784,7 @@ intelInitContext(struct intel_context *intel,
       intelInitExtensions(ctx);
       break;
    case API_OPENGLES:
+      intelInitExtensionsES1(ctx);
       break;
    case API_OPENGLES2:
       intelInitExtensionsES2(ctx);
@@ -889,19 +793,12 @@ intelInitContext(struct intel_context *intel,
 
    INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control);
    if (INTEL_DEBUG & DEBUG_BUFMGR)
-      dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE);
+      dri_bufmgr_set_debug(intel->bufmgr, true);
 
-   intel_batchbuffer_reset(intel);
+   intel_batchbuffer_init(intel);
 
    intel_fbo_init(intel);
 
-   if (intel->ctx.Mesa_DXTn) {
-      _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
-      _mesa_enable_extension(ctx, "GL_S3_s3tc");
-   }
-   else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) {
-      _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
-   }
    intel->use_texture_tiling = driQueryOptionb(&intel->optionCache,
                                               "texture_tiling");
    intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z");
@@ -924,7 +821,7 @@ intelInitContext(struct intel_context *intel,
       intel->always_flush_cache = 1;
    }
 
-   return GL_TRUE;
+   return true;
 }
 
 void
@@ -962,7 +859,9 @@ intelDestroyContext(__DRIcontext * driContextPriv)
       /* free the Mesa context */
       _mesa_free_context_data(&intel->ctx);
 
-      FREE(intel);
+      _math_matrix_dtr(&intel->ViewportMatrix);
+
+      ralloc_free(intel);
       driContextPriv->driverPrivate = NULL;
    }
 }
@@ -973,7 +872,7 @@ intelUnbindContext(__DRIcontext * driContextPriv)
    /* Unset current context and dispath table */
    _mesa_make_current(NULL, NULL, NULL);
 
-   return GL_TRUE;
+   return true;
 }
 
 GLboolean
@@ -1017,11 +916,611 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
        * 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);
+      intel_draw_buffer(&intel->ctx);
    }
    else {
       _mesa_make_current(NULL, NULL, NULL);
    }
 
-   return GL_TRUE;
+   return true;
+}
+
+/**
+ * \brief Query DRI2 to obtain a DRIdrawable's buffers.
+ *
+ * To determine which DRI buffers to request, examine the renderbuffers
+ * attached to the drawable's framebuffer. Then request the buffers with
+ * DRI2GetBuffers() or DRI2GetBuffersWithFormat().
+ *
+ * This is called from intel_update_renderbuffers(). It is used only if either
+ * the hardware or the X driver lacks separate stencil support.
+ *
+ * \param drawable      Drawable whose buffers are queried.
+ * \param buffers       [out] List of buffers returned by DRI2 query.
+ * \param buffer_count  [out] Number of buffers returned.
+ *
+ * \see intel_update_renderbuffers()
+ * \see DRI2GetBuffers()
+ * \see DRI2GetBuffersWithFormat()
+ */
+static void
+intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
+                                            __DRIdrawable *drawable,
+                                            __DRIbuffer **buffers,
+                                            int *buffer_count)
+{
+   assert(!intel->must_use_separate_stencil);
+
+   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+
+   if (screen->dri2.loader
+       && screen->dri2.loader->base.version > 2
+       && screen->dri2.loader->getBuffersWithFormat != NULL) {
+
+      int i = 0;
+      const int max_attachments = 4;
+      unsigned *attachments = calloc(2 * max_attachments, sizeof(unsigned));
+
+      struct intel_renderbuffer *front_rb;
+      struct intel_renderbuffer *back_rb;
+      struct intel_renderbuffer *depth_rb;
+      struct intel_renderbuffer *stencil_rb;
+
+      front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+      back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+      depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+      stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+      if ((intel->is_front_buffer_rendering ||
+          intel->is_front_buffer_reading ||
+          !back_rb) && front_rb) {
+        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+        attachments[i++] = intel_bits_per_pixel(front_rb);
+      }
+
+      if (back_rb) {
+        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+        attachments[i++] = intel_bits_per_pixel(back_rb);
+      }
+
+      if (depth_rb && stencil_rb) {
+        attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+        attachments[i++] = intel_bits_per_pixel(depth_rb);
+      } else if (depth_rb) {
+        attachments[i++] = __DRI_BUFFER_DEPTH;
+        attachments[i++] = intel_bits_per_pixel(depth_rb);
+      } else if (stencil_rb) {
+        attachments[i++] = __DRI_BUFFER_STENCIL;
+        attachments[i++] = intel_bits_per_pixel(stencil_rb);
+      }
+
+      assert(i <= 2 * max_attachments);
+
+      *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                          &drawable->w,
+                                                          &drawable->h,
+                                                          attachments, i / 2,
+                                                          buffer_count,
+                                                          drawable->loaderPrivate);
+      free(attachments);
+
+   } else if (screen->dri2.loader) {
+
+      int i = 0;
+      const int max_attachments = 4;
+      unsigned *attachments = calloc(max_attachments, sizeof(unsigned));
+
+      if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT))
+        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+      if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
+        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+      if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
+        attachments[i++] = __DRI_BUFFER_DEPTH;
+      if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
+        attachments[i++] = __DRI_BUFFER_STENCIL;
+
+      assert(i <= max_attachments);
+
+      *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                          &drawable->w,
+                                                          &drawable->h,
+                                                          attachments, i,
+                                                          buffer_count,
+                                                          drawable->loaderPrivate);
+      free(attachments);
+
+   } else {
+      *buffers = NULL;
+      *buffer_count = 0;
+   }
+}
+
+/**
+ * \brief Assign a DRI buffer's DRM region to a renderbuffer.
+ *
+ * This is called from intel_update_renderbuffers().  It is used only if
+ * either the hardware or the X driver lacks separate stencil support.
+ *
+ * \par Note:
+ *    DRI buffers whose attachment point is DRI2BufferStencil or
+ *    DRI2BufferDepthStencil are handled as special cases.
+ *
+ * \param buffer_name is a human readable name, such as "dri2 front buffer",
+ *        that is passed to intel_region_alloc_for_handle().
+ *
+ * \see intel_update_renderbuffers()
+ * \see intel_region_alloc_for_handle()
+ */
+static void
+intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
+                                             __DRIdrawable *drawable,
+                                             __DRIbuffer *buffer,
+                                             struct intel_renderbuffer *rb,
+                                             const char *buffer_name)
+{
+   assert(!intel->must_use_separate_stencil);
+
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   struct intel_renderbuffer *depth_rb = NULL;
+
+   if (!rb)
+      return;
+
+   if (rb->mt &&
+       rb->mt->region &&
+       rb->mt->region->name == buffer->name)
+      return;
+
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+      fprintf(stderr,
+             "attaching buffer %d, at %d, cpp %d, pitch %d\n",
+             buffer->name, buffer->attachment,
+             buffer->cpp, buffer->pitch);
+   }
+
+   bool identify_depth_and_stencil = false;
+   if (buffer->attachment == __DRI_BUFFER_STENCIL) {
+      struct intel_renderbuffer *depth_rb =
+        intel_get_renderbuffer(fb, BUFFER_DEPTH);
+      identify_depth_and_stencil = depth_rb && depth_rb->mt;
+   }
+
+   if (identify_depth_and_stencil) {
+      if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+        fprintf(stderr, "(reusing depth buffer as stencil)\n");
+      }
+      intel_miptree_reference(&rb->mt, depth_rb->mt);
+   } else {
+      intel_miptree_release(&rb->mt);
+      struct intel_region *region =
+                   intel_region_alloc_for_handle(intel->intelScreen,
+                                                buffer->cpp,
+                                                drawable->w,
+                                                drawable->h,
+                                                buffer->pitch / buffer->cpp,
+                                                buffer->name,
+                                                buffer_name);
+      if (!region)
+        return;
+
+      rb->mt = intel_miptree_create_for_region(intel,
+                                               GL_TEXTURE_2D,
+                                               rb->Base.Format,
+                                               region);
+      intel_region_release(&region);
+      if (!rb->mt)
+        return;
+   }
+
+   if (buffer->attachment == __DRI_BUFFER_DEPTH_STENCIL) {
+      struct intel_renderbuffer *stencil_rb =
+        intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+      if (!stencil_rb)
+        return;
+
+      /* The rb passed in is the BUFFER_DEPTH attachment, and we need
+       * to associate this region to BUFFER_STENCIL as well.
+       */
+      intel_miptree_reference(&stencil_rb->mt, rb->mt);
+   }
+}
+
+/**
+ * \brief Query DRI2 to obtain a DRIdrawable's buffers.
+ *
+ * To determine which DRI buffers to request, examine the renderbuffers
+ * attached to the drawable's framebuffer. Then request the buffers with
+ * DRI2GetBuffersWithFormat().
+ *
+ * This is called from intel_update_renderbuffers(). It is used when 1) the
+ * hardware supports separate stencil and 2) the X driver's separate stencil
+ * support has been verified to work or is still unknown.
+ *
+ * \param drawable      Drawable whose buffers are queried.
+ * \param buffers       [out] List of buffers returned by DRI2 query.
+ * \param buffer_count  [out] Number of buffers returned.
+ * \param attachments   [out] List of pairs (attachment_point, bits_per_pixel)
+ *                      that were submitted in the DRI2 query. Number of pairs
+ *                      is same as buffer_count.
+ *
+ * \see intel_update_renderbuffers()
+ * \see DRI2GetBuffersWithFormat()
+ * \see enum intel_dri2_has_hiz
+ */
+static void
+intel_query_dri2_buffers_with_separate_stencil(struct intel_context *intel,
+                                              __DRIdrawable *drawable,
+                                              __DRIbuffer **buffers,
+                                              unsigned **attachments,
+                                              int *count)
+{
+   assert(intel->has_separate_stencil);
+
+   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+
+   const int max_attachments = 5;
+   int i = 0;
+
+   *attachments = calloc(2 * max_attachments, sizeof(unsigned));
+   if (!*attachments) {
+      *buffers = NULL;
+      *count = 0;
+      return;
+   }
+
+   struct intel_renderbuffer *front_rb;
+   struct intel_renderbuffer *back_rb;
+   struct intel_renderbuffer *depth_rb;
+   struct intel_renderbuffer *stencil_rb;
+
+   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+   depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+   stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+   if ((intel->is_front_buffer_rendering ||
+       intel->is_front_buffer_reading ||
+       !back_rb) && front_rb) {
+      (*attachments)[i++] = __DRI_BUFFER_FRONT_LEFT;
+      (*attachments)[i++] = intel_bits_per_pixel(front_rb);
+   }
+
+   if (back_rb) {
+      (*attachments)[i++] = __DRI_BUFFER_BACK_LEFT;
+      (*attachments)[i++] = intel_bits_per_pixel(back_rb);
+   }
+
+   /*
+    * We request a separate stencil buffer, and perhaps a hiz buffer too, even
+    * if we do not yet know if the X driver supports it. See the comments for
+    * 'enum intel_dri2_has_hiz'.
+    */
+
+   if (depth_rb) {
+      (*attachments)[i++] = __DRI_BUFFER_DEPTH;
+      (*attachments)[i++] = intel_bits_per_pixel(depth_rb);
+
+      if (intel->vtbl.is_hiz_depth_format(intel, depth_rb->Base.Format)) {
+        /* Depth and hiz buffer have same bpp. */
+        (*attachments)[i++] = __DRI_BUFFER_HIZ;
+        (*attachments)[i++] = intel_bits_per_pixel(depth_rb);
+      }
+   }
+
+   if (stencil_rb) {
+      assert(stencil_rb->Base.Format == MESA_FORMAT_S8);
+      (*attachments)[i++] = __DRI_BUFFER_STENCIL;
+      (*attachments)[i++] = intel_bits_per_pixel(stencil_rb);
+   }
+
+   assert(i <= 2 * max_attachments);
+
+   *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                       &drawable->w,
+                                                       &drawable->h,
+                                                       *attachments, i / 2,
+                                                       count,
+                                                       drawable->loaderPrivate);
+
+   if (!*buffers) {
+      free(*attachments);
+      *attachments = NULL;
+      *count = 0;
+   }
+}
+
+/**
+ * \brief Assign a DRI buffer's DRM region to a renderbuffer.
+ *
+ * This is called from intel_update_renderbuffers().  It is used when 1) the
+ * hardware supports separate stencil and 2) the X driver's separate stencil
+ * support has been verified to work or is still unknown.
+ *
+ * \par Note:
+ *    DRI buffers whose attachment point is DRI2BufferStencil or DRI2BufferHiz
+ *    are handled as special cases.
+ *
+ * \param buffer_name is a human readable name, such as "dri2 front buffer",
+ *        that is passed to intel_region_alloc_for_handle().
+ *
+ * \see intel_update_renderbuffers()
+ * \see intel_region_alloc_for_handle()
+ * \see enum intel_dri2_has_hiz
+ */
+static void
+intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
+                                               __DRIdrawable *drawable,
+                                               __DRIbuffer *buffer,
+                                               struct intel_renderbuffer *rb,
+                                               const char *buffer_name)
+{
+   assert(intel->has_separate_stencil);
+   assert(buffer->attachment != __DRI_BUFFER_DEPTH_STENCIL);
+
+   if (!rb)
+      return;
+
+   /* If the renderbuffer's and DRIbuffer's regions match, then continue. */
+   if ((buffer->attachment != __DRI_BUFFER_HIZ &&
+       rb->mt &&
+       rb->mt->region &&
+       rb->mt->region->name == buffer->name) ||
+       (buffer->attachment == __DRI_BUFFER_HIZ &&
+       rb->mt &&
+       rb->mt->hiz_mt &&
+       rb->mt->hiz_mt->region->name == buffer->name)) {
+      return;
+   }
+
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+      fprintf(stderr,
+             "attaching buffer %d, at %d, cpp %d, pitch %d\n",
+             buffer->name, buffer->attachment,
+             buffer->cpp, buffer->pitch);
+   }
+
+   int buffer_width;
+   int buffer_height;
+   if (buffer->attachment == __DRI_BUFFER_STENCIL) {
+      /* The stencil buffer has quirky pitch requirements.  From Section
+       * 2.11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
+       *    The pitch must be set to 2x the value computed based on width, as
+       *    the stencil buffer is stored with two rows interleaved.
+       *
+       * To satisfy the pitch requirement, the X driver allocated the region
+       * with the following dimensions.
+       */
+       buffer_width = ALIGN(drawable->w, 64);
+       buffer_height = ALIGN(ALIGN(drawable->h, 2) / 2, 64);
+   } else {
+       buffer_width = drawable->w;
+       buffer_height = drawable->h;
+   }
+
+   /* Release the buffer storage now in case we have to return early
+    * due to failure to allocate new storage.
+    */
+   if (buffer->attachment == __DRI_BUFFER_HIZ) {
+      intel_miptree_release(&rb->mt->hiz_mt);
+   } else {
+      intel_miptree_release(&rb->mt);
+   }
+
+   struct intel_region *region =
+      intel_region_alloc_for_handle(intel->intelScreen,
+                                   buffer->cpp,
+                                   buffer_width,
+                                   buffer_height,
+                                   buffer->pitch / buffer->cpp,
+                                   buffer->name,
+                                   buffer_name);
+   if (!region)
+      return;
+
+   struct intel_mipmap_tree *mt =
+      intel_miptree_create_for_region(intel,
+                                     GL_TEXTURE_2D,
+                                     rb->Base.Format,
+                                     region);
+   intel_region_release(&region);
+
+   /* Associate buffer with new storage. */
+   if (buffer->attachment == __DRI_BUFFER_HIZ) {
+      rb->mt->hiz_mt = mt;
+   } else {
+      rb->mt = mt;
+   }
+}
+
+/**
+ * \brief Verify that the X driver supports hiz and separate stencil.
+ *
+ * This implements the cleanup stage of the handshake described in the
+ * comments for 'enum intel_dri2_has_hiz'.
+ *
+ * This should be called from intel_update_renderbuffers() after 1) the
+ * DRIdrawable has been queried for its buffers via DRI2GetBuffersWithFormat()
+ * and 2) the DRM region of each returned DRIbuffer has been assigned to the
+ * appropriate intel_renderbuffer. Furthermore, this should be called *only*
+ * when 1) intel_update_renderbuffers() tried to used the X driver's separate
+ * stencil functionality and 2) it has not yet been determined if the X driver
+ * supports separate stencil.
+ *
+ * If we determine that the X driver does have support, then we set
+ * intel_screen.dri2_has_hiz to true and return.
+ *
+ * If we determine that the X driver lacks support, and we requested
+ * a DRI2BufferDepth and DRI2BufferStencil, then we must remedy the mistake by
+ * taking the following actions:
+ *    1. Discard the framebuffer's stencil and depth renderbuffers.
+ *    2. Create a combined depth/stencil renderbuffer and attach
+ *       it to the framebuffer's depth and stencil attachment points.
+ *    3. Query the drawable for a new set of buffers, which consists of the
+ *       originally requested set plus DRI2BufferDepthStencil.
+ *    4. Assign the DRI2BufferDepthStencil's DRM region to the new
+ *       depth/stencil renderbuffer.
+ *
+ * \pre intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN
+ *
+ * \param drawable      Drawable whose buffers were queried.
+ *
+ * \param buffers       [in/out] As input, the buffer list returned by the
+ *                      original DRI2 query. As output, the current buffer
+ *                      list, which may have been altered by a new DRI2 query.
+ *
+ * \param attachments   [in/out] As input, the attachment list submitted
+ *                      in the original DRI2 query. As output, the attachment
+ *                      list that was submitted in the DRI2 query that
+ *                      obtained the current buffer list, as returned in the
+ *                      output parameter \c buffers.  (Note: If no new query
+ *                      was made, then the list remains unaltered).
+ *
+ * \param count         [out] Number of buffers in the current buffer list, as
+ *                      returned in the output parameter \c buffers.
+ *
+ * \see enum intel_dri2_has_hiz
+ * \see struct intel_screen::dri2_has_hiz
+ * \see intel_update_renderbuffers
+ */
+static void
+intel_verify_dri2_has_hiz(struct intel_context *intel,
+                         __DRIdrawable *drawable,
+                         __DRIbuffer **buffers,
+                         unsigned **attachments,
+                         int *count)
+{
+   assert(intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN);
+
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   struct intel_renderbuffer *stencil_rb =
+      intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+   if (stencil_rb) {
+      /*
+       * We requested a DRI2BufferStencil without knowing if the X driver
+       * supports it. Now, check if X handled the request correctly and clean
+       * up if it did not. (See comments for 'enum intel_dri2_has_hiz').
+       */
+      struct intel_renderbuffer *depth_rb =
+        intel_get_renderbuffer(fb, BUFFER_DEPTH);
+      assert(stencil_rb->Base.Format == MESA_FORMAT_S8);
+      assert(depth_rb && depth_rb->Base.Format == MESA_FORMAT_X8_Z24);
+
+      if (stencil_rb->mt->region->tiling == I915_TILING_NONE) {
+        /*
+         * The stencil buffer is actually W tiled. The region's tiling is
+         * I915_TILING_NONE, however, because the GTT is incapable of W
+         * fencing.
+         */
+        intel->intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_TRUE;
+        return;
+      } else {
+        /*
+         * Oops... the screen doesn't support separate stencil. Discard the
+         * separate depth and stencil buffers and replace them with
+         * a combined depth/stencil buffer. Discard the hiz buffer too.
+         */
+        intel->intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_FALSE;
+        if (intel->must_use_separate_stencil) {
+           _mesa_problem(&intel->ctx,
+                         "intel_context requires separate stencil, but the "
+                         "DRIscreen does not support it. You may need to "
+                         "upgrade the Intel X driver to 2.16.0");
+           abort();
+        }
+
+        /* 1. Discard depth and stencil renderbuffers. */
+        _mesa_remove_renderbuffer(fb, BUFFER_DEPTH);
+        depth_rb = NULL;
+        _mesa_remove_renderbuffer(fb, BUFFER_STENCIL);
+        stencil_rb = NULL;
+
+        /* 2. Create new depth/stencil renderbuffer. */
+        struct intel_renderbuffer *depth_stencil_rb =
+           intel_create_renderbuffer(MESA_FORMAT_S8_Z24);
+        _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depth_stencil_rb->Base);
+        _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depth_stencil_rb->Base);
+
+        /* 3. Append DRI2BufferDepthStencil to attachment list. */
+        int old_count = *count;
+        unsigned int *old_attachments = *attachments;
+        *count = old_count + 1;
+        *attachments = malloc(2 * (*count) * sizeof(unsigned));
+        memcpy(*attachments, old_attachments, 2 * old_count * sizeof(unsigned));
+        free(old_attachments);
+        (*attachments)[2 * old_count + 0] = __DRI_BUFFER_DEPTH_STENCIL;
+        (*attachments)[2 * old_count + 1] = intel_bits_per_pixel(depth_stencil_rb);
+
+        /* 4. Request new set of DRI2 attachments. */
+        __DRIscreen *screen = intel->intelScreen->driScrnPriv;
+        *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                             &drawable->w,
+                                                             &drawable->h,
+                                                             *attachments,
+                                                             *count,
+                                                             count,
+                                                             drawable->loaderPrivate);
+        if (!*buffers)
+           return;
+
+        /*
+         * I don't know how to recover from the failure assertion below.
+         * Rather than fail gradually and unexpectedly, we should just die
+         * now.
+         */
+        assert(*count == old_count + 1);
+
+        /* 5. Assign the DRI buffer's DRM region to the its renderbuffers. */
+        __DRIbuffer *depth_stencil_buffer = NULL;
+        for (int i = 0; i < *count; ++i) {
+           if ((*buffers)[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
+              depth_stencil_buffer = &(*buffers)[i];
+              break;
+           }
+        }
+        struct intel_region *region =
+           intel_region_alloc_for_handle(intel->intelScreen,
+                                         depth_stencil_buffer->cpp,
+                                         drawable->w,
+                                         drawable->h,
+                                         depth_stencil_buffer->pitch
+                                            / depth_stencil_buffer->cpp,
+                                         depth_stencil_buffer->name,
+                                         "dri2 depth / stencil buffer");
+        if (!region)
+           return;
+
+        struct intel_mipmap_tree *mt =
+              intel_miptree_create_for_region(intel,
+                                              GL_TEXTURE_2D,
+                                              depth_stencil_rb->Base.Format,
+                                              region);
+        intel_region_release(&region);
+        if (!mt)
+           return;
+
+        intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_DEPTH)->mt, mt);
+        intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_STENCIL)->mt, mt);
+        intel_miptree_release(&mt);
+      }
+   }
+
+   if (intel_framebuffer_has_hiz(fb)) {
+      /*
+       * In the future, the driver may advertise a GL config with hiz
+       * compatible depth bits and 0 stencil bits (for example, when the
+       * driver gains support for float32 depth buffers). When that day comes,
+       * here we need to verify that the X driver does in fact support hiz and
+       * clean up if it doesn't.
+       *
+       * Presently, however, no verification or clean up is necessary, and
+       * execution should not reach here. If the framebuffer still has a hiz
+       * region, then we have already set dri2_has_hiz to true after
+       * confirming above that the stencil buffer is W tiled.
+       */
+      assert(0);
+   }
 }