i965: Use sample barycentric coordinates with per sample shading
[mesa.git] / src / mesa / drivers / dri / i965 / brw_context.c
index 109f40babe34bc0b65276c93410af55c619d4ec0..fd0ea547dbd094c4fef1405efa42cb3bec19f94c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ Copyright 2003 VMware, Inc.
  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
- Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ Intel funded Tungsten Graphics to
  develop this 3D driver.
+
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:
+
  The above copyright notice and this permission notice (including the
  next paragraph) shall be included in all copies or substantial
  portions of the Software.
+
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
  **********************************************************************/
  /*
   * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Keith Whitwell <keithw@vmware.com>
   */
 
 
@@ -37,7 +37,6 @@
 #include "main/imports.h"
 #include "main/macros.h"
 #include "main/points.h"
-#include "main/simple_list.h"
 #include "main/version.h"
 #include "main/vtxfmt.h"
 
@@ -95,30 +94,39 @@ brw_query_samples_for_format(struct gl_context *ctx, GLenum target,
    }
 }
 
+const char *const brw_vendor_string = "Intel Open Source Technology Center";
+
+const char *
+brw_get_renderer_string(unsigned deviceID)
+{
+   const char *chipset;
+   static char buffer[128];
+
+   switch (deviceID) {
+#undef CHIPSET
+#define CHIPSET(id, symbol, str) case id: chipset = str; break;
+#include "pci_ids/i965_pci_ids.h"
+   default:
+      chipset = "Unknown Intel Chipset";
+      break;
+   }
+
+   (void) driGetRendererString(buffer, chipset, 0);
+   return buffer;
+}
+
 static const GLubyte *
 intelGetString(struct gl_context * ctx, GLenum name)
 {
    const struct brw_context *const brw = brw_context(ctx);
-   const char *chipset;
-   static char buffer[128];
 
    switch (name) {
    case GL_VENDOR:
-      return (GLubyte *) "Intel Open Source Technology Center";
-      break;
+      return (GLubyte *) brw_vendor_string;
 
    case GL_RENDERER:
-      switch (brw->intelScreen->deviceID) {
-#undef CHIPSET
-#define CHIPSET(id, family, str) case id: chipset = str; break;
-#include "pci_ids/i965_pci_ids.h"
-      default:
-         chipset = "Unknown Intel Chipset";
-         break;
-      }
-
-      (void) driGetRendererString(buffer, chipset, 0);
-      return (GLubyte *) buffer;
+      return
+         (GLubyte *) brw_get_renderer_string(brw->intelScreen->deviceID);
 
    default:
       return NULL;
@@ -126,14 +134,11 @@ intelGetString(struct gl_context * ctx, GLenum name)
 }
 
 static void
-intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+intel_viewport(struct gl_context *ctx)
 {
    struct brw_context *brw = brw_context(ctx);
    __DRIcontext *driContext = brw->driContext;
 
-   if (brw->saved_viewport)
-      brw->saved_viewport(ctx, x, y, w, h);
-
    if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
       dri2InvalidateDrawable(driContext->driDrawablePriv);
       dri2InvalidateDrawable(driContext->driReadablePriv);
@@ -152,6 +157,8 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
    brw->NewGLState |= new_state;
 }
 
+#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
+
 static void
 intel_flush_front(struct gl_context *ctx)
 {
@@ -161,8 +168,7 @@ intel_flush_front(struct gl_context *ctx)
    __DRIscreen *const screen = brw->intelScreen->driScrnPriv;
 
    if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
-      if (screen->dri2.loader->flushFrontBuffer != NULL &&
-          driDrawable &&
+      if (flushFront(screen) && driDrawable &&
           driDrawable->loaderPrivate) {
 
          /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
@@ -175,8 +181,7 @@ intel_flush_front(struct gl_context *ctx)
          intel_resolve_for_dri2_flush(brw, driDrawable);
          intel_batchbuffer_flush(brw);
 
-         screen->dri2.loader->flushFrontBuffer(driDrawable,
-                                               driDrawable->loaderPrivate);
+         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
 
          /* We set the dirty bit in intel_prepare_render() if we're
           * front buffer rendering once we get there.
@@ -221,10 +226,8 @@ brw_init_driver_functions(struct brw_context *brw,
     * So EGL still relies on viewport hacks to handle window resizing.
     * This should go away with DRI3000.
     */
-   if (!brw->driContext->driScreenPriv->dri2.useInvalidate) {
-      brw->saved_viewport = functions->Viewport;
+   if (!brw->driContext->driScreenPriv->dri2.useInvalidate)
       functions->Viewport = intel_viewport;
-   }
 
    functions->Flush = intel_glFlush;
    functions->Finish = intelFinish;
@@ -251,9 +254,15 @@ brw_init_driver_functions(struct brw_context *brw,
 
    functions->QuerySamplesForFormat = brw_query_samples_for_format;
 
+   functions->NewTransformFeedback = brw_new_transform_feedback;
+   functions->DeleteTransformFeedback = brw_delete_transform_feedback;
+   functions->GetTransformFeedbackVertexCount =
+      brw_get_transform_feedback_vertex_count;
    if (brw->gen >= 7) {
       functions->BeginTransformFeedback = gen7_begin_transform_feedback;
       functions->EndTransformFeedback = gen7_end_transform_feedback;
+      functions->PauseTransformFeedback = gen7_pause_transform_feedback;
+      functions->ResumeTransformFeedback = gen7_resume_transform_feedback;
    } else {
       functions->BeginTransformFeedback = brw_begin_transform_feedback;
       functions->EndTransformFeedback = brw_end_transform_feedback;
@@ -274,15 +283,20 @@ brw_initialize_context_constants(struct brw_context *brw)
 
    ctx->Const.MaxDualSourceDrawBuffers = 1;
    ctx->Const.MaxDrawBuffers = BRW_MAX_DRAW_BUFFERS;
-   ctx->Const.FragmentProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = BRW_MAX_TEX_UNIT;
    ctx->Const.MaxTextureCoordUnits = 8; /* Mesa limit */
    ctx->Const.MaxTextureUnits =
       MIN2(ctx->Const.MaxTextureCoordUnits,
-           ctx->Const.FragmentProgram.MaxTextureImageUnits);
-   ctx->Const.VertexProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT;
+           ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = BRW_MAX_TEX_UNIT;
+   if (brw->gen >= 7)
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = BRW_MAX_TEX_UNIT;
+   else
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = 0;
    ctx->Const.MaxCombinedTextureImageUnits =
-      ctx->Const.VertexProgram.MaxTextureImageUnits +
-      ctx->Const.FragmentProgram.MaxTextureImageUnits;
+      ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits +
+      ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits +
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits;
 
    ctx->Const.MaxTextureLevels = 14; /* 8192 */
    if (ctx->Const.MaxTextureLevels > MAX_TEXTURE_LEVELS)
@@ -296,7 +310,7 @@ brw_initialize_context_constants(struct brw_context *brw)
       ctx->Const.MaxArrayTextureLayers = 512;
 
    ctx->Const.MaxTextureRectSize = 1 << 12;
-   
+
    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
 
    ctx->Const.MaxRenderbufferSize = 8192;
@@ -321,19 +335,36 @@ brw_initialize_context_constants(struct brw_context *brw)
    ctx->Const.MaxTransformFeedbackSeparateComponents =
       BRW_MAX_SOL_BINDINGS / BRW_MAX_SOL_BUFFERS;
 
-   if (brw->gen == 6) {
-      ctx->Const.MaxSamples = 4;
-      ctx->Const.MaxColorTextureSamples = 4;
-      ctx->Const.MaxDepthTextureSamples = 4;
-      ctx->Const.MaxIntegerSamples = 4;
-   } else if (brw->gen >= 7) {
-      ctx->Const.MaxSamples = 8;
-      ctx->Const.MaxColorTextureSamples = 8;
-      ctx->Const.MaxDepthTextureSamples = 8;
-      ctx->Const.MaxIntegerSamples = 8;
-      ctx->Const.MaxProgramTextureGatherComponents = 4;
+   ctx->Const.AlwaysUseGetTransformFeedbackVertexCount = true;
+
+   int max_samples;
+   const int *msaa_modes = intel_supported_msaa_modes(brw->intelScreen);
+   const int clamp_max_samples =
+      driQueryOptioni(&brw->optionCache, "clamp_max_samples");
+
+   if (clamp_max_samples < 0) {
+      max_samples = msaa_modes[0];
+   } else {
+      /* Select the largest supported MSAA mode that does not exceed
+       * clamp_max_samples.
+       */
+      max_samples = 0;
+      for (int i = 0; msaa_modes[i] != 0; ++i) {
+         if (msaa_modes[i] <= clamp_max_samples) {
+            max_samples = msaa_modes[i];
+            break;
+         }
+      }
    }
 
+   ctx->Const.MaxSamples = max_samples;
+   ctx->Const.MaxColorTextureSamples = max_samples;
+   ctx->Const.MaxDepthTextureSamples = max_samples;
+   ctx->Const.MaxIntegerSamples = max_samples;
+
+   if (brw->gen >= 7)
+      ctx->Const.MaxProgramTextureGatherComponents = 4;
+
    ctx->Const.MinLineWidth = 1.0;
    ctx->Const.MinLineWidthAA = 1.0;
    ctx->Const.MaxLineWidth = 5.0;
@@ -349,41 +380,51 @@ brw_initialize_context_constants(struct brw_context *brw)
    if (brw->gen >= 5 || brw->is_g4x)
       ctx->Const.MaxClipPlanes = 8;
 
-   ctx->Const.VertexProgram.MaxNativeInstructions = 16 * 1024;
-   ctx->Const.VertexProgram.MaxAluInstructions = 0;
-   ctx->Const.VertexProgram.MaxTexInstructions = 0;
-   ctx->Const.VertexProgram.MaxTexIndirections = 0;
-   ctx->Const.VertexProgram.MaxNativeAluInstructions = 0;
-   ctx->Const.VertexProgram.MaxNativeTexInstructions = 0;
-   ctx->Const.VertexProgram.MaxNativeTexIndirections = 0;
-   ctx->Const.VertexProgram.MaxNativeAttribs = 16;
-   ctx->Const.VertexProgram.MaxNativeTemps = 256;
-   ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
-   ctx->Const.VertexProgram.MaxNativeParameters = 1024;
-   ctx->Const.VertexProgram.MaxEnvParams =
-      MIN2(ctx->Const.VertexProgram.MaxNativeParameters,
-          ctx->Const.VertexProgram.MaxEnvParams);
-
-   ctx->Const.FragmentProgram.MaxNativeInstructions = 1024;
-   ctx->Const.FragmentProgram.MaxNativeAluInstructions = 1024;
-   ctx->Const.FragmentProgram.MaxNativeTexInstructions = 1024;
-   ctx->Const.FragmentProgram.MaxNativeTexIndirections = 1024;
-   ctx->Const.FragmentProgram.MaxNativeAttribs = 12;
-   ctx->Const.FragmentProgram.MaxNativeTemps = 256;
-   ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
-   ctx->Const.FragmentProgram.MaxNativeParameters = 1024;
-   ctx->Const.FragmentProgram.MaxEnvParams =
-      MIN2(ctx->Const.FragmentProgram.MaxNativeParameters,
-          ctx->Const.FragmentProgram.MaxEnvParams);
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeInstructions = 16 * 1024;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxAluInstructions = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxTexInstructions = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxTexIndirections = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAluInstructions = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeTexInstructions = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeTexIndirections = 0;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAttribs = 16;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeTemps = 256;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAddressRegs = 1;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeParameters = 1024;
+   ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams =
+      MIN2(ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeParameters,
+          ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams);
+
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeInstructions = 1024;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeAluInstructions = 1024;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeTexInstructions = 1024;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeTexIndirections = 1024;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeAttribs = 12;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeTemps = 256;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeAddressRegs = 0;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeParameters = 1024;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams =
+      MIN2(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxNativeParameters,
+          ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams);
 
    /* Fragment shaders use real, 32-bit twos-complement integers for all
     * integer types.
     */
-   ctx->Const.FragmentProgram.LowInt.RangeMin = 31;
-   ctx->Const.FragmentProgram.LowInt.RangeMax = 30;
-   ctx->Const.FragmentProgram.LowInt.Precision = 0;
-   ctx->Const.FragmentProgram.HighInt = ctx->Const.FragmentProgram.LowInt;
-   ctx->Const.FragmentProgram.MediumInt = ctx->Const.FragmentProgram.LowInt;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].LowInt.RangeMin = 31;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].LowInt.RangeMax = 30;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].LowInt.Precision = 0;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].HighInt = ctx->Const.Program[MESA_SHADER_FRAGMENT].LowInt;
+   ctx->Const.Program[MESA_SHADER_FRAGMENT].MediumInt = ctx->Const.Program[MESA_SHADER_FRAGMENT].LowInt;
+
+   if (brw->gen >= 7) {
+      ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters = MAX_ATOMIC_COUNTERS;
+      ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters = MAX_ATOMIC_COUNTERS;
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicCounters = MAX_ATOMIC_COUNTERS;
+      ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers = BRW_MAX_ABO;
+      ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers = BRW_MAX_ABO;
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers = BRW_MAX_ABO;
+      ctx->Const.MaxCombinedAtomicBuffers = 3 * BRW_MAX_ABO;
+   }
 
    /* Gen6 converts quads to polygon in beginning of 3D pipeline,
     * but we're not sure how it's actually done for vertex order,
@@ -395,18 +436,29 @@ brw_initialize_context_constants(struct brw_context *brw)
 
    ctx->Const.NativeIntegers = true;
    ctx->Const.UniformBooleanTrue = 1;
+
+   /* From the gen4 PRM, volume 4 page 127:
+    *
+    *     "For SURFTYPE_BUFFER non-rendertarget surfaces, this field specifies
+    *      the base address of the first element of the surface, computed in
+    *      software by adding the surface base address to the byte offset of
+    *      the element in the buffer."
+    *
+    * However, unaligned accesses are slower, so enforce buffer alignment.
+    */
    ctx->Const.UniformBufferOffsetAlignment = 16;
+   ctx->Const.TextureBufferOffsetAlignment = 16;
 
    if (brw->gen >= 6) {
       ctx->Const.MaxVarying = 32;
-      ctx->Const.VertexProgram.MaxOutputComponents = 128;
-      ctx->Const.GeometryProgram.MaxInputComponents = 128;
-      ctx->Const.GeometryProgram.MaxOutputComponents = 128;
-      ctx->Const.FragmentProgram.MaxInputComponents = 128;
+      ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 128;
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents = 64;
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents = 128;
+      ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents = 128;
    }
 
    /* We want the GLSL compiler to emit code that uses condition codes */
-   for (int i = 0; i < MESA_SHADER_TYPES; i++) {
+   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
       ctx->ShaderCompilerOptions[i].MaxIfDepth = brw->gen < 6 ? 16 : UINT_MAX;
       ctx->ShaderCompilerOptions[i].EmitCondCodes = true;
       ctx->ShaderCompilerOptions[i].EmitNoNoise = true;
@@ -421,7 +473,19 @@ brw_initialize_context_constants(struct brw_context *brw)
       ctx->ShaderCompilerOptions[i].LowerClipDistance = true;
    }
 
-   ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4 = true;
+   ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = true;
+   ctx->ShaderCompilerOptions[MESA_SHADER_GEOMETRY].OptimizeForAOS = true;
+
+   /* ARB_viewport_array */
+   if (brw->gen >= 7 && ctx->API == API_OPENGL_CORE) {
+      ctx->Const.MaxViewports = GEN7_NUM_VIEWPORTS;
+      ctx->Const.ViewportSubpixelBits = 0;
+
+      /* Cast to float before negating becuase MaxViewportWidth is unsigned.
+       */
+      ctx->Const.ViewportBounds.Min = -(float)ctx->Const.MaxViewportWidth;
+      ctx->Const.ViewportBounds.Max = ctx->Const.MaxViewportWidth;
+   }
 }
 
 /**
@@ -483,13 +547,14 @@ brw_process_driconf_options(struct brw_context *brw)
       driQueryOptionb(options, "disable_glsl_line_continuations");
 }
 
-bool
+GLboolean
 brwCreateContext(gl_api api,
                 const struct gl_config *mesaVis,
                 __DRIcontext *driContextPriv,
                  unsigned major_version,
                  unsigned minor_version,
                  uint32_t flags,
+                 bool notify_reset,
                  unsigned *dri_ctx_error,
                 void *sharedContextPrivate)
 {
@@ -500,6 +565,20 @@ brwCreateContext(gl_api api,
    struct dd_function_table functions;
    struct gl_config visual;
 
+   /* Only allow the __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS flag if the kernel
+    * provides us with context reset notifications.
+    */
+   uint32_t allowed_flags = __DRI_CTX_FLAG_DEBUG
+      | __DRI_CTX_FLAG_FORWARD_COMPATIBLE;
+
+   if (screen->has_context_reset_notification)
+      allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS;
+
+   if (flags & ~allowed_flags) {
+      *dri_ctx_error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
+      return false;
+   }
+
    struct brw_context *brw = rzalloc(NULL, struct brw_context);
    if (!brw) {
       printf("%s: failed to alloc context\n", __FUNCTION__);
@@ -518,7 +597,7 @@ brwCreateContext(gl_api api,
    brw->is_baytrail = devinfo->is_baytrail;
    brw->is_haswell = devinfo->is_haswell;
    brw->has_llc = devinfo->has_llc;
-   brw->has_hiz = devinfo->has_hiz_and_separate_stencil;
+   brw->has_hiz = devinfo->has_hiz_and_separate_stencil && brw->gen < 8;
    brw->has_separate_stencil = devinfo->has_hiz_and_separate_stencil;
    brw->has_pln = devinfo->has_pln;
    brw->has_compr4 = devinfo->has_compr4;
@@ -542,6 +621,9 @@ brwCreateContext(gl_api api,
 
    brw_init_driver_functions(brw, &functions);
 
+   if (notify_reset)
+      functions.GetGraphicsResetStatus = brw_get_graphics_reset_status;
+
    struct gl_context *ctx = &brw->ctx;
 
    if (mesaVis == NULL) {
@@ -556,6 +638,8 @@ brwCreateContext(gl_api api,
       return false;
    }
 
+   driContextSetFlags(ctx, flags);
+
    /* Initialize the software rasterizer and helper modules.
     *
     * As of GL 3.1 core, the gen4+ driver doesn't need the swrast context for
@@ -583,13 +667,18 @@ brwCreateContext(gl_api api,
    brw_process_intel_debug_variable(brw);
    brw_initialize_context_constants(brw);
 
+   ctx->Const.ResetStrategy = notify_reset
+      ? GL_LOSE_CONTEXT_ON_RESET_ARB : GL_NO_RESET_NOTIFICATION_ARB;
+
    /* Reinitialize the context point state.  It depends on ctx->Const values. */
    _mesa_init_point(ctx);
 
-   intelInitExtensions(ctx);
-
    intel_batchbuffer_init(brw);
 
+   brw_init_state(brw);
+
+   intelInitExtensions(ctx);
+
    intel_fbo_init(brw);
 
    if (brw->gen >= 6) {
@@ -647,8 +736,7 @@ brwCreateContext(gl_api api,
 
    brw->prim_restart.in_progress = false;
    brw->prim_restart.enable_cut_index = false;
-
-   brw_init_state( brw );
+   brw->gs.enabled = false;
 
    if (brw->gen < 6) {
       brw->curbe.last_buf = calloc(1, 4096);
@@ -665,6 +753,9 @@ brwCreateContext(gl_api api,
       brw->perf_debug = true;
    }
 
+   if ((flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) != 0)
+      ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
+
    brw_fs_alloc_reg_sets(brw);
    brw_vec4_alloc_reg_set(brw);
 
@@ -827,6 +918,7 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
    if (driContextPriv) {
       struct gl_context *ctx = &brw->ctx;
       struct gl_framebuffer *fb, *readFb;
+      struct intel_renderbuffer *rb = NULL;
 
       if (driDrawPriv == NULL && driReadPriv == NULL) {
          fb = _mesa_get_incomplete_framebuffer();
@@ -834,6 +926,7 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
       } else {
          fb = driDrawPriv->driverPrivate;
          readFb = driReadPriv->driverPrivate;
+         rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
          driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
          driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
       }
@@ -845,7 +938,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
       intel_gles3_srgb_workaround(brw, fb);
       intel_gles3_srgb_workaround(brw, readFb);
 
-      intel_prepare_render(brw);
+      if (rb && !rb->mt) {
+         /* If we don't have buffers for the drawable yet, force a call to
+          * getbuffers here so we can have a default drawable size. */
+         intel_prepare_render(brw);
+      }
+
       _mesa_make_current(ctx, fb, readFb);
    } else {
       _mesa_make_current(NULL, NULL, NULL);
@@ -906,12 +1004,14 @@ intel_process_dri2_buffer(struct brw_context *brw,
                           struct intel_renderbuffer *rb,
                           const char *buffer_name);
 
-void
-intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+static void
+intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable);
+
+static void
+intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
 {
    struct gl_framebuffer *fb = drawable->driverPrivate;
    struct intel_renderbuffer *rb;
-   struct brw_context *brw = context->driverPrivate;
    __DRIbuffer *buffers = NULL;
    int i, count;
    const char *region_name;
@@ -961,6 +1061,27 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
        intel_process_dri2_buffer(brw, drawable, &buffers[i], rb, region_name);
    }
 
+}
+
+void
+intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+   struct brw_context *brw = context->driverPrivate;
+   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
+
+   /* 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
+    * thus ignore the invalidate. */
+   drawable->lastStamp = drawable->dri2.stamp;
+
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI))
+      fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
+
+   if (screen->image.loader)
+      intel_update_image_buffers(brw, drawable);
+   else
+      intel_update_dri2_buffers(brw, drawable);
+
    driUpdateFramebufferSize(&brw->ctx, drawable);
 }
 
@@ -1165,3 +1286,111 @@ intel_process_dri2_buffer(struct brw_context *brw,
                                                  region);
    intel_region_release(&region);
 }
+
+/**
+ * \brief Query DRI image loader 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 from
+ * the image loader
+ *
+ * This is called from intel_update_renderbuffers().
+ *
+ * \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()
+ */
+
+static void
+intel_update_image_buffer(struct brw_context *intel,
+                          __DRIdrawable *drawable,
+                          struct intel_renderbuffer *rb,
+                          __DRIimage *buffer,
+                          enum __DRIimageBufferMask buffer_type)
+{
+   struct intel_region *region = buffer->region;
+
+   if (!rb || !region)
+      return;
+
+   unsigned num_samples = rb->Base.Base.NumSamples;
+
+   /* Check and see if we're already bound to the right
+    * buffer object
+    */
+   if (num_samples == 0) {
+       if (rb->mt &&
+           rb->mt->region &&
+           rb->mt->region->bo == region->bo)
+          return;
+   } else {
+       if (rb->mt &&
+           rb->mt->singlesample_mt &&
+           rb->mt->singlesample_mt->region &&
+           rb->mt->singlesample_mt->region->bo == region->bo)
+          return;
+   }
+
+   intel_miptree_release(&rb->mt);
+   rb->mt = intel_miptree_create_for_image_buffer(intel,
+                                                  buffer_type,
+                                                  intel_rb_format(rb),
+                                                  num_samples,
+                                                  region);
+}
+
+static void
+intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
+{
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
+   struct intel_renderbuffer *front_rb;
+   struct intel_renderbuffer *back_rb;
+   struct __DRIimageList images;
+   unsigned int format;
+   uint32_t buffer_mask = 0;
+
+   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+
+   if (back_rb)
+      format = intel_rb_format(back_rb);
+   else if (front_rb)
+      format = intel_rb_format(front_rb);
+   else
+      return;
+
+   if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+
+   if (back_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
+
+   (*screen->image.loader->getBuffers) (drawable,
+                                        driGLFormatToImageFormat(format),
+                                        &drawable->dri2.stamp,
+                                        drawable->loaderPrivate,
+                                        buffer_mask,
+                                        &images);
+
+   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
+      drawable->w = images.front->width;
+      drawable->h = images.front->height;
+      intel_update_image_buffer(brw,
+                                drawable,
+                                front_rb,
+                                images.front,
+                                __DRI_IMAGE_BUFFER_FRONT);
+   }
+   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
+      drawable->w = images.back->width;
+      drawable->h = images.back->height;
+      intel_update_image_buffer(brw,
+                                drawable,
+                                back_rb,
+                                images.back,
+                                __DRI_IMAGE_BUFFER_BACK);
+   }
+}