From 6c0c95d6045d2d2b4e6a3a2f11457850031c57bc Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Fri, 22 Aug 2014 21:55:11 +0200
Subject: fontconfig libxcb/xcb-proto mesa xkeyboard-config git update 22 Aug
 2014

libxcb/xcb-proto commit 8e3db42d67a0035bb16d16da28bd5eea7a269178
xkeyboard-config commit 10fce2c2baae471795d069f3a5f1307eedb9ff0a
fontconfig       commit 286cdc9c10b0453c25950103b6a1f7170d15bfdc
mesa             commit 97d03b9366bfa55b27feb92aa5afacd9c5f6f421
---
 mesalib/src/mesa/Android.libmesa_dricore.mk        |    1 +
 mesalib/src/mesa/Makefile.am                       |   14 +-
 mesalib/src/mesa/Makefile.sources                  |    1 +
 mesalib/src/mesa/drivers/common/meta.c             |  142 +-
 mesalib/src/mesa/drivers/common/meta.h             |   17 +-
 mesalib/src/mesa/drivers/dri/Android.mk            |    6 +-
 mesalib/src/mesa/drivers/dri/common/Android.mk     |    4 +-
 mesalib/src/mesa/drivers/dri/common/utils.c        |    4 +
 mesalib/src/mesa/drivers/dri/swrast/swrast.c       |   73 +-
 mesalib/src/mesa/drivers/haiku/swrast/SConscript   |    1 +
 mesalib/src/mesa/main/buffers.c                    |    2 +-
 mesalib/src/mesa/main/condrender.c                 |   23 +-
 mesalib/src/mesa/main/context.c                    |  204 +--
 mesalib/src/mesa/main/context.h                    |    3 +
 mesalib/src/mesa/main/copyimage.c                  |    8 +-
 mesalib/src/mesa/main/extensions.c                 |   15 +-
 mesalib/src/mesa/main/extensions.h                 |    2 +-
 mesalib/src/mesa/main/ff_fragment_shader.cpp       |    2 +-
 mesalib/src/mesa/main/ffvertex_prog.c              |    2 +-
 mesalib/src/mesa/main/format_info.py               |    7 +-
 mesalib/src/mesa/main/formats.c                    |   45 +
 mesalib/src/mesa/main/formats.csv                  |    6 +
 mesalib/src/mesa/main/formats.h                    |    9 +
 mesalib/src/mesa/main/glformats.c                  |   10 +
 mesalib/src/mesa/main/mipmap.c                     |   13 +-
 mesalib/src/mesa/main/mtypes.h                     |    7 +-
 mesalib/src/mesa/main/pixelstore.c                 |   42 +
 mesalib/src/mesa/main/pixelstore.h                 |    8 +
 mesalib/src/mesa/main/shaderapi.c                  |    4 +-
 mesalib/src/mesa/main/shared.c                     |    2 +-
 mesalib/src/mesa/main/texcompress.c                |   34 +-
 mesalib/src/mesa/main/texcompress_bptc.c           | 1649 ++++++++++++++++++++
 mesalib/src/mesa/main/texcompress_bptc.h           |   44 +
 mesalib/src/mesa/main/texformat.c                  |    8 +
 mesalib/src/mesa/main/texgetimage.c                |    9 +-
 mesalib/src/mesa/main/teximage.c                   |   64 +-
 mesalib/src/mesa/main/teximage.h                   |    6 -
 mesalib/src/mesa/main/texparam.c                   |    6 +-
 mesalib/src/mesa/main/texstore.c                   |   40 +-
 mesalib/src/mesa/main/texstore.h                   |    9 +-
 mesalib/src/mesa/main/uniform_query.cpp            |    4 +-
 mesalib/src/mesa/main/varray.c                     |    4 +-
 mesalib/src/mesa/main/varray.h                     |    4 +
 mesalib/src/mesa/main/version.c                    |  308 ++--
 mesalib/src/mesa/main/version.h                    |   11 +-
 mesalib/src/mesa/program/ir_to_mesa.cpp            |   11 +-
 mesalib/src/mesa/program/programopt.c              |    2 +-
 mesalib/src/mesa/program/register_allocate.c       |  145 +-
 mesalib/src/mesa/program/register_allocate.h       |    5 +-
 mesalib/src/mesa/program/sampler.cpp               |   11 +
 mesalib/src/mesa/program/sampler.h                 |    3 +
 mesalib/src/mesa/state_tracker/st_atom_texture.c   |    2 +-
 mesalib/src/mesa/state_tracker/st_cb_condrender.c  |   20 +-
 mesalib/src/mesa/state_tracker/st_cb_drawpixels.c  |    2 +-
 mesalib/src/mesa/state_tracker/st_cb_fbo.c         |    2 +-
 mesalib/src/mesa/state_tracker/st_cb_readpixels.c  |    2 +-
 mesalib/src/mesa/state_tracker/st_cb_texture.c     |   94 +-
 mesalib/src/mesa/state_tracker/st_context.c        |   39 +-
 mesalib/src/mesa/state_tracker/st_context.h        |    1 +
 mesalib/src/mesa/state_tracker/st_extensions.c     |  461 +++---
 mesalib/src/mesa/state_tracker/st_extensions.h     |   16 +-
 mesalib/src/mesa/state_tracker/st_format.c         |   95 +-
 mesalib/src/mesa/state_tracker/st_format.h         |    4 +-
 mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp |   72 +-
 mesalib/src/mesa/state_tracker/st_manager.c        |   38 +
 mesalib/src/mesa/state_tracker/st_texture.c        |   16 +-
 mesalib/src/mesa/state_tracker/st_texture.h        |   15 +-
 mesalib/src/mesa/swrast/s_texfetch.c               |   24 +
 mesalib/src/mesa/vbo/vbo_exec_array.c              |    6 +
 69 files changed, 3183 insertions(+), 780 deletions(-)
 create mode 100644 mesalib/src/mesa/main/texcompress_bptc.c
 create mode 100644 mesalib/src/mesa/main/texcompress_bptc.h

(limited to 'mesalib/src/mesa')

diff --git a/mesalib/src/mesa/Android.libmesa_dricore.mk b/mesalib/src/mesa/Android.libmesa_dricore.mk
index 217f6498a..28d6feb35 100644
--- a/mesalib/src/mesa/Android.libmesa_dricore.mk
+++ b/mesalib/src/mesa/Android.libmesa_dricore.mk
@@ -50,6 +50,7 @@ endif # MESA_ENABLE_ASM
 ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
 LOCAL_SRC_FILES += \
 	$(SRCDIR)main/streaming-load-memcpy.c
+LOCAL_CFLAGS := -msse4.1
 endif
 
 LOCAL_C_INCLUDES := \
diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am
index 57c1e4a57..e71bccbbe 100644
--- a/mesalib/src/mesa/Makefile.am
+++ b/mesalib/src/mesa/Makefile.am
@@ -135,22 +135,20 @@ endif
 libmesa_la_SOURCES = \
 	$(MESA_FILES) \
 	$(PROGRAM_FILES) \
-        $(MESA_ASM_FILES_FOR_ARCH)
+	$(MESA_ASM_FILES_FOR_ARCH)
 
 libmesa_la_LIBADD = \
-        $(top_builddir)/src/glsl/libglsl.la \
-	$(ARCH_LIBS) \
-        $()
+	$(top_builddir)/src/glsl/libglsl.la \
+	$(ARCH_LIBS)
 
 libmesagallium_la_SOURCES = \
 	$(MESA_GALLIUM_FILES) \
 	$(PROGRAM_FILES) \
-        $(MESA_ASM_FILES_FOR_ARCH)
+	$(MESA_ASM_FILES_FOR_ARCH)
 
 libmesagallium_la_LIBADD = \
-        $(top_builddir)/src/glsl/libglsl.la \
-	$(ARCH_LIBS) \
-        $()
+	$(top_builddir)/src/glsl/libglsl.la \
+	$(ARCH_LIBS)
 
 libmesa_sse41_la_SOURCES = \
 	main/streaming-load-memcpy.c
diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources
index 594565771..12336c074 100644
--- a/mesalib/src/mesa/Makefile.sources
+++ b/mesalib/src/mesa/Makefile.sources
@@ -97,6 +97,7 @@ MAIN_FILES = \
 	$(SRCDIR)main/stencil.c \
 	$(SRCDIR)main/syncobj.c \
 	$(SRCDIR)main/texcompress.c \
+	$(SRCDIR)main/texcompress_bptc.c \
 	$(SRCDIR)main/texcompress_cpal.c \
 	$(SRCDIR)main/texcompress_rgtc.c \
 	$(SRCDIR)main/texcompress_s3tc.c \
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index a1d06d412..90befd42d 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1527,12 +1527,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
 {
    const char *vs_source =
       "#extension GL_AMD_vertex_shader_layer : enable\n"
+      "#extension GL_ARB_draw_instanced : enable\n"
       "attribute vec4 position;\n"
-      "uniform int layer;\n"
       "void main()\n"
       "{\n"
       "#ifdef GL_AMD_vertex_shader_layer\n"
-      "   gl_Layer = layer;\n"
+      "   gl_Layer = gl_InstanceID;\n"
       "#endif\n"
       "   gl_Position = position;\n"
       "}\n";
@@ -1568,7 +1568,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
    _mesa_LinkProgram(clear->ShaderProg);
 
    clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, "color");
-   clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg, "layer");
 
    has_integer_textures = _mesa_is_gles3(ctx) ||
       (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130);
@@ -1579,12 +1578,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
          ralloc_asprintf(shader_source_mem_ctx,
                          "#version 130\n"
                          "#extension GL_AMD_vertex_shader_layer : enable\n"
+                         "#extension GL_ARB_draw_instanced : enable\n"
                          "in vec4 position;\n"
-                         "uniform int layer;\n"
                          "void main()\n"
                          "{\n"
                          "#ifdef GL_AMD_vertex_shader_layer\n"
-                         "   gl_Layer = layer;\n"
+                         "   gl_Layer = gl_InstanceID;\n"
                          "#endif\n"
                          "   gl_Position = position;\n"
                          "}\n");
@@ -1623,8 +1622,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
 
       clear->IntegerColorLocation =
 	 _mesa_GetUniformLocation(clear->IntegerShaderProg, "color");
-      clear->IntegerLayerLocation =
-         _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer");
    }
 }
 
@@ -1653,8 +1650,8 @@ meta_glsl_clear_cleanup(struct clear_state *clear)
  * Since the bitfield has no associated order, the assignment of draw buffer
  * indices to color attachment indices is rather arbitrary.
  */
-static void
-drawbuffers_from_bitfield(GLbitfield bits)
+void
+_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits)
 {
    GLenum enums[MAX_DRAW_BUFFERS];
    int i = 0;
@@ -1767,7 +1764,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
    /* GL_COLOR_BUFFER_BIT */
    if (buffers & BUFFER_BITS_COLOR) {
       /* Only draw to the buffers we were asked to clear. */
-      drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR);
+      _mesa_meta_drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR);
 
       /* leave colormask state as-is */
 
@@ -1832,15 +1829,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
 
    /* draw quad(s) */
    if (fb->MaxNumLayers > 0) {
-      unsigned layer;
-      assert(glsl && clear->LayerLocation != -1);
-      for (layer = 0; layer < fb->MaxNumLayers; layer++) {
-         if (fb->_IntegerColor)
-            _mesa_Uniform1i(clear->IntegerLayerLocation, layer);
-         else
-            _mesa_Uniform1i(clear->LayerLocation, layer);
-         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-      }
+      _mesa_DrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, fb->MaxNumLayers);
    } else {
       _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }
@@ -2784,7 +2773,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
                                        GLint x, GLint y,
                                        GLsizei width, GLsizei height)
 {
-   struct gl_texture_object *texObj = texImage->TexObject;
    GLuint fbo;
    bool success = false;
    GLbitfield mask;
@@ -2793,8 +2781,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
    if (!ctx->Extensions.ARB_framebuffer_object)
       return false;
 
-   _mesa_unlock_texture(ctx, texObj);
-
    _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
 
    _mesa_GenFramebuffers(1, &fbo);
@@ -2845,7 +2831,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
    success = mask == 0x0;
 
  out:
-   _mesa_lock_texture(ctx, texObj);
    _mesa_DeleteFramebuffers(1, &fbo);
    _mesa_meta_end(ctx);
    return success;
@@ -2863,7 +2848,6 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                            GLint x, GLint y,
                            GLsizei width, GLsizei height)
 {
-   struct gl_texture_object *texObj = texImage->TexObject;
    GLenum format, type;
    GLint bpp;
    void *buf;
@@ -2908,8 +2892,6 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       return;
    }
 
-   _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
-
    /*
     * Read image from framebuffer (disable pixel transfer ops)
     */
@@ -2938,19 +2920,25 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
 
    _mesa_meta_end(ctx);
 
-   _mesa_lock_texture(ctx, texObj); /* re-lock */
-
    free(buf);
 }
 
+static void
+meta_decompress_fbo_cleanup(struct decompress_fbo_state *decompress_fbo)
+{
+   if (decompress_fbo->FBO != 0) {
+      _mesa_DeleteFramebuffers(1, &decompress_fbo->FBO);
+      _mesa_DeleteRenderbuffers(1, &decompress_fbo->RBO);
+   }
+
+   memset(decompress_fbo, 0, sizeof(*decompress_fbo));
+}
 
 static void
 meta_decompress_cleanup(struct decompress_state *decompress)
 {
-   if (decompress->FBO != 0) {
-      _mesa_DeleteFramebuffers(1, &decompress->FBO);
-      _mesa_DeleteRenderbuffers(1, &decompress->RBO);
-   }
+   meta_decompress_fbo_cleanup(&decompress->byteFBO);
+   meta_decompress_fbo_cleanup(&decompress->floatFBO);
 
    if (decompress->VAO != 0) {
       _mesa_DeleteVertexArrays(1, &decompress->VAO);
@@ -2972,7 +2960,7 @@ meta_decompress_cleanup(struct decompress_state *decompress)
  * \param dest  destination buffer
  * \param destRowLength  dest image rowLength (ala GL_PACK_ROW_LENGTH)
  */
-static void
+static bool
 decompress_texture_image(struct gl_context *ctx,
                          struct gl_texture_image *texImage,
                          GLuint slice,
@@ -2980,17 +2968,33 @@ decompress_texture_image(struct gl_context *ctx,
                          GLvoid *dest)
 {
    struct decompress_state *decompress = &ctx->Meta->Decompress;
+   struct decompress_fbo_state *decompress_fbo;
    struct gl_texture_object *texObj = texImage->TexObject;
    const GLint width = texImage->Width;
    const GLint height = texImage->Height;
    const GLint depth = texImage->Height;
    const GLenum target = texObj->Target;
+   GLenum rbFormat;
    GLenum faceTarget;
    struct vertex verts[4];
    GLuint samplerSave;
+   GLenum status;
    const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
                                       ctx->Extensions.ARB_fragment_shader;
 
+   switch (_mesa_get_format_datatype(texImage->TexFormat)) {
+   case GL_FLOAT:
+      decompress_fbo = &decompress->floatFBO;
+      rbFormat = GL_RGBA32F;
+      break;
+   case GL_UNSIGNED_NORMALIZED:
+      decompress_fbo = &decompress->byteFBO;
+      rbFormat = GL_RGBA;
+      break;
+   default:
+      return false;
+   }
+
    if (slice > 0) {
       assert(target == GL_TEXTURE_3D ||
              target == GL_TEXTURE_2D_ARRAY ||
@@ -3001,11 +3005,11 @@ decompress_texture_image(struct gl_context *ctx,
    case GL_TEXTURE_1D:
    case GL_TEXTURE_1D_ARRAY:
       assert(!"No compressed 1D textures.");
-      return;
+      return false;
 
    case GL_TEXTURE_3D:
       assert(!"No compressed 3D textures.");
-      return;
+      return false;
 
    case GL_TEXTURE_CUBE_MAP_ARRAY:
       faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6);
@@ -3027,27 +3031,35 @@ decompress_texture_image(struct gl_context *ctx,
          ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
 
    /* Create/bind FBO/renderbuffer */
-   if (decompress->FBO == 0) {
-      _mesa_GenFramebuffers(1, &decompress->FBO);
-      _mesa_GenRenderbuffers(1, &decompress->RBO);
-      _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO);
-      _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO);
+   if (decompress_fbo->FBO == 0) {
+      _mesa_GenFramebuffers(1, &decompress_fbo->FBO);
+      _mesa_GenRenderbuffers(1, &decompress_fbo->RBO);
+      _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO);
+      _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO);
       _mesa_FramebufferRenderbuffer(GL_FRAMEBUFFER_EXT,
                                        GL_COLOR_ATTACHMENT0_EXT,
                                        GL_RENDERBUFFER_EXT,
-                                       decompress->RBO);
+                                       decompress_fbo->RBO);
    }
    else {
-      _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO);
+      _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO);
    }
 
    /* alloc dest surface */
-   if (width > decompress->Width || height > decompress->Height) {
-      _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO);
-      _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA,
-                                   width, height);
-      decompress->Width = width;
-      decompress->Height = height;
+   if (width > decompress_fbo->Width || height > decompress_fbo->Height) {
+      _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO);
+      _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, rbFormat,
+                                width, height);
+      status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+      if (status != GL_FRAMEBUFFER_COMPLETE) {
+         /* If the framebuffer isn't complete then we'll leave
+          * decompress_fbo->Width as zero so that it will fail again next time
+          * too */
+         _mesa_meta_end(ctx);
+         return false;
+      }
+      decompress_fbo->Width = width;
+      decompress_fbo->Height = height;
    }
 
    if (use_glsl_version) {
@@ -3169,6 +3181,8 @@ decompress_texture_image(struct gl_context *ctx,
    _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
 
    _mesa_meta_end(ctx);
+
+   return true;
 }
 
 
@@ -3182,17 +3196,10 @@ _mesa_meta_GetTexImage(struct gl_context *ctx,
                        GLenum format, GLenum type, GLvoid *pixels,
                        struct gl_texture_image *texImage)
 {
-   /* We can only use the decompress-with-blit method here if the texels are
-    * unsigned, normalized values.  We could handle signed and unnormalized 
-    * with floating point renderbuffers...
-    */
-   if (_mesa_is_format_compressed(texImage->TexFormat) &&
-       _mesa_get_format_datatype(texImage->TexFormat)
-       == GL_UNSIGNED_NORMALIZED) {
-      struct gl_texture_object *texObj = texImage->TexObject;
+   if (_mesa_is_format_compressed(texImage->TexFormat)) {
       GLuint slice;
-      /* Need to unlock the texture here to prevent deadlock... */
-      _mesa_unlock_texture(ctx, texObj);
+      bool result;
+
       for (slice = 0; slice < texImage->Depth; slice++) {
          void *dst;
          if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY
@@ -3212,14 +3219,17 @@ _mesa_meta_GetTexImage(struct gl_context *ctx,
          else {
             dst = pixels;
          }
-         decompress_texture_image(ctx, texImage, slice, format, type, dst);
+         result = decompress_texture_image(ctx, texImage, slice,
+                                           format, type, dst);
+         if (!result)
+            break;
       }
-      /* ... and relock it */
-      _mesa_lock_texture(ctx, texObj);
-   }
-   else {
-      _mesa_get_teximage(ctx, format, type, pixels, texImage);
+
+      if (result)
+         return;
    }
+
+   _mesa_get_teximage(ctx, format, type, pixels, texImage);
 }
 
 
@@ -3515,15 +3525,11 @@ _mesa_meta_ClearTexSubImage(struct gl_context *ctx,
 {
    bool res;
 
-   _mesa_unlock_texture(ctx, texImage->TexObject);
-
    res = cleartexsubimage_using_fbo(ctx, texImage,
                                     xoffset, yoffset, zoffset,
                                     width, height, depth,
                                     clearValue);
 
-   _mesa_lock_texture(ctx, texImage->TexObject);
-
    if (res)
       return;
 
diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h
index e2da2f427..56ba9bc65 100644
--- a/mesalib/src/mesa/drivers/common/meta.h
+++ b/mesalib/src/mesa/drivers/common/meta.h
@@ -342,14 +342,24 @@ struct gen_mipmap_state
    struct blit_shader_table shaders;
 };
 
+/**
+ * One of the FBO states for decompress_state. There will be one for each
+ * required renderbuffer format.
+ */
+struct decompress_fbo_state
+{
+   GLuint FBO, RBO;
+   GLint Width, Height;
+};
+
 /**
  * State for texture decompression
  */
 struct decompress_state
 {
    GLuint VAO;
-   GLuint VBO, FBO, RBO, Sampler;
-   GLint Width, Height;
+   struct decompress_fbo_state byteFBO, floatFBO;
+   GLuint VBO, Sampler;
 
    struct blit_shader_table shaders;
 };
@@ -501,6 +511,9 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
                    GLfloat width, GLfloat height);
 
 /* meta-internal functions */
+void
+_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits);
+
 GLuint
 _mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target,
                                      const GLcharARB *source);
diff --git a/mesalib/src/mesa/drivers/dri/Android.mk b/mesalib/src/mesa/drivers/dri/Android.mk
index e0cf51c58..935722c53 100644
--- a/mesalib/src/mesa/drivers/dri/Android.mk
+++ b/mesalib/src/mesa/drivers/dri/Android.mk
@@ -35,15 +35,15 @@ MESA_DRI_CFLAGS := \
 	-DHAVE_ANDROID_PLATFORM
 
 MESA_DRI_C_INCLUDES := \
+	$(MESA_TOP)/src \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,libmesa_dri_common) \
 	$(addprefix $(MESA_TOP)/, $(mesa_dri_common_INCLUDES)) \
-	$(DRM_TOP) \
-	$(DRM_TOP)/include/drm \
+	$(TARGET_OUT_HEADERS)/libdrm \
 	external/expat/lib
 
 MESA_DRI_WHOLE_STATIC_LIBRARIES := \
 	libmesa_glsl \
-	libmegadriver_stub \
+	libmesa_megadriver_stub \
 	libmesa_dri_common \
 	libmesa_dricore
 
diff --git a/mesalib/src/mesa/drivers/dri/common/Android.mk b/mesalib/src/mesa/drivers/dri/common/Android.mk
index a172a0bc6..b95feb679 100644
--- a/mesalib/src/mesa/drivers/dri/common/Android.mk
+++ b/mesalib/src/mesa/drivers/dri/common/Android.mk
@@ -88,13 +88,13 @@ include $(MESA_COMMON_MK)
 include $(BUILD_STATIC_LIBRARY)
 
 #
-# Build libmegadriver_stub
+# Build libmesa_megadriver_stub
 #
 
 include $(CLEAR_VARS)
 include $(LOCAL_PATH)/Makefile.sources
 
-LOCAL_MODULE := libmegadriver_stub
+LOCAL_MODULE := libmesa_megadriver_stub
 LOCAL_MODULE_CLASS := STATIC_LIBRARIES
 LOCAL_C_INCLUDES := \
     $(MESA_DRI_C_INCLUDES)
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c
index eee77ec69..e0b3db8cf 100644
--- a/mesalib/src/mesa/drivers/dri/common/utils.c
+++ b/mesalib/src/mesa/drivers/dri/common/utils.c
@@ -519,6 +519,10 @@ driQueryRendererIntegerCommon(__DRIscreen *psp, int param, unsigned int *value)
       value[2] = v[2];
       return 0;
    }
+   case __DRI2_RENDERER_PREFERRED_PROFILE:
+      value[0] = (psp->max_gl_core_version != 0)
+         ? (1U << __DRI_API_OPENGL_CORE) : (1U << __DRI_API_OPENGL);
+      return 0;
    case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION:
       value[0] = psp->max_gl_core_version / 10;
       value[1] = psp->max_gl_core_version % 10;
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index 888138115..e28991b0c 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -61,6 +61,9 @@
 
 const __DRIextension **__driDriverGetExtensions_swrast(void);
 
+const char const *swrast_vendor_string = "Mesa Project";
+const char const *swrast_renderer_string = "Software Rasterizer";
+
 /**
  * Screen and config-related functions
  */
@@ -117,8 +120,74 @@ static const __DRItexBufferExtension swrastTexBufferExtension = {
    .releaseTexBuffer    = NULL,
 };
 
+
+static int
+swrast_query_renderer_integer(__DRIscreen *psp, int param,
+			       unsigned int *value)
+{
+   switch (param) {
+   case __DRI2_RENDERER_VENDOR_ID:
+   case __DRI2_RENDERER_DEVICE_ID:
+      /* Return 0xffffffff for both vendor and device id */
+      value[0] = 0xffffffff;
+      return 0;
+   case __DRI2_RENDERER_ACCELERATED:
+      value[0] = 0;
+      return 0;
+   case __DRI2_RENDERER_VIDEO_MEMORY: {
+      /* XXX: Do we want to return the full amount of system memory ? */
+      const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
+      const long system_page_size = sysconf(_SC_PAGE_SIZE);
+
+      if (system_memory_pages <= 0 || system_page_size <= 0)
+         return -1;
+
+      const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
+         * (uint64_t) system_page_size;
+
+      const unsigned system_memory_megabytes =
+         (unsigned) (system_memory_bytes / (1024 * 1024));
+
+      value[0] = system_memory_megabytes;
+      return 0;
+   }
+   case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
+      /**
+       * XXX: Perhaps we should return 1 ?
+       * See issue #7 from the spec, currently UNRESOLVED.
+       */
+      value[0] = 0;
+      return 0;
+   default:
+      return driQueryRendererIntegerCommon(psp, param, value);
+   }
+}
+
+static int
+swrast_query_renderer_string(__DRIscreen *psp, int param, const char **value)
+{
+   switch (param) {
+   case __DRI2_RENDERER_VENDOR_ID:
+      value[0] = swrast_vendor_string;
+      return 0;
+   case __DRI2_RENDERER_DEVICE_ID:
+      value[0] = swrast_renderer_string;
+      return 0;
+   default:
+      return -1;
+   }
+}
+
+static const __DRI2rendererQueryExtension swrast_query_renderer_extension = {
+   .base = { __DRI2_RENDERER_QUERY, 1 },
+
+   .queryInteger        = swrast_query_renderer_integer,
+   .queryString         = swrast_query_renderer_string
+};
+
 static const __DRIextension *dri_screen_extensions[] = {
     &swrastTexBufferExtension.base,
+    &swrast_query_renderer_extension.base,
     NULL
 };
 
@@ -599,9 +668,9 @@ get_string(struct gl_context *ctx, GLenum pname)
     (void) ctx;
     switch (pname) {
 	case GL_VENDOR:
-	    return (const GLubyte *) "Mesa Project";
+	    return (const GLubyte *) swrast_vendor_string;
 	case GL_RENDERER:
-	    return (const GLubyte *) "Software Rasterizer";
+	    return (const GLubyte *) swrast_renderer_string;
 	default:
 	    return NULL;
     }
diff --git a/mesalib/src/mesa/drivers/haiku/swrast/SConscript b/mesalib/src/mesa/drivers/haiku/swrast/SConscript
index aef730098..2c25f727d 100644
--- a/mesalib/src/mesa/drivers/haiku/swrast/SConscript
+++ b/mesalib/src/mesa/drivers/haiku/swrast/SConscript
@@ -3,6 +3,7 @@ Import('*')
 env = env.Clone()
 
 env.Append(CPPPATH = [
+    '#/src',
     '#/src/mapi',
     '#/src/mesa',
     '#/src/mesa/main',
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c
index 140cf6e82..8a0852c42 100644
--- a/mesalib/src/mesa/main/buffers.c
+++ b/mesalib/src/mesa/main/buffers.c
@@ -498,7 +498,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
     * (ex: glDrawBuffer(GL_FRONT_AND_BACK)).
     * Otherwise, destMask[x] can only have one bit set.
     */
-   if (_mesa_bitcount(destMask[0]) > 1) {
+   if (n > 0 && _mesa_bitcount(destMask[0]) > 1) {
       GLuint count = 0, destMask0 = destMask[0];
       while (destMask0) {
          GLint bufIndex = ffs(destMask0) - 1;
diff --git a/mesalib/src/mesa/main/condrender.c b/mesalib/src/mesa/main/condrender.c
index 0ad1e5c2a..75f9d74bc 100644
--- a/mesalib/src/mesa/main/condrender.c
+++ b/mesalib/src/mesa/main/condrender.c
@@ -77,8 +77,14 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode)
    case GL_QUERY_NO_WAIT:
    case GL_QUERY_BY_REGION_WAIT:
    case GL_QUERY_BY_REGION_NO_WAIT:
-      /* OK */
-      break;
+      break; /* OK */
+   case GL_QUERY_WAIT_INVERTED:
+   case GL_QUERY_NO_WAIT_INVERTED:
+   case GL_QUERY_BY_REGION_WAIT_INVERTED:
+   case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+      if (ctx->Extensions.ARB_conditional_render_inverted)
+         break; /* OK */
+      /* fallthrough - invalid */
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glBeginConditionalRender(mode=%s)",
                   _mesa_lookup_enum_by_nr(mode));
@@ -156,12 +162,25 @@ _mesa_check_conditional_render(struct gl_context *ctx)
          ctx->Driver.WaitQuery(ctx, q);
       }
       return q->Result > 0;
+   case GL_QUERY_BY_REGION_WAIT_INVERTED:
+      /* fall-through */
+   case GL_QUERY_WAIT_INVERTED:
+      if (!q->Ready) {
+         ctx->Driver.WaitQuery(ctx, q);
+      }
+      return q->Result == 0;
    case GL_QUERY_BY_REGION_NO_WAIT:
       /* fall-through */
    case GL_QUERY_NO_WAIT:
       if (!q->Ready)
          ctx->Driver.CheckQuery(ctx, q);
       return q->Ready ? (q->Result > 0) : GL_TRUE;
+   case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+      /* fall-through */
+   case GL_QUERY_NO_WAIT_INVERTED:
+      if (!q->Ready)
+         ctx->Driver.CheckQuery(ctx, q);
+      return q->Ready ? (q->Result == 0) : GL_TRUE;
    default:
       _mesa_problem(ctx, "Bad cond render mode %s in "
                     " _mesa_check_conditional_render()",
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 50aae8bf6..232084267 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -464,7 +464,7 @@ _mesa_init_current(struct gl_context *ctx)
  * Important: drivers should override these with actual limits.
  */
 static void
-init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
+init_program_limits(struct gl_constants *consts, gl_shader_stage stage,
                     struct gl_program_constants *prog)
 {
    prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
@@ -546,7 +546,7 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
 
    prog->MaxUniformBlocks = 12;
    prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
-                                         ctx->Const.MaxUniformBlockSize / 4 *
+                                         consts->MaxUniformBlockSize / 4 *
                                          prog->MaxUniformBlocks);
 
    prog->MaxAtomicBuffers = 0;
@@ -559,161 +559,161 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
  * Use defaults from config.h.  The device drivers will often override
  * some of these values (such as number of texture units).
  */
-static void 
-_mesa_init_constants(struct gl_context *ctx)
+void
+_mesa_init_constants(struct gl_constants *consts, gl_api api)
 {
    int i;
-   assert(ctx);
+   assert(consts);
 
    /* Constants, may be overriden (usually only reduced) by device drivers */
-   ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES;
-   ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
-   ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
-   ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
-   ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
-   ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
-   ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
-   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
-   ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
-                                     ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
-   ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
-   ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
-   ctx->Const.MaxTextureBufferSize = 65536;
-   ctx->Const.TextureBufferOffsetAlignment = 1;
-   ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
-   ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
-   ctx->Const.MinPointSize = MIN_POINT_SIZE;
-   ctx->Const.MaxPointSize = MAX_POINT_SIZE;
-   ctx->Const.MinPointSizeAA = MIN_POINT_SIZE;
-   ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE;
-   ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
-   ctx->Const.MinLineWidth = MIN_LINE_WIDTH;
-   ctx->Const.MaxLineWidth = MAX_LINE_WIDTH;
-   ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH;
-   ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH;
-   ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
-   ctx->Const.MaxClipPlanes = 6;
-   ctx->Const.MaxLights = MAX_LIGHTS;
-   ctx->Const.MaxShininess = 128.0;
-   ctx->Const.MaxSpotExponent = 128.0;
-   ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH;
-   ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
-   ctx->Const.MinMapBufferAlignment = 64;
+   consts->MaxTextureMbytes = MAX_TEXTURE_MBYTES;
+   consts->MaxTextureLevels = MAX_TEXTURE_LEVELS;
+   consts->Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
+   consts->MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
+   consts->MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
+   consts->MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
+   consts->MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
+   consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+   consts->MaxTextureUnits = MIN2(consts->MaxTextureCoordUnits,
+                                     consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
+   consts->MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
+   consts->MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+   consts->MaxTextureBufferSize = 65536;
+   consts->TextureBufferOffsetAlignment = 1;
+   consts->MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
+   consts->SubPixelBits = SUB_PIXEL_BITS;
+   consts->MinPointSize = MIN_POINT_SIZE;
+   consts->MaxPointSize = MAX_POINT_SIZE;
+   consts->MinPointSizeAA = MIN_POINT_SIZE;
+   consts->MaxPointSizeAA = MAX_POINT_SIZE;
+   consts->PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
+   consts->MinLineWidth = MIN_LINE_WIDTH;
+   consts->MaxLineWidth = MAX_LINE_WIDTH;
+   consts->MinLineWidthAA = MIN_LINE_WIDTH;
+   consts->MaxLineWidthAA = MAX_LINE_WIDTH;
+   consts->LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
+   consts->MaxClipPlanes = 6;
+   consts->MaxLights = MAX_LIGHTS;
+   consts->MaxShininess = 128.0;
+   consts->MaxSpotExponent = 128.0;
+   consts->MaxViewportWidth = MAX_VIEWPORT_WIDTH;
+   consts->MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+   consts->MinMapBufferAlignment = 64;
 
    /* Driver must override these values if ARB_viewport_array is supported. */
-   ctx->Const.MaxViewports = 1;
-   ctx->Const.ViewportSubpixelBits = 0;
-   ctx->Const.ViewportBounds.Min = 0;
-   ctx->Const.ViewportBounds.Max = 0;
+   consts->MaxViewports = 1;
+   consts->ViewportSubpixelBits = 0;
+   consts->ViewportBounds.Min = 0;
+   consts->ViewportBounds.Max = 0;
 
    /** GL_ARB_uniform_buffer_object */
-   ctx->Const.MaxCombinedUniformBlocks = 36;
-   ctx->Const.MaxUniformBufferBindings = 36;
-   ctx->Const.MaxUniformBlockSize = 16384;
-   ctx->Const.UniformBufferOffsetAlignment = 1;
+   consts->MaxCombinedUniformBlocks = 36;
+   consts->MaxUniformBufferBindings = 36;
+   consts->MaxUniformBlockSize = 16384;
+   consts->UniformBufferOffsetAlignment = 1;
 
    /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */
-   ctx->Const.MaxUserAssignableUniformLocations =
+   consts->MaxUserAssignableUniformLocations =
       4 * MESA_SHADER_STAGES * MAX_UNIFORMS;
 
    for (i = 0; i < MESA_SHADER_STAGES; i++)
-      init_program_limits(ctx, i, &ctx->Const.Program[i]);
+      init_program_limits(consts, i, &consts->Program[i]);
 
-   ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
-   ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+   consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES;
+   consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
 
    /* CheckArrayBounds is overriden by drivers/x11 for X server */
-   ctx->Const.CheckArrayBounds = GL_FALSE;
+   consts->CheckArrayBounds = GL_FALSE;
 
    /* GL_ARB_draw_buffers */
-   ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+   consts->MaxDrawBuffers = MAX_DRAW_BUFFERS;
 
-   ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
-   ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
+   consts->MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
+   consts->MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
 
-   ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
-   ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
-   ctx->Const.MaxVarying = 16; /* old limit not to break tnl and swrast */
-   ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
-   ctx->Const.MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
-   ctx->Const.MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
+   consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+   consts->MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+   consts->MaxVarying = 16; /* old limit not to break tnl and swrast */
+   consts->Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+   consts->MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
+   consts->MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
 
    /* Shading language version */
-   if (_mesa_is_desktop_gl(ctx)) {
-      ctx->Const.GLSLVersion = 120;
-      _mesa_override_glsl_version(ctx);
+   if (api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) {
+      consts->GLSLVersion = 120;
+      _mesa_override_glsl_version(consts);
    }
-   else if (ctx->API == API_OPENGLES2) {
-      ctx->Const.GLSLVersion = 100;
+   else if (api == API_OPENGLES2) {
+      consts->GLSLVersion = 100;
    }
-   else if (ctx->API == API_OPENGLES) {
-      ctx->Const.GLSLVersion = 0; /* GLSL not supported */
+   else if (api == API_OPENGLES) {
+      consts->GLSLVersion = 0; /* GLSL not supported */
    }
 
    /* GL_ARB_framebuffer_object */
-   ctx->Const.MaxSamples = 0;
+   consts->MaxSamples = 0;
 
    /* GL_ARB_sync */
-   ctx->Const.MaxServerWaitTimeout = 0x1fff7fffffffULL;
+   consts->MaxServerWaitTimeout = 0x1fff7fffffffULL;
 
    /* GL_EXT_provoking_vertex */
-   ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+   consts->QuadsFollowProvokingVertexConvention = GL_TRUE;
 
    /* GL_EXT_transform_feedback */
-   ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
-   ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
-   ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
-   ctx->Const.MaxVertexStreams = 1;
+   consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
+   consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+   consts->MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+   consts->MaxVertexStreams = 1;
 
    /* GL 3.2  */
-   ctx->Const.ProfileMask = ctx->API == API_OPENGL_CORE
+   consts->ProfileMask = api == API_OPENGL_CORE
                           ? GL_CONTEXT_CORE_PROFILE_BIT
                           : GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
 
    /** GL_EXT_gpu_shader4 */
-   ctx->Const.MinProgramTexelOffset = -8;
-   ctx->Const.MaxProgramTexelOffset = 7;
+   consts->MinProgramTexelOffset = -8;
+   consts->MaxProgramTexelOffset = 7;
 
    /* GL_ARB_texture_gather */
-   ctx->Const.MinProgramTextureGatherOffset = -8;
-   ctx->Const.MaxProgramTextureGatherOffset = 7;
+   consts->MinProgramTextureGatherOffset = -8;
+   consts->MaxProgramTextureGatherOffset = 7;
 
    /* GL_ARB_robustness */
-   ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
+   consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
 
    /* PrimitiveRestart */
-   ctx->Const.PrimitiveRestartInSoftware = GL_FALSE;
+   consts->PrimitiveRestartInSoftware = GL_FALSE;
 
    /* ES 3.0 or ARB_ES3_compatibility */
-   ctx->Const.MaxElementIndex = 0xffffffffu;
+   consts->MaxElementIndex = 0xffffffffu;
 
    /* GL_ARB_texture_multisample */
-   ctx->Const.MaxColorTextureSamples = 1;
-   ctx->Const.MaxDepthTextureSamples = 1;
-   ctx->Const.MaxIntegerSamples = 1;
+   consts->MaxColorTextureSamples = 1;
+   consts->MaxDepthTextureSamples = 1;
+   consts->MaxIntegerSamples = 1;
 
    /* GL_ARB_shader_atomic_counters */
-   ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
-   ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
-   ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
-   ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
+   consts->MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
+   consts->MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
+   consts->MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
+   consts->MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
 
    /* GL_ARB_vertex_attrib_binding */
-   ctx->Const.MaxVertexAttribRelativeOffset = 2047;
-   ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
+   consts->MaxVertexAttribRelativeOffset = 2047;
+   consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
 
    /* GL_ARB_compute_shader */
-   ctx->Const.MaxComputeWorkGroupCount[0] = 65535;
-   ctx->Const.MaxComputeWorkGroupCount[1] = 65535;
-   ctx->Const.MaxComputeWorkGroupCount[2] = 65535;
-   ctx->Const.MaxComputeWorkGroupSize[0] = 1024;
-   ctx->Const.MaxComputeWorkGroupSize[1] = 1024;
-   ctx->Const.MaxComputeWorkGroupSize[2] = 64;
-   ctx->Const.MaxComputeWorkGroupInvocations = 1024;
+   consts->MaxComputeWorkGroupCount[0] = 65535;
+   consts->MaxComputeWorkGroupCount[1] = 65535;
+   consts->MaxComputeWorkGroupCount[2] = 65535;
+   consts->MaxComputeWorkGroupSize[0] = 1024;
+   consts->MaxComputeWorkGroupSize[1] = 1024;
+   consts->MaxComputeWorkGroupSize[2] = 64;
+   consts->MaxComputeWorkGroupInvocations = 1024;
 
    /** GL_ARB_gpu_shader5 */
-   ctx->Const.MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
-   ctx->Const.MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET;
+   consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
+   consts->MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET;
 }
 
 
@@ -790,10 +790,10 @@ init_attrib_groups(struct gl_context *ctx)
    assert(ctx);
 
    /* Constants */
-   _mesa_init_constants( ctx );
+   _mesa_init_constants(&ctx->Const, ctx->API);
 
    /* Extensions */
-   _mesa_init_extensions( ctx );
+   _mesa_init_extensions(&ctx->Extensions);
 
    /* Attribute Groups */
    _mesa_init_accum( ctx );
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index 792ab4cd5..d902ea76e 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -143,6 +143,9 @@ _mesa_get_current_context(void);
 
 /*@}*/
 
+extern void
+_mesa_init_constants(struct gl_constants *consts, gl_api api);
+
 extern void
 _mesa_init_get_hash(struct gl_context *ctx);
 
diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c
index dcbc83de6..df7d7c272 100644
--- a/mesalib/src/mesa/main/copyimage.c
+++ b/mesalib/src/mesa/main/copyimage.c
@@ -277,6 +277,12 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                   dstX, dstY, dstZ,
                   srcWidth, srcHeight, srcWidth);
 
+   if (!ctx->Extensions.ARB_copy_image) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glCopyImageSubData(extension not available)");
+      return;
+   }
+
    if (!prepare_target(ctx, srcName, &srcTarget, srcLevel,
                        &srcTexObj, &srcTexImage, &tmpTexNames[0], "src"))
       goto cleanup;
@@ -328,7 +334,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                                                    srcTexImage->InternalFormat,
                                                    dstTexImage->InternalFormat)) {
    } else {
-      return; /* Error loged by _mesa_texture_view_compatible_format */
+      return; /* Error logged by _mesa_texture_view_compatible_format */
    }
 
    for (i = 0; i < srcDepth; ++i) {
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index d60838a1c..553c01e34 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -94,6 +94,7 @@ static const struct extension extension_table[] = {
    { "GL_ARB_color_buffer_float",                  o(ARB_color_buffer_float),                  GL,             2004 },
    { "GL_ARB_compressed_texture_pixel_storage",    o(dummy_true),                              GL,             2011 },
    { "GL_ARB_compute_shader",                      o(ARB_compute_shader),                      GL,             2012 },
+   { "GL_ARB_conditional_render_inverted",         o(ARB_conditional_render_inverted),         GL,             2014 },
    { "GL_ARB_copy_buffer",                         o(dummy_true),                              GL,             2008 },
    { "GL_ARB_copy_image",                          o(ARB_copy_image),                          GL,             2012 },
    { "GL_ARB_conservative_depth",                  o(ARB_conservative_depth),                  GL,             2011 },
@@ -101,6 +102,7 @@ static const struct extension extension_table[] = {
    { "GL_ARB_depth_buffer_float",                  o(ARB_depth_buffer_float),                  GL,             2008 },
    { "GL_ARB_depth_clamp",                         o(ARB_depth_clamp),                         GL,             2003 },
    { "GL_ARB_depth_texture",                       o(ARB_depth_texture),                       GLL,            2001 },
+   { "GL_ARB_derivative_control",                  o(ARB_derivative_control),                  GL,             2014 },
    { "GL_ARB_draw_buffers",                        o(dummy_true),                              GL,             2002 },
    { "GL_ARB_draw_buffers_blend",                  o(ARB_draw_buffers_blend),                  GL,             2009 },
    { "GL_ARB_draw_elements_base_vertex",           o(ARB_draw_elements_base_vertex),           GL,             2009 },
@@ -116,7 +118,7 @@ static const struct extension extension_table[] = {
    { "GL_ARB_framebuffer_object",                  o(ARB_framebuffer_object),                  GL,             2005 },
    { "GL_ARB_framebuffer_sRGB",                    o(EXT_framebuffer_sRGB),                    GL,             1998 },
    { "GL_ARB_get_program_binary",                  o(dummy_true),                              GL,             2010 },
-   { "GL_ARB_gpu_shader5",                         o(ARB_gpu_shader5),                         GL,             2010 },
+   { "GL_ARB_gpu_shader5",                         o(ARB_gpu_shader5),                         GLC,            2010 },
    { "GL_ARB_half_float_pixel",                    o(dummy_true),                              GL,             2003 },
    { "GL_ARB_half_float_vertex",                   o(ARB_half_float_vertex),                   GL,             2008 },
    { "GL_ARB_instanced_arrays",                    o(ARB_instanced_arrays),                    GL,             2008 },
@@ -152,11 +154,13 @@ static const struct extension extension_table[] = {
    { "GL_ARB_shadow",                              o(ARB_shadow),                              GLL,            2001 },
    { "GL_ARB_stencil_texturing",                   o(ARB_stencil_texturing),                   GL,             2012 },
    { "GL_ARB_sync",                                o(ARB_sync),                                GL,             2003 },
+   { "GL_ARB_texture_barrier",                     o(NV_texture_barrier),                      GL,             2014 },
    { "GL_ARB_texture_border_clamp",                o(ARB_texture_border_clamp),                GLL,            2000 },
    { "GL_ARB_texture_buffer_object",               o(ARB_texture_buffer_object),               GLC,            2008 },
    { "GL_ARB_texture_buffer_object_rgb32",         o(ARB_texture_buffer_object_rgb32),         GLC,            2009 },
    { "GL_ARB_texture_buffer_range",                o(ARB_texture_buffer_range),                GLC,            2012 },
    { "GL_ARB_texture_compression",                 o(dummy_true),                              GLL,            2000 },
+   { "GL_ARB_texture_compression_bptc",            o(ARB_texture_compression_bptc),            GL,             2010 },
    { "GL_ARB_texture_compression_rgtc",            o(ARB_texture_compression_rgtc),            GL,             2004 },
    { "GL_ARB_texture_cube_map",                    o(ARB_texture_cube_map),                    GLL,            1999 },
    { "GL_ARB_texture_cube_map_array",              o(ARB_texture_cube_map_array),              GL,             2009 },
@@ -449,6 +453,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
    ctx->Extensions.ARB_point_sprite = GL_TRUE;
    ctx->Extensions.ARB_shadow = GL_TRUE;
    ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
+   ctx->Extensions.ARB_texture_compression_bptc = GL_TRUE;
    ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
    ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
    ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
@@ -667,9 +672,9 @@ _mesa_one_time_init_extension_overrides(void)
  * Note: Sets gl_extensions.dummy_true to true.
  */
 void
-_mesa_init_extensions( struct gl_context *ctx )
+_mesa_init_extensions(struct gl_extensions *extensions)
 {
-   GLboolean *base = (GLboolean *) &ctx->Extensions;
+   GLboolean *base = (GLboolean *) extensions;
    GLboolean *sentinel = base + o(extension_sentinel);
    GLboolean *i;
 
@@ -678,8 +683,8 @@ _mesa_init_extensions( struct gl_context *ctx )
       *i = GL_FALSE;
 
    /* Then, selectively turn default extensions on. */
-   ctx->Extensions.dummy_true = GL_TRUE;
-   ctx->Extensions.EXT_texture3D = GL_TRUE;
+   extensions->dummy_true = GL_TRUE;
+   extensions->EXT_texture3D = GL_TRUE;
 }
 
 
diff --git a/mesalib/src/mesa/main/extensions.h b/mesalib/src/mesa/main/extensions.h
index 3a404d2e0..595512a5d 100644
--- a/mesalib/src/mesa/main/extensions.h
+++ b/mesalib/src/mesa/main/extensions.h
@@ -45,7 +45,7 @@ extern void _mesa_enable_sw_extensions(struct gl_context *ctx);
 
 extern void _mesa_one_time_init_extension_overrides(void);
 
-extern void _mesa_init_extensions(struct gl_context *ctx);
+extern void _mesa_init_extensions(struct gl_extensions *extentions);
 
 extern GLubyte *_mesa_make_extension_string(struct gl_context *ctx);
 
diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp
index 8758b5e9d..9bb706cc5 100644
--- a/mesalib/src/mesa/main/ff_fragment_shader.cpp
+++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp
@@ -1252,7 +1252,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key)
    validate_ir_tree(p.shader->ir);
 
    const struct gl_shader_compiler_options *options =
-      &ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
+      &ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
 
    while (do_common_optimization(p.shader->ir, false, false, options,
                                  ctx->Const.NativeIntegers))
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 728cf968b..d5afc3d81 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -1676,7 +1676,7 @@ _mesa_get_fixed_func_vertex_program(struct gl_context *ctx)
          return NULL;
 
       create_new_program( &key, prog,
-                          ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
+                          ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
                           ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps );
 
 #if 0
diff --git a/mesalib/src/mesa/main/format_info.py b/mesalib/src/mesa/main/format_info.py
index 448bd0055..7424fe0cd 100644
--- a/mesalib/src/mesa/main/format_info.py
+++ b/mesalib/src/mesa/main/format_info.py
@@ -62,7 +62,9 @@ def get_gl_base_format(fmat):
 
 def get_gl_data_type(fmat):
    if fmat.is_compressed():
-      if 'SIGNED' in fmat.name or 'SNORM' in fmat.name:
+      if 'FLOAT' in fmat.name:
+         return 'GL_FLOAT'
+      elif 'SIGNED' in fmat.name or 'SNORM' in fmat.name:
          return 'GL_SIGNED_NORMALIZED'
       else:
          return 'GL_UNSIGNED_NORMALIZED'
@@ -125,6 +127,9 @@ def get_channel_bits(fmat, chan_name):
 
          bits = 11 if fmat.name.endswith('11_EAC') else 8
          return bits if fmat.has_channel(chan_name) else 0
+      elif fmat.layout == 'bptc':
+         bits = 16 if fmat.name.endswith('_FLOAT') else 8
+         return bits if fmat.has_channel(chan_name) else 0
       else:
          assert False
    else:
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c
index f03425e41..db22a45c4 100644
--- a/mesalib/src/mesa/main/formats.c
+++ b/mesalib/src/mesa/main/formats.c
@@ -369,6 +369,7 @@ _mesa_get_format_color_encoding(mesa_format format)
    case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
    case MESA_FORMAT_B8G8R8X8_SRGB:
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
       return GL_SRGB;
    default:
       return GL_LINEAR;
@@ -376,6 +377,31 @@ _mesa_get_format_color_encoding(mesa_format format)
 }
 
 
+/**
+ * Return TRUE if format is an ETC2 compressed format specified
+ * by GL_ARB_ES3_compatibility.
+ */
+bool
+_mesa_is_format_etc2(mesa_format format)
+{
+   switch (format) {
+   case MESA_FORMAT_ETC2_RGB8:
+   case MESA_FORMAT_ETC2_SRGB8:
+   case MESA_FORMAT_ETC2_RGBA8_EAC:
+   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
+   case MESA_FORMAT_ETC2_R11_EAC:
+   case MESA_FORMAT_ETC2_RG11_EAC:
+   case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
+   case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
+   case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
+   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
 /**
  * For an sRGB format, return the corresponding linear color space format.
  * For non-sRGB formats, return the format as-is.
@@ -426,6 +452,9 @@ _mesa_get_srgb_format_linear(mesa_format format)
    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
       format = MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
       break;
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+      format = MESA_FORMAT_BPTC_RGBA_UNORM;
+      break;
    case MESA_FORMAT_B8G8R8X8_SRGB:
       format = MESA_FORMAT_B8G8R8X8_UNORM;
       break;
@@ -491,6 +520,12 @@ _mesa_get_uncompressed_format(mesa_format format)
    case MESA_FORMAT_ETC2_RG11_EAC:
    case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
       return MESA_FORMAT_R16G16_UNORM;
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+      return MESA_FORMAT_A8B8G8R8_UNORM;
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+      return MESA_FORMAT_RGB_FLOAT32;
    default:
 #ifdef DEBUG
       assert(!_mesa_is_format_compressed(format));
@@ -968,6 +1003,10 @@ _mesa_format_to_type_and_comps(mesa_format format,
    case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
    case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
       /* XXX generate error instead? */
       *datatype = GL_UNSIGNED_BYTE;
       *comps = 0;
@@ -1524,6 +1563,12 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
    case MESA_FORMAT_RGBA_DXT5:
       return GL_FALSE;
 
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+      return GL_FALSE;
+
    case MESA_FORMAT_RGBA_FLOAT32:
       return format == GL_RGBA && type == GL_FLOAT && !swapBytes;
    case MESA_FORMAT_RGBA_FLOAT16:
diff --git a/mesalib/src/mesa/main/formats.csv b/mesalib/src/mesa/main/formats.csv
index eade6facd..4d542b7c6 100644
--- a/mesalib/src/mesa/main/formats.csv
+++ b/mesalib/src/mesa/main/formats.csv
@@ -280,3 +280,9 @@ MESA_FORMAT_ETC2_SIGNED_R11_EAC           , etc2  , 4, 4, x64 ,     ,     ,
 MESA_FORMAT_ETC2_SIGNED_RG11_EAC          , etc2  , 4, 4, x128,     ,     ,     , xy01, rgb
 MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 , etc2  , 4, 4, x64 ,     ,     ,     , xyzw, rgb
 MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, etc2  , 4, 4, x64 ,     ,     ,     , xyzw, srgb
+
+# BPTC compressed formats
+MESA_FORMAT_BPTC_RGBA_UNORM               , bptc  , 4, 4, x128,     ,     ,     , xyzw, rgb
+MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM         , bptc  , 4, 4, x128,     ,     ,     , xyzw, srgb
+MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT         , bptc  , 4, 4, x128,     ,     ,     , xyz1, rgb
+MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT       , bptc  , 4, 4, x128,     ,     ,     , xyz1, rgb
diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h
index 457c8abf8..d6253bf86 100644
--- a/mesalib/src/mesa/main/formats.h
+++ b/mesalib/src/mesa/main/formats.h
@@ -427,6 +427,12 @@ typedef enum
    MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1,
    MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1,
 
+   /* BPTC compressed formats */
+   MESA_FORMAT_BPTC_RGBA_UNORM,
+   MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM,
+   MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT,
+   MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT,
+
    MESA_FORMAT_COUNT
 } mesa_format;
 
@@ -476,6 +482,9 @@ _mesa_is_format_signed(mesa_format format);
 extern GLboolean
 _mesa_is_format_integer(mesa_format format);
 
+extern bool
+_mesa_is_format_etc2(mesa_format format);
+
 extern GLenum
 _mesa_get_format_color_encoding(mesa_format format);
 
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index 0fb25ba0f..00478f989 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -787,6 +787,10 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_SIGNED_RG11_EAC:
       case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
       case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+      case GL_COMPRESSED_RGBA_BPTC_UNORM:
+      case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+      case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+      case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
       /* generic integer formats */
       case GL_RED_INTEGER_EXT:
       case GL_GREEN_INTEGER_EXT:
@@ -1040,6 +1044,12 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
       return _mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility;
+   case GL_COMPRESSED_RGBA_BPTC_UNORM:
+   case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+   case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+   case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+      return _mesa_is_desktop_gl(ctx) &&
+         ctx->Extensions.ARB_texture_compression_bptc;
    case GL_PALETTE4_RGB8_OES:
    case GL_PALETTE4_RGBA8_OES:
    case GL_PALETTE4_R5_G6_B5_OES:
diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c
index cc109cc52..fdaa68282 100644
--- a/mesalib/src/mesa/main/mipmap.c
+++ b/mesalib/src/mesa/main/mipmap.c
@@ -2038,12 +2038,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 
    components = _mesa_format_num_components(temp_format);
 
-   /* Revisit this if we get compressed formats with >8 bits per component */
-   if (_mesa_get_format_datatype(srcImage->TexFormat)
-       == GL_SIGNED_NORMALIZED) {
+   switch (_mesa_get_format_datatype(srcImage->TexFormat)) {
+   case GL_FLOAT:
+      temp_datatype = GL_FLOAT;
+      break;
+   case GL_SIGNED_NORMALIZED:
+      /* Revisit this if we get compressed formats with >8 bits per component */
       temp_datatype = GL_BYTE;
-   }
-   else {
+      break;
+   default:
       temp_datatype = GL_UNSIGNED_BYTE;
    }
 
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index e141ac658..cb2a4df4f 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -3529,6 +3529,8 @@ struct gl_constants
    GLfloat MaxFragmentInterpolationOffset;
 
    GLboolean FakeSWMSAA;
+
+   struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
 };
 
 
@@ -3551,11 +3553,13 @@ struct gl_extensions
    GLboolean ARB_clear_texture;
    GLboolean ARB_color_buffer_float;
    GLboolean ARB_compute_shader;
+   GLboolean ARB_conditional_render_inverted;
    GLboolean ARB_conservative_depth;
    GLboolean ARB_copy_image;
    GLboolean ARB_depth_buffer_float;
    GLboolean ARB_depth_clamp;
    GLboolean ARB_depth_texture;
+   GLboolean ARB_derivative_control;
    GLboolean ARB_draw_buffers_blend;
    GLboolean ARB_draw_elements_base_vertex;
    GLboolean ARB_draw_indirect;
@@ -3593,6 +3597,7 @@ struct gl_extensions
    GLboolean ARB_texture_buffer_object;
    GLboolean ARB_texture_buffer_object_rgb32;
    GLboolean ARB_texture_buffer_range;
+   GLboolean ARB_texture_compression_bptc;
    GLboolean ARB_texture_compression_rgtc;
    GLboolean ARB_texture_cube_map;
    GLboolean ARB_texture_cube_map_array;
@@ -4172,8 +4177,6 @@ struct gl_context
     */
    struct gl_pipeline_object *_Shader;
 
-   struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
-
    struct gl_query_state Query;  /**< occlusion, timer queries */
 
    struct gl_transform_feedback_state TransformFeedback;
diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c
index 05f6583a4..fc815337b 100644
--- a/mesalib/src/mesa/main/pixelstore.c
+++ b/mesalib/src/mesa/main/pixelstore.c
@@ -284,3 +284,45 @@ _mesa_init_pixelstore( struct gl_context *ctx )
    _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
                                  ctx->Shared->NullBufferObj);
 }
+
+
+/**
+ * Check if the given compressed pixel storage parameters are legal.
+ * Record a GL error if illegal.
+ * \return  true if legal, false if illegal
+ */
+bool
+_mesa_compressed_pixel_storage_error_check(
+   struct gl_context *ctx,
+   GLint dimensions,
+   const struct gl_pixelstore_attrib *packing,
+   const char *caller)
+{
+   if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize)
+      return true;
+
+   if (packing->CompressedBlockWidth &&
+       packing->SkipPixels % packing->CompressedBlockWidth) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(skip-pixels %% block-width)", caller);
+      return false;
+   }
+
+   if (dimensions > 1 &&
+       packing->CompressedBlockHeight &&
+       packing->SkipRows % packing->CompressedBlockHeight) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(skip-rows %% block-height)", caller);
+      return false;
+   }
+
+   if (dimensions > 2 &&
+       packing->CompressedBlockDepth &&
+       packing->SkipImages % packing->CompressedBlockDepth) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(skip-images %% block-depth)", caller);
+      return false;
+   }
+
+   return true;
+}
diff --git a/mesalib/src/mesa/main/pixelstore.h b/mesalib/src/mesa/main/pixelstore.h
index 1b5347daf..68384548a 100644
--- a/mesalib/src/mesa/main/pixelstore.h
+++ b/mesalib/src/mesa/main/pixelstore.h
@@ -49,4 +49,12 @@ extern void
 _mesa_init_pixelstore( struct gl_context *ctx );
 
 
+extern bool
+_mesa_compressed_pixel_storage_error_check(
+   struct gl_context *ctx,
+   GLint dimensions,
+   const struct gl_pixelstore_attrib *packing,
+   const char *caller);
+
+
 #endif
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index b4a5e7050..620cab3cc 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -119,7 +119,7 @@ _mesa_init_shader_state(struct gl_context *ctx)
    options.DefaultPragmas.Optimize = GL_TRUE;
 
    for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
-      memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
+      memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options));
 
    ctx->Shader.Flags = _mesa_get_shader_flags();
 
@@ -826,7 +826,7 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
    if (!sh)
       return;
 
-   options = &ctx->ShaderCompilerOptions[sh->Stage];
+   options = &ctx->Const.ShaderCompilerOptions[sh->Stage];
 
    /* set default pragma state for shader */
    sh->Pragmas = options->DefaultPragmas;
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
index 0189dd296..7ef932ff0 100644
--- a/mesalib/src/mesa/main/shared.c
+++ b/mesalib/src/mesa/main/shared.c
@@ -113,7 +113,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
    assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
 
    /* Mutex and timestamp for texobj state validation */
-   mtx_init(&shared->TexMutex, mtx_plain);
+   mtx_init(&shared->TexMutex, mtx_recursive);
    shared->TextureStateStamp = 0;
 
    shared->FrameBuffers = _mesa_NewHashTable();
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
index 9dbfe9ffe..b4efeee3b 100644
--- a/mesalib/src/mesa/main/texcompress.c
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -42,6 +42,7 @@
 #include "texcompress_rgtc.h"
 #include "texcompress_s3tc.h"
 #include "texcompress_etc.h"
+#include "texcompress_bptc.h"
 
 
 /**
@@ -92,6 +93,8 @@ _mesa_gl_compressed_format_base_format(GLenum format)
 
    case GL_COMPRESSED_RGB:
    case GL_COMPRESSED_SRGB:
+   case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+   case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case GL_COMPRESSED_RGB_FXT1_3DFX:
    case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
@@ -104,8 +107,6 @@ _mesa_gl_compressed_format_base_format(GLenum format)
    case GL_COMPRESSED_SRGB_ALPHA:
    case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
    case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
-   case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
-   case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
@@ -235,6 +236,12 @@ _mesa_gl_compressed_format_base_format(GLenum format)
  * GL_EXT_texture_compression_latc.  At the very least, Catalyst 11.6 does not
  * expose the 3dc formats through this mechanism.
  *
+ * The spec for GL_ARB_texture_compression_bptc doesn't mention whether it
+ * should be included in GL_COMPRESSED_TEXTURE_FORMATS. However as it takes a
+ * very long time to compress the textures in this format it's probably not
+ * very useful as a general format where the GL will have to compress it on
+ * the fly.
+ *
  * \param ctx  the GL context
  * \param formats  the resulting format list (may be NULL).
  *
@@ -434,6 +441,15 @@ _mesa_glenum_to_compressed_format(GLenum format)
    case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
       return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1;
 
+   case GL_COMPRESSED_RGBA_BPTC_UNORM:
+      return MESA_FORMAT_BPTC_RGBA_UNORM;
+   case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+      return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
+   case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+      return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT;
+   case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+      return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT;
+
    default:
       return MESA_FORMAT_NONE;
    }
@@ -515,6 +531,15 @@ _mesa_compressed_format_to_glenum(struct gl_context *ctx, mesa_format mesaFormat
    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
       return GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
 
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+      return GL_COMPRESSED_RGBA_BPTC_UNORM;
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+      return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+      return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+      return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+
    default:
       _mesa_problem(ctx, "Unexpected mesa texture format in"
                     " _mesa_compressed_format_to_glenum()");
@@ -586,6 +611,11 @@ _mesa_get_compressed_fetch_func(mesa_format format)
       return _mesa_get_compressed_rgtc_func(format);
    case MESA_FORMAT_ETC1_RGB8:
       return _mesa_get_etc_fetch_func(format);
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+      return _mesa_get_bptc_fetch_func(format);
    default:
       return NULL;
    }
diff --git a/mesalib/src/mesa/main/texcompress_bptc.c b/mesalib/src/mesa/main/texcompress_bptc.c
new file mode 100644
index 000000000..9204f123e
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_bptc.c
@@ -0,0 +1,1649 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * 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 without limitation
+ * the rights to use, copy, modify, merge, publish, 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.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE 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.
+ */
+
+/**
+ * \file texcompress_bptc.c
+ * GL_ARB_texture_compression_bptc support.
+ */
+
+#include <stdbool.h>
+#include "texcompress.h"
+#include "texcompress_bptc.h"
+#include "util/format_srgb.h"
+#include "texstore.h"
+#include "macros.h"
+#include "image.h"
+
+#define BLOCK_SIZE 4
+#define N_PARTITIONS 64
+#define BLOCK_BYTES 16
+
+struct bptc_unorm_mode {
+   int n_subsets;
+   int n_partition_bits;
+   bool has_rotation_bits;
+   bool has_index_selection_bit;
+   int n_color_bits;
+   int n_alpha_bits;
+   bool has_endpoint_pbits;
+   bool has_shared_pbits;
+   int n_index_bits;
+   int n_secondary_index_bits;
+};
+
+struct bptc_float_bitfield {
+   int8_t endpoint;
+   uint8_t component;
+   uint8_t offset;
+   uint8_t n_bits;
+   bool reverse;
+};
+
+struct bptc_float_mode {
+   bool reserved;
+   bool transformed_endpoints;
+   int n_partition_bits;
+   int n_endpoint_bits;
+   int n_index_bits;
+   int n_delta_bits[3];
+   struct bptc_float_bitfield bitfields[24];
+};
+
+struct bit_writer {
+   uint8_t buf;
+   int pos;
+   uint8_t *dst;
+};
+
+static const struct bptc_unorm_mode
+bptc_unorm_modes[] = {
+   /* 0 */ { 3, 4, false, false, 4, 0, true,  false, 3, 0 },
+   /* 1 */ { 2, 6, false, false, 6, 0, false, true,  3, 0 },
+   /* 2 */ { 3, 6, false, false, 5, 0, false, false, 2, 0 },
+   /* 3 */ { 2, 6, false, false, 7, 0, true,  false, 2, 0 },
+   /* 4 */ { 1, 0, true,  true,  5, 6, false, false, 2, 3 },
+   /* 5 */ { 1, 0, true,  false, 7, 8, false, false, 2, 2 },
+   /* 6 */ { 1, 0, false, false, 7, 7, true,  false, 4, 0 },
+   /* 7 */ { 2, 6, false, false, 5, 5, true,  false, 2, 0 }
+};
+
+static const struct bptc_float_mode
+bptc_float_modes[] = {
+   /* 00 */
+   { false, true, 5, 10, 3, { 5, 5, 5 },
+     { { 2, 1, 4, 1, false }, { 2, 2, 4, 1, false }, { 3, 2, 4, 1, false },
+       { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+       { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+       { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
+       { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
+       { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 01 */
+   { false, true, 5, 7, 3, { 6, 6, 6 },
+     { { 2, 1, 5, 1, false }, { 3, 1, 4, 1, false }, { 3, 1, 5, 1, false },
+       { 0, 0, 0, 7, false }, { 3, 2, 0, 1, false }, { 3, 2, 1, 1, false },
+       { 2, 2, 4, 1, false }, { 0, 1, 0, 7, false }, { 2, 2, 5, 1, false },
+       { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, { 0, 2, 0, 7, false },
+       { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
+       { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
+       { 2, 0, 0, 6, false },
+       { 3, 0, 0, 6, false },
+       { -1 } }
+   },
+   /* 00010 */
+   { false, true, 5, 11, 3, { 5, 4, 4 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 5, false }, { 0, 0, 10, 1, false }, { 2, 1, 0, 4, false },
+       { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, { 3, 2, 0, 1, false },
+       { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
+       { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+       { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 00011 */
+   { false, false, 0, 10, 4, { 10, 10, 10 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 10, false }, { 1, 1, 0, 10, false }, { 1, 2, 0, 10, false },
+       { -1 } }
+   },
+   /* 00110 */
+   { false, true, 5, 11, 3, { 4, 5, 4 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 3, 1, 4, 1, false },
+       { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, { 0, 1, 10, 1, false },
+       { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
+       { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
+       { 3, 2, 0, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
+       { 2, 1, 4, 1, false }, { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 00111 */
+   { false, true, 0, 11, 4, { 9, 9, 9 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 9, false }, { 0, 0, 10, 1, false }, { 1, 1, 0, 9, false },
+       { 0, 1, 10, 1, false }, { 1, 2, 0, 9, false }, { 0, 2, 10, 1, false },
+       { -1 } }
+   },
+   /* 01010 */
+   { false, true, 5, 11, 3, { 4, 4, 5 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 2, 2, 4, 1, false },
+       { 2, 1, 0, 4, false }, { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false },
+       { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+       { 0, 2, 10, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
+       { 3, 2, 1, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
+       { 3, 2, 4, 1, false }, { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 01011 */
+   { false, true, 0, 12, 4, { 8, 8, 8 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 8, false }, { 0, 0, 10, 2, true }, { 1, 1, 0, 8, false },
+       { 0, 1, 10, 2, true }, { 1, 2, 0, 8, false }, { 0, 2, 10, 2, true },
+       { -1 } }
+   },
+   /* 01110 */
+   { false, true, 5, 9, 3, { 5, 5, 5 },
+     { { 0, 0, 0, 9, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 9, false },
+       { 2, 1, 4, 1, false }, { 0, 2, 0, 9, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+       { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+       { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
+       { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
+       { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 01111 */
+   { false, true, 0, 16, 4, { 4, 4, 4 },
+     { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+       { 1, 0, 0, 4, false }, { 0, 0, 10, 6, true }, { 1, 1, 0, 4, false },
+       { 0, 1, 10, 6, true }, { 1, 2, 0, 4, false }, { 0, 2, 10, 6, true },
+       { -1 } }
+   },
+   /* 10010 */
+   { false, true, 5, 8, 3, { 6, 5, 5 },
+     { { 0, 0, 0, 8, false }, { 3, 1, 4, 1, false }, { 2, 2, 4, 1, false },
+       { 0, 1, 0, 8, false }, { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false },
+       { 0, 2, 0, 8, false }, { 3, 2, 3, 1, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false },
+       { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+       { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 6, false },
+       { 3, 0, 0, 6, false },
+       { -1 } }
+   },
+   /* 10011 */
+   { true /* reserved */ },
+   /* 10110 */
+   { false, true, 5, 8, 3, { 5, 6, 5 },
+     { { 0, 0, 0, 8, false }, { 3, 2, 0, 1, false }, { 2, 2, 4, 1, false },
+       { 0, 1, 0, 8, false }, { 2, 1, 5, 1, false }, { 2, 1, 4, 1, false },
+       { 0, 2, 0, 8, false }, { 3, 1, 5, 1, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+       { 1, 1, 0, 6, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+       { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+       { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 10111 */
+   { true /* reserved */ },
+   /* 11010 */
+   { false, true, 5, 8, 3, { 5, 5, 6 },
+     { { 0, 0, 0, 8, false }, { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false },
+       { 0, 1, 0, 8, false }, { 2, 2, 5, 1, false }, { 2, 1, 4, 1, false },
+       { 0, 2, 0, 8, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+       { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+       { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+       { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+       { -1 } }
+   },
+   /* 11011 */
+   { true /* reserved */ },
+   /* 11110 */
+   { false, false, 5, 6, 3, { 6, 6, 6 },
+     { { 0, 0, 0, 6, false }, { 3, 1, 4, 1, false }, { 3, 2, 0, 1, false },
+       { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 6, false },
+       { 2, 1, 5, 1, false }, { 2, 2, 5, 1, false }, { 3, 2, 2, 1, false },
+       { 2, 1, 4, 1, false }, { 0, 2, 0, 6, false }, { 3, 1, 5, 1, false },
+       { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+       { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
+       { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
+       { 2, 0, 0, 6, false }, { 3, 0, 0, 6, false },
+       { -1 } }
+   },
+   /* 11111 */
+   { true /* reserved */ },
+};
+
+/* This partition table is used when the mode has two subsets. Each
+ * partition is represented by a 32-bit value which gives 2 bits per texel
+ * within the block. The value of the two bits represents which subset to use
+ * (0 or 1).
+ */
+static const uint32_t
+partition_table1[N_PARTITIONS] = {
+   0x50505050U, 0x40404040U, 0x54545454U, 0x54505040U,
+   0x50404000U, 0x55545450U, 0x55545040U, 0x54504000U,
+   0x50400000U, 0x55555450U, 0x55544000U, 0x54400000U,
+   0x55555440U, 0x55550000U, 0x55555500U, 0x55000000U,
+   0x55150100U, 0x00004054U, 0x15010000U, 0x00405054U,
+   0x00004050U, 0x15050100U, 0x05010000U, 0x40505054U,
+   0x00404050U, 0x05010100U, 0x14141414U, 0x05141450U,
+   0x01155440U, 0x00555500U, 0x15014054U, 0x05414150U,
+   0x44444444U, 0x55005500U, 0x11441144U, 0x05055050U,
+   0x05500550U, 0x11114444U, 0x41144114U, 0x44111144U,
+   0x15055054U, 0x01055040U, 0x05041050U, 0x05455150U,
+   0x14414114U, 0x50050550U, 0x41411414U, 0x00141400U,
+   0x00041504U, 0x00105410U, 0x10541000U, 0x04150400U,
+   0x50410514U, 0x41051450U, 0x05415014U, 0x14054150U,
+   0x41050514U, 0x41505014U, 0x40011554U, 0x54150140U,
+   0x50505500U, 0x00555050U, 0x15151010U, 0x54540404U,
+};
+
+/* This partition table is used when the mode has three subsets. In this case
+ * the values can be 0, 1 or 2.
+ */
+static const uint32_t
+partition_table2[N_PARTITIONS] = {
+   0xaa685050U, 0x6a5a5040U, 0x5a5a4200U, 0x5450a0a8U,
+   0xa5a50000U, 0xa0a05050U, 0x5555a0a0U, 0x5a5a5050U,
+   0xaa550000U, 0xaa555500U, 0xaaaa5500U, 0x90909090U,
+   0x94949494U, 0xa4a4a4a4U, 0xa9a59450U, 0x2a0a4250U,
+   0xa5945040U, 0x0a425054U, 0xa5a5a500U, 0x55a0a0a0U,
+   0xa8a85454U, 0x6a6a4040U, 0xa4a45000U, 0x1a1a0500U,
+   0x0050a4a4U, 0xaaa59090U, 0x14696914U, 0x69691400U,
+   0xa08585a0U, 0xaa821414U, 0x50a4a450U, 0x6a5a0200U,
+   0xa9a58000U, 0x5090a0a8U, 0xa8a09050U, 0x24242424U,
+   0x00aa5500U, 0x24924924U, 0x24499224U, 0x50a50a50U,
+   0x500aa550U, 0xaaaa4444U, 0x66660000U, 0xa5a0a5a0U,
+   0x50a050a0U, 0x69286928U, 0x44aaaa44U, 0x66666600U,
+   0xaa444444U, 0x54a854a8U, 0x95809580U, 0x96969600U,
+   0xa85454a8U, 0x80959580U, 0xaa141414U, 0x96960000U,
+   0xaaaa1414U, 0xa05050a0U, 0xa0a5a5a0U, 0x96000000U,
+   0x40804080U, 0xa9a8a9a8U, 0xaaaaaa44U, 0x2a4a5254U
+};
+
+static const uint8_t
+anchor_indices[][N_PARTITIONS] = {
+   /* Anchor index values for the second subset of two-subset partitioning */
+   {
+      0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
+      0xf,0x2,0x8,0x2,0x2,0x8,0x8,0xf,0x2,0x8,0x2,0x2,0x8,0x8,0x2,0x2,
+      0xf,0xf,0x6,0x8,0x2,0x8,0xf,0xf,0x2,0x8,0x2,0x2,0x2,0xf,0xf,0x6,
+      0x6,0x2,0x6,0x8,0xf,0xf,0x2,0x2,0xf,0xf,0xf,0xf,0xf,0x2,0x2,0xf
+   },
+
+   /* Anchor index values for the second subset of three-subset partitioning */
+   {
+      0x3,0x3,0xf,0xf,0x8,0x3,0xf,0xf,0x8,0x8,0x6,0x6,0x6,0x5,0x3,0x3,
+      0x3,0x3,0x8,0xf,0x3,0x3,0x6,0xa,0x5,0x8,0x8,0x6,0x8,0x5,0xf,0xf,
+      0x8,0xf,0x3,0x5,0x6,0xa,0x8,0xf,0xf,0x3,0xf,0x5,0xf,0xf,0xf,0xf,
+      0x3,0xf,0x5,0x5,0x5,0x8,0x5,0xa,0x5,0xa,0x8,0xd,0xf,0xc,0x3,0x3
+   },
+
+   /* Anchor index values for the third subset of three-subset
+    * partitioning
+    */
+   {
+      0xf,0x8,0x8,0x3,0xf,0xf,0x3,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,
+      0xf,0x8,0xf,0x3,0xf,0x8,0xf,0x8,0x3,0xf,0x6,0xa,0xf,0xf,0xa,0x8,
+      0xf,0x3,0xf,0xa,0xa,0x8,0x9,0xa,0x6,0xf,0x8,0xf,0x3,0x6,0x6,0x8,
+      0xf,0x3,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3,0xf,0xf,0x8
+   }
+};
+
+static int
+extract_bits(const uint8_t *block,
+             int offset,
+             int n_bits)
+{
+   int byte_index = offset / 8;
+   int bit_index = offset % 8;
+   int n_bits_in_byte = MIN2(n_bits, 8 - bit_index);
+   int result = 0;
+   int bit = 0;
+
+   while (true) {
+      result |= ((block[byte_index] >> bit_index) &
+                 ((1 << n_bits_in_byte) - 1)) << bit;
+
+      n_bits -= n_bits_in_byte;
+
+      if (n_bits <= 0)
+         return result;
+
+      bit += n_bits_in_byte;
+      byte_index++;
+      bit_index = 0;
+      n_bits_in_byte = MIN2(n_bits, 8);
+   }
+}
+
+static uint8_t
+expand_component(uint8_t byte,
+                 int n_bits)
+{
+   /* Expands a n-bit quantity into a byte by copying the most-significant
+    * bits into the unused least-significant bits.
+    */
+   return byte << (8 - n_bits) | (byte >> (2 * n_bits - 8));
+}
+
+static int
+extract_unorm_endpoints(const struct bptc_unorm_mode *mode,
+                        const uint8_t *block,
+                        int bit_offset,
+                        uint8_t endpoints[][4])
+{
+   int component;
+   int subset;
+   int endpoint;
+   int pbit;
+   int n_components;
+
+   /* Extract each color component */
+   for (component = 0; component < 3; component++) {
+      for (subset = 0; subset < mode->n_subsets; subset++) {
+         for (endpoint = 0; endpoint < 2; endpoint++) {
+            endpoints[subset * 2 + endpoint][component] =
+               extract_bits(block, bit_offset, mode->n_color_bits);
+            bit_offset += mode->n_color_bits;
+         }
+      }
+   }
+
+   /* Extract the alpha values */
+   if (mode->n_alpha_bits > 0) {
+      for (subset = 0; subset < mode->n_subsets; subset++) {
+         for (endpoint = 0; endpoint < 2; endpoint++) {
+            endpoints[subset * 2 + endpoint][3] =
+               extract_bits(block, bit_offset, mode->n_alpha_bits);
+            bit_offset += mode->n_alpha_bits;
+         }
+      }
+
+      n_components = 4;
+   } else {
+      for (subset = 0; subset < mode->n_subsets; subset++)
+         for (endpoint = 0; endpoint < 2; endpoint++)
+            endpoints[subset * 2 + endpoint][3] = 255;
+
+      n_components = 3;
+   }
+
+   /* Add in the p-bits */
+   if (mode->has_endpoint_pbits) {
+      for (subset = 0; subset < mode->n_subsets; subset++) {
+         for (endpoint = 0; endpoint < 2; endpoint++) {
+            pbit = extract_bits(block, bit_offset, 1);
+            bit_offset += 1;
+
+            for (component = 0; component < n_components; component++) {
+               endpoints[subset * 2 + endpoint][component] <<= 1;
+               endpoints[subset * 2 + endpoint][component] |= pbit;
+            }
+         }
+      }
+   } else if (mode->has_shared_pbits) {
+      for (subset = 0; subset < mode->n_subsets; subset++) {
+         pbit = extract_bits(block, bit_offset, 1);
+         bit_offset += 1;
+
+         for (endpoint = 0; endpoint < 2; endpoint++) {
+            for (component = 0; component < n_components; component++) {
+               endpoints[subset * 2 + endpoint][component] <<= 1;
+               endpoints[subset * 2 + endpoint][component] |= pbit;
+            }
+         }
+      }
+   }
+
+   /* Expand the n-bit values to a byte */
+   for (subset = 0; subset < mode->n_subsets; subset++) {
+      for (endpoint = 0; endpoint < 2; endpoint++) {
+         for (component = 0; component < 3; component++) {
+            endpoints[subset * 2 + endpoint][component] =
+               expand_component(endpoints[subset * 2 + endpoint][component],
+                                mode->n_color_bits +
+                                mode->has_endpoint_pbits +
+                                mode->has_shared_pbits);
+         }
+
+         if (mode->n_alpha_bits > 0) {
+            endpoints[subset * 2 + endpoint][3] =
+               expand_component(endpoints[subset * 2 + endpoint][3],
+                                mode->n_alpha_bits +
+                                mode->has_endpoint_pbits +
+                                mode->has_shared_pbits);
+         }
+      }
+   }
+
+   return bit_offset;
+}
+
+static bool
+is_anchor(int n_subsets,
+          int partition_num,
+          int texel)
+{
+   if (texel == 0)
+      return true;
+
+   switch (n_subsets) {
+   case 1:
+      return false;
+   case 2:
+      return anchor_indices[0][partition_num] == texel;
+   case 3:
+      return (anchor_indices[1][partition_num] == texel ||
+              anchor_indices[2][partition_num] == texel);
+   default:
+      assert(false);
+      return false;
+   }
+}
+
+static int
+count_anchors_before_texel(int n_subsets,
+                           int partition_num,
+                           int texel)
+{
+   int count = 1;
+
+   if (texel == 0)
+      return 0;
+
+   switch (n_subsets) {
+   case 1:
+      break;
+   case 2:
+      if (texel > anchor_indices[0][partition_num])
+         count++;
+      break;
+   case 3:
+      if (texel > anchor_indices[1][partition_num])
+         count++;
+      if (texel > anchor_indices[2][partition_num])
+         count++;
+      break;
+   default:
+      assert(false);
+      return 0;
+   }
+
+   return count;
+}
+
+static int32_t
+interpolate(int32_t a, int32_t b,
+            int index,
+            int index_bits)
+{
+   static const uint8_t weights2[] = { 0, 21, 43, 64 };
+   static const uint8_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
+   static const uint8_t weights4[] =
+      { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
+   static const uint8_t *weights[] = {
+      NULL, NULL, weights2, weights3, weights4
+   };
+   int weight;
+
+   weight = weights[index_bits][index];
+
+   return ((64 - weight) * a + weight * b + 32) >> 6;
+}
+
+static void
+apply_rotation(int rotation,
+               uint8_t *result)
+{
+   uint8_t t;
+
+   if (rotation == 0)
+      return;
+
+   rotation--;
+
+   t = result[rotation];
+   result[rotation] = result[3];
+   result[3] = t;
+}
+
+static void
+fetch_rgba_unorm_from_block(const uint8_t *block,
+                            uint8_t *result,
+                            int texel)
+{
+   int mode_num = ffs(block[0]);
+   const struct bptc_unorm_mode *mode;
+   int bit_offset, secondary_bit_offset;
+   int partition_num;
+   int subset_num;
+   int rotation;
+   int index_selection;
+   int index_bits;
+   int indices[2];
+   int index;
+   int anchors_before_texel;
+   bool anchor;
+   uint8_t endpoints[3 * 2][4];
+   uint32_t subsets;
+   int component;
+
+   if (mode_num == 0) {
+      /* According to the spec this mode is reserved and shouldn't be used. */
+      memset(result, 0, 3);
+      result[3] = 0xff;
+      return;
+   }
+
+   mode = bptc_unorm_modes + mode_num - 1;
+   bit_offset = mode_num;
+
+   partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
+   bit_offset += mode->n_partition_bits;
+
+   switch (mode->n_subsets) {
+   case 1:
+      subsets = 0;
+      break;
+   case 2:
+      subsets = partition_table1[partition_num];
+      break;
+   case 3:
+      subsets = partition_table2[partition_num];
+      break;
+   default:
+      assert(false);
+      return;
+   }
+
+   if (mode->has_rotation_bits) {
+      rotation = extract_bits(block, bit_offset, 2);
+      bit_offset += 2;
+   } else {
+      rotation = 0;
+   }
+
+   if (mode->has_index_selection_bit) {
+      index_selection = extract_bits(block, bit_offset, 1);
+      bit_offset++;
+   } else {
+      index_selection = 0;
+   }
+
+   bit_offset = extract_unorm_endpoints(mode, block, bit_offset, endpoints);
+
+   anchors_before_texel = count_anchors_before_texel(mode->n_subsets,
+                                                     partition_num, texel);
+
+   /* Calculate the offset to the secondary index */
+   secondary_bit_offset = (bit_offset +
+                           BLOCK_SIZE * BLOCK_SIZE * mode->n_index_bits -
+                           mode->n_subsets +
+                           mode->n_secondary_index_bits * texel -
+                           anchors_before_texel);
+
+   /* Calculate the offset to the primary index for this texel */
+   bit_offset += mode->n_index_bits * texel - anchors_before_texel;
+
+   subset_num = (subsets >> (texel * 2)) & 3;
+
+   anchor = is_anchor(mode->n_subsets, partition_num, texel);
+
+   index_bits = mode->n_index_bits;
+   if (anchor)
+      index_bits--;
+   indices[0] = extract_bits(block, bit_offset, index_bits);
+
+   if (mode->n_secondary_index_bits) {
+      index_bits = mode->n_secondary_index_bits;
+      if (anchor)
+         index_bits--;
+      indices[1] = extract_bits(block, secondary_bit_offset, index_bits);
+   }
+
+   index = indices[index_selection];
+   index_bits = (index_selection ?
+                 mode->n_secondary_index_bits :
+                 mode->n_index_bits);
+
+   for (component = 0; component < 3; component++)
+      result[component] = interpolate(endpoints[subset_num * 2][component],
+                                      endpoints[subset_num * 2 + 1][component],
+                                      index,
+                                      index_bits);
+
+   /* Alpha uses the opposite index from the color components */
+   if (mode->n_secondary_index_bits && !index_selection) {
+      index = indices[1];
+      index_bits = mode->n_secondary_index_bits;
+   } else {
+      index = indices[0];
+      index_bits = mode->n_index_bits;
+   }
+
+   result[3] = interpolate(endpoints[subset_num * 2][3],
+                           endpoints[subset_num * 2 + 1][3],
+                           index,
+                           index_bits);
+
+   apply_rotation(rotation, result);
+}
+
+static void
+fetch_bptc_rgba_unorm_bytes(const GLubyte *map,
+                            GLint rowStride, GLint i, GLint j,
+                            GLubyte *texel)
+{
+   const GLubyte *block;
+
+   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
+
+   fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
+}
+
+static void
+fetch_bptc_rgba_unorm(const GLubyte *map,
+                      GLint rowStride, GLint i, GLint j,
+                      GLfloat *texel)
+{
+   GLubyte texel_bytes[4];
+
+   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
+
+   texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
+   texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
+   texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
+   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
+}
+
+static void
+fetch_bptc_srgb_alpha_unorm(const GLubyte *map,
+                            GLint rowStride, GLint i, GLint j,
+                            GLfloat *texel)
+{
+   GLubyte texel_bytes[4];
+
+   fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
+
+   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
+   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
+   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
+   texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
+}
+
+static int32_t
+sign_extend(int32_t value,
+            int n_bits)
+{
+   if ((value & (1 << (n_bits - 1)))) {
+      value |= (~(int32_t) 0) << n_bits;
+   }
+
+   return value;
+}
+
+static int
+signed_unquantize(int value, int n_endpoint_bits)
+{
+   bool sign;
+
+   if (n_endpoint_bits >= 16)
+      return value;
+
+   if (value == 0)
+      return 0;
+
+   sign = false;
+
+   if (value < 0) {
+      sign = true;
+      value = -value;
+   }
+
+   if (value >= (1 << (n_endpoint_bits - 1)) - 1)
+      value = 0x7fff;
+   else
+      value = ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
+
+   if (sign)
+      value = -value;
+
+   return value;
+}
+
+static int
+unsigned_unquantize(int value, int n_endpoint_bits)
+{
+   if (n_endpoint_bits >= 15)
+      return value;
+
+   if (value == 0)
+      return 0;
+
+   if (value == (1 << n_endpoint_bits) - 1)
+      return 0xffff;
+
+   return ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
+}
+
+static int
+extract_float_endpoints(const struct bptc_float_mode *mode,
+                        const uint8_t *block,
+                        int bit_offset,
+                        int32_t endpoints[][3],
+                        bool is_signed)
+{
+   const struct bptc_float_bitfield *bitfield;
+   int endpoint, component;
+   int n_endpoints;
+   int value;
+   int i;
+
+   if (mode->n_partition_bits)
+      n_endpoints = 4;
+   else
+      n_endpoints = 2;
+
+   memset(endpoints, 0, sizeof endpoints[0][0] * n_endpoints * 3);
+
+   for (bitfield = mode->bitfields; bitfield->endpoint != -1; bitfield++) {
+      value = extract_bits(block, bit_offset, bitfield->n_bits);
+      bit_offset += bitfield->n_bits;
+
+      if (bitfield->reverse) {
+         for (i = 0; i < bitfield->n_bits; i++) {
+            if (value & (1 << i))
+               endpoints[bitfield->endpoint][bitfield->component] |=
+                  1 << ((bitfield->n_bits - 1 - i) + bitfield->offset);
+         }
+      } else {
+         endpoints[bitfield->endpoint][bitfield->component] |=
+            value << bitfield->offset;
+      }
+   }
+
+   if (mode->transformed_endpoints) {
+      /* The endpoints are specified as signed offsets from e0 */
+      for (endpoint = 1; endpoint < n_endpoints; endpoint++) {
+         for (component = 0; component < 3; component++) {
+            value = sign_extend(endpoints[endpoint][component],
+                                mode->n_delta_bits[component]);
+            endpoints[endpoint][component] =
+               ((endpoints[0][component] + value) &
+                ((1 << mode->n_endpoint_bits) - 1));
+         }
+      }
+   }
+
+   if (is_signed) {
+      for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
+         for (component = 0; component < 3; component++) {
+            value = sign_extend(endpoints[endpoint][component],
+                                mode->n_endpoint_bits);
+            endpoints[endpoint][component] =
+               signed_unquantize(value, mode->n_endpoint_bits);
+         }
+      }
+   } else {
+      for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
+         for (component = 0; component < 3; component++) {
+            endpoints[endpoint][component] =
+               unsigned_unquantize(endpoints[endpoint][component],
+                                   mode->n_endpoint_bits);
+         }
+      }
+   }
+
+   return bit_offset;
+}
+
+static int32_t
+finish_unsigned_unquantize(int32_t value)
+{
+   return value * 31 / 64;
+}
+
+static int32_t
+finish_signed_unquantize(int32_t value)
+{
+   if (value < 0)
+      return (-value * 31 / 32) | 0x8000;
+   else
+      return value * 31 / 32;
+}
+
+static void
+fetch_rgb_float_from_block(const uint8_t *block,
+                           float *result,
+                           int texel,
+                           bool is_signed)
+{
+   int mode_num;
+   const struct bptc_float_mode *mode;
+   int bit_offset;
+   int partition_num;
+   int subset_num;
+   int index_bits;
+   int index;
+   int anchors_before_texel;
+   int32_t endpoints[2 * 2][3];
+   uint32_t subsets;
+   int n_subsets;
+   int component;
+   int32_t value;
+
+   if (block[0] & 0x2) {
+      mode_num = (((block[0] >> 1) & 0xe) | (block[0] & 1)) + 2;
+      bit_offset = 5;
+   } else {
+      mode_num = block[0] & 3;
+      bit_offset = 2;
+   }
+
+   mode = bptc_float_modes + mode_num;
+
+   if (mode->reserved) {
+      memset(result, 0, sizeof result[0] * 3);
+      result[3] = 1.0f;
+      return;
+   }
+
+   bit_offset = extract_float_endpoints(mode, block, bit_offset,
+                                        endpoints, is_signed);
+
+   if (mode->n_partition_bits) {
+      partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
+      bit_offset += mode->n_partition_bits;
+
+      subsets = partition_table1[partition_num];
+      n_subsets = 2;
+   } else {
+      partition_num = 0;
+      subsets = 0;
+      n_subsets = 1;
+   }
+
+   anchors_before_texel =
+      count_anchors_before_texel(n_subsets, partition_num, texel);
+
+   /* Calculate the offset to the primary index for this texel */
+   bit_offset += mode->n_index_bits * texel - anchors_before_texel;
+
+   subset_num = (subsets >> (texel * 2)) & 3;
+
+   index_bits = mode->n_index_bits;
+   if (is_anchor(n_subsets, partition_num, texel))
+      index_bits--;
+   index = extract_bits(block, bit_offset, index_bits);
+
+   for (component = 0; component < 3; component++) {
+      value = interpolate(endpoints[subset_num * 2][component],
+                          endpoints[subset_num * 2 + 1][component],
+                          index,
+                          mode->n_index_bits);
+
+      if (is_signed)
+         value = finish_signed_unquantize(value);
+      else
+         value = finish_unsigned_unquantize(value);
+
+      result[component] = _mesa_half_to_float(value);
+   }
+
+   result[3] = 1.0f;
+}
+
+static void
+fetch_bptc_rgb_float(const GLubyte *map,
+                     GLint rowStride, GLint i, GLint j,
+                     GLfloat *texel,
+                     bool is_signed)
+{
+   const GLubyte *block;
+
+   block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
+
+   fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
+}
+
+static void
+fetch_bptc_rgb_signed_float(const GLubyte *map,
+                            GLint rowStride, GLint i, GLint j,
+                            GLfloat *texel)
+{
+   fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
+}
+
+static void
+fetch_bptc_rgb_unsigned_float(const GLubyte *map,
+                              GLint rowStride, GLint i, GLint j,
+                              GLfloat *texel)
+{
+   fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
+}
+
+compressed_fetch_func
+_mesa_get_bptc_fetch_func(mesa_format format)
+{
+   switch (format) {
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+      return fetch_bptc_rgba_unorm;
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+      return fetch_bptc_srgb_alpha_unorm;
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+      return fetch_bptc_rgb_signed_float;
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+      return fetch_bptc_rgb_unsigned_float;
+   default:
+      return NULL;
+   }
+}
+
+static void
+write_bits(struct bit_writer *writer, int n_bits, int value)
+{
+   do {
+      if (n_bits + writer->pos >= 8) {
+         *(writer->dst++) = writer->buf | (value << writer->pos);
+         writer->buf = 0;
+         value >>= (8 - writer->pos);
+         n_bits -= (8 - writer->pos);
+         writer->pos = 0;
+      } else {
+         writer->buf |= value << writer->pos;
+         writer->pos += n_bits;
+         break;
+      }
+   } while (n_bits > 0);
+}
+
+static void
+get_average_luminance_alpha_unorm(int width, int height,
+                                  const uint8_t *src, int src_rowstride,
+                                  int *average_luminance, int *average_alpha)
+{
+   int luminance_sum = 0, alpha_sum = 0;
+   int y, x;
+
+   for (y = 0; y < height; y++) {
+      for (x = 0; x < width; x++) {
+         luminance_sum += src[0] + src[1] + src[2];
+         alpha_sum += src[3];
+         src += 4;
+      }
+      src += src_rowstride - width * 4;
+   }
+
+   *average_luminance = luminance_sum / (width * height);
+   *average_alpha = alpha_sum / (width * height);
+}
+
+static void
+get_rgba_endpoints_unorm(int width, int height,
+                         const uint8_t *src, int src_rowstride,
+                         int average_luminance, int average_alpha,
+                         uint8_t endpoints[][4])
+{
+   int endpoint_luminances[2];
+   int midpoint;
+   int sums[2][4];
+   int endpoint;
+   int luminance;
+   uint8_t temp[3];
+   const uint8_t *p = src;
+   int rgb_left_endpoint_count = 0;
+   int alpha_left_endpoint_count = 0;
+   int y, x, i;
+
+   memset(sums, 0, sizeof sums);
+
+   for (y = 0; y < height; y++) {
+      for (x = 0; x < width; x++) {
+         luminance = p[0] + p[1] + p[2];
+         if (luminance < average_luminance) {
+            endpoint = 0;
+            rgb_left_endpoint_count++;
+         } else {
+            endpoint = 1;
+         }
+         for (i = 0; i < 3; i++)
+            sums[endpoint][i] += p[i];
+
+         if (p[2] < average_alpha) {
+            endpoint = 0;
+            alpha_left_endpoint_count++;
+         } else {
+            endpoint = 1;
+         }
+         sums[endpoint][3] += p[3];
+
+         p += 4;
+      }
+
+      p += src_rowstride - width * 4;
+   }
+
+   if (rgb_left_endpoint_count == 0 ||
+       rgb_left_endpoint_count == width * height) {
+      for (i = 0; i < 3; i++)
+         endpoints[0][i] = endpoints[1][i] =
+            (sums[0][i] + sums[1][i]) / (width * height);
+   } else {
+      for (i = 0; i < 3; i++) {
+         endpoints[0][i] = sums[0][i] / rgb_left_endpoint_count;
+         endpoints[1][i] = (sums[1][i] /
+                            (width * height - rgb_left_endpoint_count));
+      }
+   }
+
+   if (alpha_left_endpoint_count == 0 ||
+       alpha_left_endpoint_count == width * height) {
+      endpoints[0][3] = endpoints[1][3] =
+         (sums[0][3] + sums[1][3]) / (width * height);
+   } else {
+         endpoints[0][3] = sums[0][3] / alpha_left_endpoint_count;
+         endpoints[1][3] = (sums[1][3] /
+                            (width * height - alpha_left_endpoint_count));
+   }
+
+   /* We may need to swap the endpoints to ensure the most-significant bit of
+    * the first index is zero */
+
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      endpoint_luminances[endpoint] =
+         endpoints[endpoint][0] +
+         endpoints[endpoint][1] +
+         endpoints[endpoint][2];
+   }
+   midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2;
+
+   if ((src[0] + src[1] + src[2] <= midpoint) !=
+       (endpoint_luminances[0] <= midpoint)) {
+      memcpy(temp, endpoints[0], 3);
+      memcpy(endpoints[0], endpoints[1], 3);
+      memcpy(endpoints[1], temp, 3);
+   }
+
+   /* Same for the alpha endpoints */
+
+   midpoint = (endpoints[0][3] + endpoints[1][3]) / 2;
+
+   if ((src[3] <= midpoint) != (endpoints[0][3] <= midpoint)) {
+      temp[0] = endpoints[0][3];
+      endpoints[0][3] = endpoints[1][3];
+      endpoints[1][3] = temp[0];
+   }
+}
+
+static void
+write_rgb_indices_unorm(struct bit_writer *writer,
+                        int src_width, int src_height,
+                        const uint8_t *src, int src_rowstride,
+                        uint8_t endpoints[][4])
+{
+   int luminance;
+   int endpoint_luminances[2];
+   int endpoint;
+   int index;
+   int y, x;
+
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      endpoint_luminances[endpoint] =
+         endpoints[endpoint][0] +
+         endpoints[endpoint][1] +
+         endpoints[endpoint][2];
+   }
+
+   /* If the endpoints have the same luminance then we'll just use index 0 for
+    * all of the texels */
+   if (endpoint_luminances[0] == endpoint_luminances[1]) {
+      write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 2 - 1, 0);
+      return;
+   }
+
+   for (y = 0; y < src_height; y++) {
+      for (x = 0; x < src_width; x++) {
+         luminance = src[0] + src[1] + src[2];
+
+         index = ((luminance - endpoint_luminances[0]) * 3 /
+                  (endpoint_luminances[1] - endpoint_luminances[0]));
+         if (index < 0)
+            index = 0;
+         else if (index > 3)
+            index = 3;
+
+         assert(x != 0 || y != 0 || index < 2);
+
+         write_bits(writer, (x == 0 && y == 0) ? 1 : 2, index);
+
+         src += 4;
+      }
+
+      /* Pad the indices out to the block size */
+      if (src_width < BLOCK_SIZE)
+         write_bits(writer, 2 * (BLOCK_SIZE - src_width), 0);
+
+      src += src_rowstride - src_width * 4;
+   }
+
+   /* Pad the indices out to the block size */
+   if (src_height < BLOCK_SIZE)
+      write_bits(writer, 2 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static void
+write_alpha_indices_unorm(struct bit_writer *writer,
+                          int src_width, int src_height,
+                          const uint8_t *src, int src_rowstride,
+                          uint8_t endpoints[][4])
+{
+   int index;
+   int y, x;
+
+   /* If the endpoints have the same alpha then we'll just use index 0 for
+    * all of the texels */
+   if (endpoints[0][3] == endpoints[1][3]) {
+      write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 3 - 1, 0);
+      return;
+   }
+
+   for (y = 0; y < src_height; y++) {
+      for (x = 0; x < src_width; x++) {
+         index = (((int) src[3] - (int) endpoints[0][3]) * 7 /
+                  ((int) endpoints[1][3] - endpoints[0][3]));
+         if (index < 0)
+            index = 0;
+         else if (index > 7)
+            index = 7;
+
+         assert(x != 0 || y != 0 || index < 4);
+
+         /* The first index has one less bit */
+         write_bits(writer, (x == 0 && y == 0) ? 2 : 3, index);
+
+         src += 4;
+      }
+
+      /* Pad the indices out to the block size */
+      if (src_width < BLOCK_SIZE)
+         write_bits(writer, 3 * (BLOCK_SIZE - src_width), 0);
+
+      src += src_rowstride - src_width * 4;
+   }
+
+   /* Pad the indices out to the block size */
+   if (src_height < BLOCK_SIZE)
+      write_bits(writer, 3 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static void
+compress_rgba_unorm_block(int src_width, int src_height,
+                          const uint8_t *src, int src_rowstride,
+                          uint8_t *dst)
+{
+   int average_luminance, average_alpha;
+   uint8_t endpoints[2][4];
+   struct bit_writer writer;
+   int component, endpoint;
+
+   get_average_luminance_alpha_unorm(src_width, src_height, src, src_rowstride,
+                                     &average_luminance, &average_alpha);
+   get_rgba_endpoints_unorm(src_width, src_height, src, src_rowstride,
+                            average_luminance, average_alpha,
+                            endpoints);
+
+   writer.dst = dst;
+   writer.pos = 0;
+   writer.buf = 0;
+
+   write_bits(&writer, 5, 0x10); /* mode 4 */
+   write_bits(&writer, 2, 0); /* rotation 0 */
+   write_bits(&writer, 1, 0); /* index selection bit */
+
+   /* Write the color endpoints */
+   for (component = 0; component < 3; component++)
+      for (endpoint = 0; endpoint < 2; endpoint++)
+         write_bits(&writer, 5, endpoints[endpoint][component] >> 3);
+
+   /* Write the alpha endpoints */
+   for (endpoint = 0; endpoint < 2; endpoint++)
+      write_bits(&writer, 6, endpoints[endpoint][3] >> 2);
+
+   write_rgb_indices_unorm(&writer,
+                           src_width, src_height,
+                           src, src_rowstride,
+                           endpoints);
+   write_alpha_indices_unorm(&writer,
+                             src_width, src_height,
+                             src, src_rowstride,
+                             endpoints);
+}
+
+static void
+compress_rgba_unorm(int width, int height,
+                    const uint8_t *src, int src_rowstride,
+                    uint8_t *dst, int dst_rowstride)
+{
+   int dst_row_diff;
+   int y, x;
+
+   if (dst_rowstride >= width * 4)
+      dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4;
+   else
+      dst_row_diff = 0;
+
+   for (y = 0; y < height; y += BLOCK_SIZE) {
+      for (x = 0; x < width; x += BLOCK_SIZE) {
+         compress_rgba_unorm_block(MIN2(width - x, BLOCK_SIZE),
+                                   MIN2(height - y, BLOCK_SIZE),
+                                   src + x * 4 + y * src_rowstride,
+                                   src_rowstride,
+                                   dst);
+         dst += BLOCK_BYTES;
+      }
+      dst += dst_row_diff;
+   }
+}
+
+GLboolean
+_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)
+{
+   const GLubyte *pixels;
+   const GLubyte *tempImage = NULL;
+   GLenum baseFormat;
+   int rowstride;
+
+   if (srcFormat != GL_RGBA ||
+       srcType != GL_UNSIGNED_BYTE ||
+       ctx->_ImageTransferState ||
+       srcPacking->SwapBytes) {
+      /* convert image to RGBA/ubyte */
+      baseFormat = _mesa_get_format_base_format(dstFormat);
+      tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
+                                              baseInternalFormat,
+                                              baseFormat,
+                                              srcWidth, srcHeight, srcDepth,
+                                              srcFormat, srcType, srcAddr,
+                                              srcPacking);
+      if (!tempImage)
+         return GL_FALSE; /* out of memory */
+
+      pixels = tempImage;
+      rowstride = srcWidth * 4;
+   } else {
+      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
+                                     srcFormat, srcType, 0, 0);
+      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
+                                         srcFormat, srcType);
+   }
+
+   compress_rgba_unorm(srcWidth, srcHeight,
+                       pixels, rowstride,
+                       dstSlices[0], dstRowStride);
+
+   free((void *) tempImage);
+
+   return GL_TRUE;
+}
+
+static float
+get_average_luminance_float(int width, int height,
+                            const float *src, int src_rowstride)
+{
+   float luminance_sum = 0;
+   int y, x;
+
+   for (y = 0; y < height; y++) {
+      for (x = 0; x < width; x++) {
+         luminance_sum += src[0] + src[1] + src[2];
+         src += 3;
+      }
+      src += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float);
+   }
+
+   return luminance_sum / (width * height);
+}
+
+static float
+clamp_value(float value, bool is_signed)
+{
+   if (value > 65504.0f)
+      return 65504.0f;
+
+   if (is_signed) {
+      if (value < -65504.0f)
+         return -65504.0f;
+      else
+         return value;
+   }
+
+   if (value < 0.0f)
+      return 0.0f;
+
+   return value;
+}
+
+static void
+get_endpoints_float(int width, int height,
+                    const float *src, int src_rowstride,
+                    float average_luminance, float endpoints[][3],
+                    bool is_signed)
+{
+   float endpoint_luminances[2];
+   float midpoint;
+   float sums[2][3];
+   int endpoint, component;
+   float luminance;
+   float temp[3];
+   const float *p = src;
+   int left_endpoint_count = 0;
+   int y, x, i;
+
+   memset(sums, 0, sizeof sums);
+
+   for (y = 0; y < height; y++) {
+      for (x = 0; x < width; x++) {
+         luminance = p[0] + p[1] + p[2];
+         if (luminance < average_luminance) {
+            endpoint = 0;
+            left_endpoint_count++;
+         } else {
+            endpoint = 1;
+         }
+         for (i = 0; i < 3; i++)
+            sums[endpoint][i] += p[i];
+
+         p += 3;
+      }
+
+      p += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float);
+   }
+
+   if (left_endpoint_count == 0 ||
+       left_endpoint_count == width * height) {
+      for (i = 0; i < 3; i++)
+         endpoints[0][i] = endpoints[1][i] =
+            (sums[0][i] + sums[1][i]) / (width * height);
+   } else {
+      for (i = 0; i < 3; i++) {
+         endpoints[0][i] = sums[0][i] / left_endpoint_count;
+         endpoints[1][i] = sums[1][i] / (width * height - left_endpoint_count);
+      }
+   }
+
+   /* Clamp the endpoints to the range of a half float and strip out
+    * infinities */
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      for (component = 0; component < 3; component++) {
+         endpoints[endpoint][component] =
+            clamp_value(endpoints[endpoint][component], is_signed);
+      }
+   }
+
+   /* We may need to swap the endpoints to ensure the most-significant bit of
+    * the first index is zero */
+
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      endpoint_luminances[endpoint] =
+         endpoints[endpoint][0] +
+         endpoints[endpoint][1] +
+         endpoints[endpoint][2];
+   }
+   midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2.0f;
+
+   if ((src[0] + src[1] + src[2] <= midpoint) !=
+       (endpoint_luminances[0] <= midpoint)) {
+      memcpy(temp, endpoints[0], sizeof temp);
+      memcpy(endpoints[0], endpoints[1], sizeof temp);
+      memcpy(endpoints[1], temp, sizeof temp);
+   }
+}
+
+static void
+write_rgb_indices_float(struct bit_writer *writer,
+                        int src_width, int src_height,
+                        const float *src, int src_rowstride,
+                        float endpoints[][3])
+{
+   float luminance;
+   float endpoint_luminances[2];
+   int endpoint;
+   int index;
+   int y, x;
+
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      endpoint_luminances[endpoint] =
+         endpoints[endpoint][0] +
+         endpoints[endpoint][1] +
+         endpoints[endpoint][2];
+   }
+
+   /* If the endpoints have the same luminance then we'll just use index 0 for
+    * all of the texels */
+   if (endpoint_luminances[0] == endpoint_luminances[1]) {
+      write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 4 - 1, 0);
+      return;
+   }
+
+   for (y = 0; y < src_height; y++) {
+      for (x = 0; x < src_width; x++) {
+         luminance = src[0] + src[1] + src[2];
+
+         index = ((luminance - endpoint_luminances[0]) * 15 /
+                  (endpoint_luminances[1] - endpoint_luminances[0]));
+         if (index < 0)
+            index = 0;
+         else if (index > 15)
+            index = 15;
+
+         assert(x != 0 || y != 0 || index < 8);
+
+         write_bits(writer, (x == 0 && y == 0) ? 3 : 4, index);
+
+         src += 3;
+      }
+
+      /* Pad the indices out to the block size */
+      if (src_width < BLOCK_SIZE)
+         write_bits(writer, 4 * (BLOCK_SIZE - src_width), 0);
+
+      src += (src_rowstride - src_width * 3 * sizeof (float)) / sizeof (float);
+   }
+
+   /* Pad the indices out to the block size */
+   if (src_height < BLOCK_SIZE)
+      write_bits(writer, 4 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static int
+get_endpoint_value(float value, bool is_signed)
+{
+   bool sign = false;
+   int half;
+
+   if (is_signed) {
+      half = _mesa_float_to_half(value);
+
+      if (half & 0x8000) {
+         half &= 0x7fff;
+         sign = true;
+      }
+
+      half = (32 * half / 31) >> 6;
+
+      if (sign)
+         half = -half & ((1 << 10) - 1);
+
+      return half;
+   } else {
+      if (value <= 0.0f)
+         return 0;
+
+      half = _mesa_float_to_half(value);
+
+      return (64 * half / 31) >> 6;
+   }
+}
+
+static void
+compress_rgb_float_block(int src_width, int src_height,
+                         const float *src, int src_rowstride,
+                         uint8_t *dst,
+                         bool is_signed)
+{
+   float average_luminance;
+   float endpoints[2][3];
+   struct bit_writer writer;
+   int component, endpoint;
+   int endpoint_value;
+
+   average_luminance =
+      get_average_luminance_float(src_width, src_height, src, src_rowstride);
+   get_endpoints_float(src_width, src_height, src, src_rowstride,
+                       average_luminance, endpoints, is_signed);
+
+   writer.dst = dst;
+   writer.pos = 0;
+   writer.buf = 0;
+
+   write_bits(&writer, 5, 3); /* mode 3 */
+
+   /* Write the endpoints */
+   for (endpoint = 0; endpoint < 2; endpoint++) {
+      for (component = 0; component < 3; component++) {
+         endpoint_value =
+            get_endpoint_value(endpoints[endpoint][component], is_signed);
+         write_bits(&writer, 10, endpoint_value);
+      }
+   }
+
+   write_rgb_indices_float(&writer,
+                           src_width, src_height,
+                           src, src_rowstride,
+                           endpoints);
+}
+
+static void
+compress_rgb_float(int width, int height,
+                   const float *src, int src_rowstride,
+                   uint8_t *dst, int dst_rowstride,
+                   bool is_signed)
+{
+   int dst_row_diff;
+   int y, x;
+
+   if (dst_rowstride >= width * 4)
+      dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4;
+   else
+      dst_row_diff = 0;
+
+   for (y = 0; y < height; y += BLOCK_SIZE) {
+      for (x = 0; x < width; x += BLOCK_SIZE) {
+         compress_rgb_float_block(MIN2(width - x, BLOCK_SIZE),
+                                  MIN2(height - y, BLOCK_SIZE),
+                                  src + x * 3 +
+                                  y * src_rowstride / sizeof (float),
+                                  src_rowstride,
+                                  dst,
+                                  is_signed);
+         dst += BLOCK_BYTES;
+      }
+      dst += dst_row_diff;
+   }
+}
+
+static GLboolean
+texstore_bptc_rgb_float(TEXSTORE_PARAMS,
+                        bool is_signed)
+{
+   const float *pixels;
+   const float *tempImage = NULL;
+   GLenum baseFormat;
+   int rowstride;
+
+   if (srcFormat != GL_RGB ||
+       srcType != GL_FLOAT ||
+       ctx->_ImageTransferState ||
+       srcPacking->SwapBytes) {
+      /* convert image to RGB/float */
+      baseFormat = _mesa_get_format_base_format(dstFormat);
+      tempImage = _mesa_make_temp_float_image(ctx, dims,
+                                              baseInternalFormat,
+                                              baseFormat,
+                                              srcWidth, srcHeight, srcDepth,
+                                              srcFormat, srcType, srcAddr,
+                                              srcPacking,
+                                              ctx->_ImageTransferState);
+      if (!tempImage)
+         return GL_FALSE; /* out of memory */
+
+      pixels = tempImage;
+      rowstride = srcWidth * sizeof(float) * 3;
+   } else {
+      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
+                                     srcFormat, srcType, 0, 0);
+      rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
+                                         srcFormat, srcType);
+   }
+
+   compress_rgb_float(srcWidth, srcHeight,
+                      pixels, rowstride,
+                      dstSlices[0], dstRowStride,
+                      is_signed);
+
+   free((void *) tempImage);
+
+   return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)
+{
+   ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT);
+
+   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
+                                  dstFormat, dstRowStride, dstSlices,
+                                  srcWidth, srcHeight, srcDepth,
+                                  srcFormat, srcType,
+                                  srcAddr, srcPacking,
+                                  true /* signed */);
+}
+
+GLboolean
+_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)
+{
+   ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT);
+
+   return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
+                                  dstFormat, dstRowStride, dstSlices,
+                                  srcWidth, srcHeight, srcDepth,
+                                  srcFormat, srcType,
+                                  srcAddr, srcPacking,
+                                  false /* unsigned */);
+}
diff --git a/mesalib/src/mesa/main/texcompress_bptc.h b/mesalib/src/mesa/main/texcompress_bptc.h
new file mode 100644
index 000000000..814548e2b
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_bptc.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * 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 without limitation
+ * the rights to use, copy, modify, merge, publish, 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.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE 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.
+ */
+
+#ifndef TEXCOMPRESS_BPTC_H
+#define TEXCOMPRESS_BPTC_H
+
+#include <inttypes.h>
+#include "glheader.h"
+#include "texcompress.h"
+#include "texstore.h"
+
+GLboolean
+_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS);
+
+GLboolean
+_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS);
+
+GLboolean
+_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS);
+
+compressed_fetch_func
+_mesa_get_bptc_fetch_func(mesa_format format);
+
+#endif
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c
index c61a74859..6d3b80556 100644
--- a/mesalib/src/mesa/main/texformat.c
+++ b/mesalib/src/mesa/main/texformat.c
@@ -345,6 +345,14 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target,
       return MESA_FORMAT_SRGBA_DXT3;
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
       return MESA_FORMAT_SRGBA_DXT5;
+   case GL_COMPRESSED_RGBA_BPTC_UNORM:
+      return MESA_FORMAT_BPTC_RGBA_UNORM;
+   case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+      return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
+   case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+      return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT;
+   case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+      return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT;
 
    case GL_ALPHA16F_ARB:
       RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT16);
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index f1e09c986..2c54e4a35 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -40,6 +40,7 @@
 #include "mtypes.h"
 #include "pack.h"
 #include "pbo.h"
+#include "pixelstore.h"
 #include "texcompress.h"
 #include "texgetimage.h"
 #include "teximage.h"
@@ -693,7 +694,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx,
    GLuint i, slice;
    GLubyte *dest;
 
-   _mesa_compute_compressed_pixelstore(dimensions, texImage,
+   _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat,
                                        texImage->Width, texImage->Height,
                                        texImage->Depth,
                                        &ctx->Pack,
@@ -1008,9 +1009,9 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
 
    /* Check for invalid pixel storage modes */
    dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target);
-   if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions,
-                                                           &ctx->Pack,
-                                                           "glGetCompressedTexImageARB")) {
+   if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
+                                              &ctx->Pack,
+                                              "glGetCompressedTexImageARB")) {
       return GL_TRUE;
    }
 
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index bb050b188..647d28ab3 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -41,6 +41,7 @@
 #include "imports.h"
 #include "macros.h"
 #include "multisample.h"
+#include "pixelstore.h"
 #include "state.h"
 #include "texcompress.h"
 #include "texcompress_cpal.h"
@@ -520,6 +521,20 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
       }
    }
 
+   if (_mesa_is_desktop_gl(ctx) &&
+       ctx->Extensions.ARB_texture_compression_bptc) {
+      switch (internalFormat) {
+      case GL_COMPRESSED_RGBA_BPTC_UNORM:
+      case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+         return GL_RGBA;
+      case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+      case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+         return GL_RGB;
+      default:
+         ; /* fallthrough */
+      }
+   }
+
    if (ctx->API == API_OPENGLES) {
       switch (internalFormat) {
       case GL_PALETTE4_RGB8_OES:
@@ -2250,36 +2265,6 @@ texture_error_check( struct gl_context *ctx,
 }
 
 
-bool
-_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx,
-                                             GLint dimensions,
-                                             struct gl_pixelstore_attrib *packing,
-                                             const char *caller)
-{
-   if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize)
-      return true;
-
-   if (packing->CompressedBlockWidth && packing->SkipPixels % packing->CompressedBlockWidth) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(skip-pixels %% block-width)", caller);
-      return false;
-   }
-
-   if (dimensions > 1 && packing->CompressedBlockHeight && packing->SkipRows % packing->CompressedBlockHeight) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(skip-rows %% block-height)", caller);
-      return false;
-   }
-
-   if (dimensions > 2 && packing->CompressedBlockDepth && packing->SkipImages % packing->CompressedBlockDepth) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(skip-images %% block-depth)", caller);
-      return false;
-   }
-
-   return true;
-}
-
 /**
  * Error checking for glCompressedTexImage[123]D().
  * Note that the width, height and depth values are not fully error checked
@@ -2389,9 +2374,9 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
    }
 
    /* Check for invalid pixel storage modes */
-   if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions,
-                                                           &ctx->Unpack,
-                                                           "glCompressedTexImage")) {
+   if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
+                                                   &ctx->Unpack,
+                                                   "glCompressedTexImage")) {
       return GL_FALSE;
    }
 
@@ -4197,9 +4182,9 @@ out:
 
 /**
  * Error checking for glCompressedTexSubImage[123]D().
- * \return error code or GL_NO_ERROR.
+ * \return GL_TRUE if error, GL_FALSE if no error
  */
-static GLenum
+static GLboolean
 compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
                                   GLenum target, GLint level,
                                   GLint xoffset, GLint yoffset, GLint zoffset,
@@ -4258,13 +4243,12 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
    }
 
    /* Check for invalid pixel storage modes */
-   if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dims,
-                                                           &ctx->Unpack,
-                                                           "glCompressedTexSubImage")) {
-      return GL_FALSE;
+   if (!_mesa_compressed_pixel_storage_error_check(ctx, dims,
+                                                &ctx->Unpack,
+                                                "glCompressedTexSubImage")) {
+      return GL_TRUE;
    }
 
-
    expectedSize = compressed_tex_size(width, height, depth, format);
    if (expectedSize != imageSize) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage%uD(size=%d)",
diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h
index 52bfa7816..4b27381a0 100644
--- a/mesalib/src/mesa/main/teximage.h
+++ b/mesalib/src/mesa/main/teximage.h
@@ -339,12 +339,6 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
                               GLsizei height, GLsizei depth,
                               GLboolean fixedsamplelocations);
 
-bool
-_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx,
-                                             GLint dimensions,
-                                             struct gl_pixelstore_attrib *packing,
-                                             const char *caller);
-
 /*@}*/
 
 #ifdef __cplusplus
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 30dd0b9b3..e40fb249e 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -1384,7 +1384,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
    if (!obj)
       return;
 
-   _mesa_lock_texture(ctx, obj);
+   _mesa_lock_context_textures(ctx);
    switch (pname) {
       case GL_TEXTURE_MAG_FILTER:
 	 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
@@ -1591,11 +1591,11 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
    }
 
    /* no error if we get here */
-   _mesa_unlock_texture(ctx, obj);
+   _mesa_unlock_context_textures(ctx);
    return;
 
 invalid_pname:
-   _mesa_unlock_texture(ctx, obj);
+   _mesa_unlock_context_textures(ctx);
    _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
 }
 
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 0e036d9eb..d2aba8ba1 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -68,6 +68,7 @@
 #include "texcompress_rgtc.h"
 #include "texcompress_s3tc.h"
 #include "texcompress_etc.h"
+#include "texcompress_bptc.h"
 #include "teximage.h"
 #include "texstore.h"
 #include "enums.h"
@@ -1426,6 +1427,15 @@ texstore_compressed(TEXSTORE_PARAMS)
       table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] =
          _mesa_texstore_etc2_srgb8_punchthrough_alpha1;
 
+      table[MESA_FORMAT_BPTC_RGBA_UNORM] =
+         _mesa_texstore_bptc_rgba_unorm;
+      table[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM] =
+         _mesa_texstore_bptc_rgba_unorm;
+      table[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT] =
+         _mesa_texstore_bptc_rgb_signed_float;
+      table[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT] =
+         _mesa_texstore_bptc_rgb_unsigned_float;
+
       initialized = GL_TRUE;
    }
 
@@ -1485,6 +1495,12 @@ texstore_swizzle(TEXSTORE_PARAMS)
    if (!is_array)
       return GL_FALSE;
 
+   if (srcFormat == GL_COLOR_INDEX)
+      return GL_FALSE;
+
+   if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat))
+      return GL_FALSE;
+
    switch (srcType) {
    case GL_FLOAT:
    case GL_UNSIGNED_BYTE:
@@ -2175,14 +2191,23 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims,
 }
 
 
+/**
+ * Compute compressed_pixelstore parameters for copying compressed
+ * texture data.
+ * \param dims  number of texture image dimensions: 1, 2 or 3
+ * \param texFormat  the compressed texture format
+ * \param width, height, depth  size of image to copy
+ * \param packing  pixelstore parameters describing user-space image packing
+ * \param store  returns the compressed_pixelstore parameters
+ */
 void
-_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage,
-                              GLsizei width, GLsizei height, GLsizei depth,
-                              const struct gl_pixelstore_attrib *packing,
-                              struct compressed_pixelstore *store)
+_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
+                                    GLsizei width, GLsizei height,
+                                    GLsizei depth,
+                                    const struct gl_pixelstore_attrib *packing,
+                                    struct compressed_pixelstore *store)
 {
    GLuint bw, bh;
-   const mesa_format texFormat = texImage->TexFormat;
 
    _mesa_get_format_block_size(texFormat, &bw, &bh);
 
@@ -2252,8 +2277,9 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
       return;
    }
 
-   _mesa_compute_compressed_pixelstore(dims, texImage, width, height, depth,
-                                 &ctx->Unpack, &store);
+   _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat,
+                                       width, height, depth,
+                                       &ctx->Unpack, &store);
 
    /* get pointer to src pixels (may be in a pbo which we'll map here) */
    data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data,
diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h
index dd1e1d015..4c41d1fcd 100644
--- a/mesalib/src/mesa/main/texstore.h
+++ b/mesalib/src/mesa/main/texstore.h
@@ -150,10 +150,11 @@ struct compressed_pixelstore {
 
 
 extern void
-_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage,
-                              GLsizei width, GLsizei height, GLsizei depth,
-                              const struct gl_pixelstore_attrib *packing,
-                              struct compressed_pixelstore *store);
+_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
+                                    GLsizei width, GLsizei height,
+                                    GLsizei depth,
+                                    const struct gl_pixelstore_attrib *packing,
+                                    struct compressed_pixelstore *store);
 
 
 #endif
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 7e630e65b..4cd2bca01 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -799,9 +799,9 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
 
       for (i = 0; i < elems; i++) {
 	 if (basicType == GLSL_TYPE_FLOAT) {
-	    dst[i].i = src[i].f != 0.0f ? 1 : 0;
+            dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
 	 } else {
-	    dst[i].i = src[i].i != 0    ? 1 : 0;
+            dst[i].i = src[i].i != 0    ? ctx->Const.UniformBooleanTrue : 0;
 	 }
       }
    }
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index 230fb30cb..5d3cc2a70 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -1553,14 +1553,14 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
        */
       if (offsets[i] < 0) {
          _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glBindVertexBuffer(offsets[%u]=%" PRId64 " < 0)",
+                     "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
                      i, (int64_t) offsets[i]);
          continue;
       }
 
       if (strides[i] < 0) {
          _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glBindVertexBuffer(strides[%u]=%d < 0)",
+                     "glBindVertexBuffers(strides[%u]=%d < 0)",
                      i, strides[i]);
          continue;
       }
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
index f94ebac99..d5d8b363d 100644
--- a/mesalib/src/mesa/main/varray.h
+++ b/mesalib/src/mesa/main/varray.h
@@ -271,6 +271,10 @@ _mesa_UnlockArraysEXT( void );
 extern void GLAPIENTRY
 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count);
 
+extern void GLAPIENTRY
+_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+                          GLsizei primcount);
+
 extern void GLAPIENTRY
 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
                    const GLvoid *indices);
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index b7cc50fc1..4dea530cd 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -124,8 +124,9 @@ create_version_string(struct gl_context *ctx, const char *prefix)
  * 3.1: select a Core profile with GL version 3.1
  * 3.1FC: select a Core+Forward Compatible profile with GL version 3.1
  */
-void
-_mesa_override_gl_version(struct gl_context *ctx)
+bool
+_mesa_override_gl_version_contextless(struct gl_constants *consts,
+                                      gl_api *apiOut, GLuint *versionOut)
 {
    int version;
    GLboolean fwd_context;
@@ -133,15 +134,25 @@ _mesa_override_gl_version(struct gl_context *ctx)
    get_gl_override(&version, &fwd_context);
 
    if (version > 0) {
-      ctx->Version = version;
+      *versionOut = version;
       if (version >= 30 && fwd_context) {
-         ctx->API = API_OPENGL_CORE;
-         ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
+         *apiOut = API_OPENGL_CORE;
+         consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
       } else if (version >= 31) {
-         ctx->API = API_OPENGL_CORE;
+         *apiOut = API_OPENGL_CORE;
       } else {
-         ctx->API = API_OPENGL_COMPAT;
+         *apiOut = API_OPENGL_COMPAT;
       }
+      return GL_TRUE;
+   }
+   return GL_FALSE;
+}
+
+void
+_mesa_override_gl_version(struct gl_context *ctx)
+{
+   if (_mesa_override_gl_version_contextless(&ctx->Const, &ctx->API,
+                                             &ctx->Version)) {
       create_version_string(ctx, "");
    }
 }
@@ -168,7 +179,7 @@ _mesa_get_gl_version_override(void)
  * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130".
  */
 void
-_mesa_override_glsl_version(struct gl_context *ctx)
+_mesa_override_glsl_version(struct gl_constants *consts)
 {
    const char *env_var = "MESA_GLSL_VERSION_OVERRIDE";
    const char *version;
@@ -179,7 +190,7 @@ _mesa_override_glsl_version(struct gl_context *ctx)
       return;
    }
 
-   n = sscanf(version, "%u", &ctx->Const.GLSLVersion);
+   n = sscanf(version, "%u", &consts->GLSLVersion);
    if (n != 1) {
       fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version);
       return;
@@ -189,31 +200,32 @@ _mesa_override_glsl_version(struct gl_context *ctx)
 /**
  * Examine enabled GL extensions to determine GL version.
  */
-static void
-compute_version(struct gl_context *ctx)
+static GLuint
+compute_version(const struct gl_extensions *extensions,
+                const struct gl_constants *consts, gl_api api)
 {
-   GLuint major, minor;
+   GLuint major, minor, version;
 
-   const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp &&
-                              ctx->Extensions.ARB_texture_cube_map &&
-                              ctx->Extensions.ARB_texture_env_combine &&
-                              ctx->Extensions.ARB_texture_env_dot3);
+   const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp &&
+                              extensions->ARB_texture_cube_map &&
+                              extensions->ARB_texture_env_combine &&
+                              extensions->ARB_texture_env_dot3);
    const GLboolean ver_1_4 = (ver_1_3 &&
-                              ctx->Extensions.ARB_depth_texture &&
-                              ctx->Extensions.ARB_shadow &&
-                              ctx->Extensions.ARB_texture_env_crossbar &&
-                              ctx->Extensions.EXT_blend_color &&
-                              ctx->Extensions.EXT_blend_func_separate &&
-                              ctx->Extensions.EXT_blend_minmax &&
-                              ctx->Extensions.EXT_point_parameters);
+                              extensions->ARB_depth_texture &&
+                              extensions->ARB_shadow &&
+                              extensions->ARB_texture_env_crossbar &&
+                              extensions->EXT_blend_color &&
+                              extensions->EXT_blend_func_separate &&
+                              extensions->EXT_blend_minmax &&
+                              extensions->EXT_point_parameters);
    const GLboolean ver_1_5 = (ver_1_4 &&
-                              ctx->Extensions.ARB_occlusion_query);
+                              extensions->ARB_occlusion_query);
    const GLboolean ver_2_0 = (ver_1_5 &&
-                              ctx->Extensions.ARB_point_sprite &&
-                              ctx->Extensions.ARB_vertex_shader &&
-                              ctx->Extensions.ARB_fragment_shader &&
-                              ctx->Extensions.ARB_texture_non_power_of_two &&
-                              ctx->Extensions.EXT_blend_equation_separate &&
+                              extensions->ARB_point_sprite &&
+                              extensions->ARB_vertex_shader &&
+                              extensions->ARB_fragment_shader &&
+                              extensions->ARB_texture_non_power_of_two &&
+                              extensions->EXT_blend_equation_separate &&
 
 			      /* Technically, 2.0 requires the functionality
 			       * of the EXT version.  Enable 2.0 if either
@@ -221,61 +233,61 @@ compute_version(struct gl_context *ctx)
 			       * driver that only exposes the ATI extension
 			       * will fallback to software when necessary.
 			       */
-			      (ctx->Extensions.EXT_stencil_two_side
-			       || ctx->Extensions.ATI_separate_stencil));
+			      (extensions->EXT_stencil_two_side
+			       || extensions->ATI_separate_stencil));
    const GLboolean ver_2_1 = (ver_2_0 &&
-                              ctx->Extensions.EXT_pixel_buffer_object &&
-                              ctx->Extensions.EXT_texture_sRGB);
+                              extensions->EXT_pixel_buffer_object &&
+                              extensions->EXT_texture_sRGB);
    const GLboolean ver_3_0 = (ver_2_1 &&
-                              ctx->Const.GLSLVersion >= 130 &&
-                              (ctx->Const.MaxSamples >= 4 || ctx->Const.FakeSWMSAA) &&
-                              (ctx->API == API_OPENGL_CORE ||
-                               ctx->Extensions.ARB_color_buffer_float) &&
-                              ctx->Extensions.ARB_depth_buffer_float &&
-                              ctx->Extensions.ARB_half_float_vertex &&
-                              ctx->Extensions.ARB_map_buffer_range &&
-                              ctx->Extensions.ARB_shader_texture_lod &&
-                              ctx->Extensions.ARB_texture_float &&
-                              ctx->Extensions.ARB_texture_rg &&
-                              ctx->Extensions.ARB_texture_compression_rgtc &&
-                              ctx->Extensions.EXT_draw_buffers2 &&
-                              ctx->Extensions.ARB_framebuffer_object &&
-                              ctx->Extensions.EXT_framebuffer_sRGB &&
-                              ctx->Extensions.EXT_packed_float &&
-                              ctx->Extensions.EXT_texture_array &&
-                              ctx->Extensions.EXT_texture_shared_exponent &&
-                              ctx->Extensions.EXT_transform_feedback &&
-                              ctx->Extensions.NV_conditional_render);
+                              consts->GLSLVersion >= 130 &&
+                              (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
+                              (api == API_OPENGL_CORE ||
+                               extensions->ARB_color_buffer_float) &&
+                              extensions->ARB_depth_buffer_float &&
+                              extensions->ARB_half_float_vertex &&
+                              extensions->ARB_map_buffer_range &&
+                              extensions->ARB_shader_texture_lod &&
+                              extensions->ARB_texture_float &&
+                              extensions->ARB_texture_rg &&
+                              extensions->ARB_texture_compression_rgtc &&
+                              extensions->EXT_draw_buffers2 &&
+                              extensions->ARB_framebuffer_object &&
+                              extensions->EXT_framebuffer_sRGB &&
+                              extensions->EXT_packed_float &&
+                              extensions->EXT_texture_array &&
+                              extensions->EXT_texture_shared_exponent &&
+                              extensions->EXT_transform_feedback &&
+                              extensions->NV_conditional_render);
    const GLboolean ver_3_1 = (ver_3_0 &&
-                              ctx->Const.GLSLVersion >= 140 &&
-                              ctx->Extensions.ARB_draw_instanced &&
-                              ctx->Extensions.ARB_texture_buffer_object &&
-                              ctx->Extensions.ARB_uniform_buffer_object &&
-                              ctx->Extensions.EXT_texture_snorm &&
-                              ctx->Extensions.NV_primitive_restart &&
-                              ctx->Extensions.NV_texture_rectangle &&
-                              ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
+                              consts->GLSLVersion >= 140 &&
+                              extensions->ARB_draw_instanced &&
+                              extensions->ARB_texture_buffer_object &&
+                              extensions->ARB_uniform_buffer_object &&
+                              extensions->EXT_texture_snorm &&
+                              extensions->NV_primitive_restart &&
+                              extensions->NV_texture_rectangle &&
+                              consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
    const GLboolean ver_3_2 = (ver_3_1 &&
-                              ctx->Const.GLSLVersion >= 150 &&
-                              ctx->Extensions.ARB_depth_clamp &&
-                              ctx->Extensions.ARB_draw_elements_base_vertex &&
-                              ctx->Extensions.ARB_fragment_coord_conventions &&
-                              ctx->Extensions.EXT_provoking_vertex &&
-                              ctx->Extensions.ARB_seamless_cube_map &&
-                              ctx->Extensions.ARB_sync &&
-                              ctx->Extensions.ARB_texture_multisample &&
-                              ctx->Extensions.EXT_vertex_array_bgra);
+                              consts->GLSLVersion >= 150 &&
+                              extensions->ARB_depth_clamp &&
+                              extensions->ARB_draw_elements_base_vertex &&
+                              extensions->ARB_fragment_coord_conventions &&
+                              extensions->EXT_provoking_vertex &&
+                              extensions->ARB_seamless_cube_map &&
+                              extensions->ARB_sync &&
+                              extensions->ARB_texture_multisample &&
+                              extensions->EXT_vertex_array_bgra);
    const GLboolean ver_3_3 = (ver_3_2 &&
-                              ctx->Const.GLSLVersion >= 330 &&
-                              ctx->Extensions.ARB_blend_func_extended &&
-                              ctx->Extensions.ARB_explicit_attrib_location &&
-                              ctx->Extensions.ARB_instanced_arrays &&
-                              ctx->Extensions.ARB_occlusion_query2 &&
-                              ctx->Extensions.ARB_shader_bit_encoding &&
-                              ctx->Extensions.ARB_texture_rgb10_a2ui &&
-                              ctx->Extensions.ARB_timer_query &&
-                              ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
-                              ctx->Extensions.EXT_texture_swizzle);
+                              consts->GLSLVersion >= 330 &&
+                              extensions->ARB_blend_func_extended &&
+                              extensions->ARB_explicit_attrib_location &&
+                              extensions->ARB_instanced_arrays &&
+                              extensions->ARB_occlusion_query2 &&
+                              extensions->ARB_shader_bit_encoding &&
+                              extensions->ARB_texture_rgb10_a2ui &&
+                              extensions->ARB_timer_query &&
+                              extensions->ARB_vertex_type_2_10_10_10_rev &&
+                              extensions->EXT_texture_swizzle);
                               /* ARB_sampler_objects is always enabled in mesa */
 
    if (ver_3_3) {
@@ -319,74 +331,95 @@ compute_version(struct gl_context *ctx)
       minor = 2;
    }
 
-   ctx->Version = major * 10 + minor;
+   version = major * 10 + minor;
 
-   create_version_string(ctx, "");
+   if (api == API_OPENGL_CORE && version < 31)
+      return 0;
+
+   return version;
 }
 
-static void
-compute_version_es1(struct gl_context *ctx)
+static GLuint
+compute_version_es1(const struct gl_extensions *extensions)
 {
    /* OpenGL ES 1.0 is derived from OpenGL 1.3 */
-   const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine &&
-                              ctx->Extensions.ARB_texture_env_dot3);
+   const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine &&
+                              extensions->ARB_texture_env_dot3);
    /* OpenGL ES 1.1 is derived from OpenGL 1.5 */
    const GLboolean ver_1_1 = (ver_1_0 &&
-                              ctx->Extensions.EXT_point_parameters);
+                              extensions->EXT_point_parameters);
 
    if (ver_1_1) {
-      ctx->Version = 11;
+      return 11;
    } else if (ver_1_0) {
-      ctx->Version = 10;
+      return 10;
    } else {
-      _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
+      return 0;
    }
-
-   create_version_string(ctx, "OpenGL ES-CM ");
 }
 
-static void
-compute_version_es2(struct gl_context *ctx)
+static GLuint
+compute_version_es2(const struct gl_extensions *extensions)
 {
    /* OpenGL ES 2.0 is derived from OpenGL 2.0 */
-   const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map &&
-                              ctx->Extensions.EXT_blend_color &&
-                              ctx->Extensions.EXT_blend_func_separate &&
-                              ctx->Extensions.EXT_blend_minmax &&
-                              ctx->Extensions.ARB_vertex_shader &&
-                              ctx->Extensions.ARB_fragment_shader &&
-                              ctx->Extensions.ARB_texture_non_power_of_two &&
-                              ctx->Extensions.EXT_blend_equation_separate);
+   const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map &&
+                              extensions->EXT_blend_color &&
+                              extensions->EXT_blend_func_separate &&
+                              extensions->EXT_blend_minmax &&
+                              extensions->ARB_vertex_shader &&
+                              extensions->ARB_fragment_shader &&
+                              extensions->ARB_texture_non_power_of_two &&
+                              extensions->EXT_blend_equation_separate);
    /* FINISHME: This list isn't quite right. */
-   const GLboolean ver_3_0 = (ctx->Extensions.ARB_half_float_vertex &&
-                              ctx->Extensions.ARB_internalformat_query &&
-                              ctx->Extensions.ARB_map_buffer_range &&
-                              ctx->Extensions.ARB_shader_texture_lod &&
-                              ctx->Extensions.ARB_texture_float &&
-                              ctx->Extensions.ARB_texture_rg &&
-                              ctx->Extensions.ARB_texture_compression_rgtc &&
-                              ctx->Extensions.EXT_draw_buffers2 &&
-                              /* ctx->Extensions.ARB_framebuffer_object && */
-                              ctx->Extensions.EXT_framebuffer_sRGB &&
-                              ctx->Extensions.EXT_packed_float &&
-                              ctx->Extensions.EXT_texture_array &&
-                              ctx->Extensions.EXT_texture_shared_exponent &&
-                              ctx->Extensions.EXT_transform_feedback &&
-                              ctx->Extensions.NV_conditional_render &&
-                              ctx->Extensions.ARB_draw_instanced &&
-                              ctx->Extensions.ARB_uniform_buffer_object &&
-                              ctx->Extensions.EXT_texture_snorm &&
-                              ctx->Extensions.NV_primitive_restart &&
-                              ctx->Extensions.OES_depth_texture_cube_map);
+   const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex &&
+                              extensions->ARB_internalformat_query &&
+                              extensions->ARB_map_buffer_range &&
+                              extensions->ARB_shader_texture_lod &&
+                              extensions->ARB_texture_float &&
+                              extensions->ARB_texture_rg &&
+                              extensions->ARB_texture_compression_rgtc &&
+                              extensions->EXT_draw_buffers2 &&
+                              /* extensions->ARB_framebuffer_object && */
+                              extensions->EXT_framebuffer_sRGB &&
+                              extensions->EXT_packed_float &&
+                              extensions->EXT_texture_array &&
+                              extensions->EXT_texture_shared_exponent &&
+                              extensions->EXT_transform_feedback &&
+                              extensions->NV_conditional_render &&
+                              extensions->ARB_draw_instanced &&
+                              extensions->ARB_uniform_buffer_object &&
+                              extensions->EXT_texture_snorm &&
+                              extensions->NV_primitive_restart &&
+                              extensions->OES_depth_texture_cube_map);
    if (ver_3_0) {
-      ctx->Version = 30;
+      return 30;
    } else if (ver_2_0) {
-      ctx->Version = 20;
+      return 20;
    } else {
-      _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
+      return 0;
    }
+}
 
-   create_version_string(ctx, "OpenGL ES ");
+GLuint
+_mesa_get_version(const struct gl_extensions *extensions,
+                  struct gl_constants *consts, gl_api api)
+{
+   switch (api) {
+   case API_OPENGL_COMPAT:
+      /* Disable GLSL 1.40 and later for legacy contexts.
+       * This disallows creation of the GL 3.1 compatibility context. */
+      if (consts->GLSLVersion > 130) {
+         consts->GLSLVersion = 130;
+      }
+      /* fall through */
+   case API_OPENGL_CORE:
+      return compute_version(extensions, consts, api);
+   case API_OPENGLES:
+      return compute_version_es1(extensions);
+   case API_OPENGLES2:
+      return compute_version_es2(extensions);
+   }
+   return 0;
 }
 
 /**
@@ -400,23 +433,28 @@ _mesa_compute_version(struct gl_context *ctx)
    if (ctx->Version)
       return;
 
+   ctx->Version = _mesa_get_version(&ctx->Extensions, &ctx->Const, ctx->API);
+
    switch (ctx->API) {
    case API_OPENGL_COMPAT:
-      /* Disable GLSL 1.40 and later for legacy contexts.
-       * This disallows creation of the GL 3.1 compatibility context. */
-      if (ctx->Const.GLSLVersion > 130) {
-         ctx->Const.GLSLVersion = 130;
-      }
-      /* fall through */
    case API_OPENGL_CORE:
-      compute_version(ctx);
+      create_version_string(ctx, "");
       break;
+
    case API_OPENGLES:
-      compute_version_es1(ctx);
+      if (!ctx->Version) {
+         _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
+         return;
+      }
+      create_version_string(ctx, "OpenGL ES-CM ");
       break;
+
    case API_OPENGLES2:
-      compute_version_es2(ctx);
+      if (!ctx->Version) {
+         _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
+         return;
+      }
+      create_version_string(ctx, "OpenGL ES ");
       break;
    }
-
 }
diff --git a/mesalib/src/mesa/main/version.h b/mesalib/src/mesa/main/version.h
index c78f87a2b..450a0e31d 100644
--- a/mesalib/src/mesa/main/version.h
+++ b/mesalib/src/mesa/main/version.h
@@ -27,18 +27,25 @@
 #ifndef VERSION_H
 #define VERSION_H
 
+#include "mtypes.h"
 
-struct gl_context;
 
+extern GLuint
+_mesa_get_version(const struct gl_extensions *extensions,
+                  struct gl_constants *consts, gl_api api);
 
 extern void
 _mesa_compute_version(struct gl_context *ctx);
 
+extern bool
+_mesa_override_gl_version_contextless(struct gl_constants *consts,
+                                      gl_api *apiOut, GLuint *versionOut);
+
 extern void
 _mesa_override_gl_version(struct gl_context *ctx);
 
 extern void
-_mesa_override_glsl_version(struct gl_context *ctx);
+_mesa_override_glsl_version(struct gl_constants *consts);
 
 extern int
 _mesa_get_gl_version_override(void);
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index b088160d3..e5844c3c4 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -1459,6 +1459,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
    case ir_unop_interpolate_at_centroid:
    case ir_binop_interpolate_at_offset:
    case ir_binop_interpolate_at_sample:
+   case ir_unop_dFdx_coarse:
+   case ir_unop_dFdx_fine:
+   case ir_unop_dFdy_coarse:
+   case ir_unop_dFdy_fine:
       assert(!"not supported");
       break;
 
@@ -2428,8 +2432,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name,
    }
 
    gl_register_file file;
-   if (type->is_sampler() ||
-       (type->is_array() && type->fields.array->is_sampler())) {
+   if (type->without_array()->is_sampler()) {
       file = PROGRAM_SAMPLER;
    } else {
       file = PROGRAM_UNIFORM;
@@ -2795,7 +2798,7 @@ get_mesa_program(struct gl_context *ctx,
    GLenum target = _mesa_shader_stage_to_program(shader->Stage);
    const char *target_string = _mesa_shader_stage_to_string(shader->Stage);
    struct gl_shader_compiler_options *options =
-         &ctx->ShaderCompilerOptions[shader->Stage];
+         &ctx->Const.ShaderCompilerOptions[shader->Stage];
 
    validate_ir_tree(shader->ir);
 
@@ -2980,7 +2983,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       bool progress;
       exec_list *ir = prog->_LinkedShaders[i]->ir;
       const struct gl_shader_compiler_options *options =
-            &ctx->ShaderCompilerOptions[prog->_LinkedShaders[i]->Stage];
+            &ctx->Const.ShaderCompilerOptions[prog->_LinkedShaders[i]->Stage];
 
       do {
 	 progress = false;
diff --git a/mesalib/src/mesa/program/programopt.c b/mesalib/src/mesa/program/programopt.c
index 92a8831d2..b654b1db6 100644
--- a/mesalib/src/mesa/program/programopt.c
+++ b/mesalib/src/mesa/program/programopt.c
@@ -218,7 +218,7 @@ _mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vpro
 void
 _mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
 {
-   if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS)
+   if (ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS)
       _mesa_insert_mvp_dp4_code( ctx, vprog );
    else
       _mesa_insert_mvp_mad_code( ctx, vprog );
diff --git a/mesalib/src/mesa/program/register_allocate.c b/mesalib/src/mesa/program/register_allocate.c
index 549154e8a..db2be5dfa 100644
--- a/mesalib/src/mesa/program/register_allocate.c
+++ b/mesalib/src/mesa/program/register_allocate.c
@@ -146,6 +146,12 @@ struct ra_node {
     */
    bool in_stack;
 
+   /**
+    * The q total, as defined in the Runeson/Nyström paper, for all the
+    * interfering nodes not in the stack.
+    */
+   unsigned int q_total;
+
    /* For an implementation that needs register spilling, this is the
     * approximate cost of spilling this node.
     */
@@ -162,16 +168,6 @@ struct ra_graph {
 
    unsigned int *stack;
    unsigned int stack_count;
-
-   /**
-    * Tracks the start of the set of optimistically-colored registers in the
-    * stack.
-    *
-    * Along with any registers not in the stack (if one called ra_simplify()
-    * and didn't do optimistic coloring), these need to be considered for
-    * spilling.
-    */
-   unsigned int stack_optimistic_start;
 };
 
 /**
@@ -354,6 +350,12 @@ ra_add_node_adjacency(struct ra_graph *g, unsigned int n1, unsigned int n2)
 {
    BITSET_SET(g->nodes[n1].adjacency, n2);
 
+   if (n1 != n2) {
+      int n1_class = g->nodes[n1].class;
+      int n2_class = g->nodes[n2].class;
+      g->nodes[n1].q_total += g->regs->classes[n1_class]->q[n2_class];
+   }
+
    if (g->nodes[n1].adjacency_count >=
        g->nodes[n1].adjacency_list_size) {
       g->nodes[n1].adjacency_list_size *= 2;
@@ -387,6 +389,7 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count)
       g->nodes[i].adjacency_list =
          ralloc_array(g, unsigned int, g->nodes[i].adjacency_list_size);
       g->nodes[i].adjacency_count = 0;
+      g->nodes[i].q_total = 0;
 
       ra_add_node_adjacency(g, i, i);
       g->nodes[i].reg = NO_REG;
@@ -415,20 +418,25 @@ ra_add_node_interference(struct ra_graph *g,
 static bool
 pq_test(struct ra_graph *g, unsigned int n)
 {
-   unsigned int j;
-   unsigned int q = 0;
    int n_class = g->nodes[n].class;
 
-   for (j = 0; j < g->nodes[n].adjacency_count; j++) {
-      unsigned int n2 = g->nodes[n].adjacency_list[j];
+   return g->nodes[n].q_total < g->regs->classes[n_class]->p;
+}
+
+static void
+decrement_q(struct ra_graph *g, unsigned int n)
+{
+   unsigned int i;
+   int n_class = g->nodes[n].class;
+
+   for (i = 0; i < g->nodes[n].adjacency_count; i++) {
+      unsigned int n2 = g->nodes[n].adjacency_list[i];
       unsigned int n2_class = g->nodes[n2].class;
 
       if (n != n2 && !g->nodes[n2].in_stack) {
-	 q += g->regs->classes[n_class]->q[n2_class];
+	 g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class];
       }
    }
-
-   return q < g->regs->classes[n_class]->p;
 }
 
 /**
@@ -436,17 +444,21 @@ pq_test(struct ra_graph *g, unsigned int n)
  * trivially-colorable nodes into a stack of nodes to be colored,
  * removing them from the graph, and rinsing and repeating.
  *
- * Returns true if all nodes were removed from the graph.  false
- * means that either spilling will be required, or optimistic coloring
- * should be applied.
+ * If we encounter a case where we can't push any nodes on the stack, then
+ * we optimistically choose a node and push it on the stack. We heuristically
+ * push the node with the lowest total q value, since it has the fewest
+ * neighbors and therefore is most likely to be allocated.
  */
-bool
+static void
 ra_simplify(struct ra_graph *g)
 {
    bool progress = true;
    int i;
 
    while (progress) {
+      unsigned int best_optimistic_node = ~0;
+      unsigned int lowest_q_total = ~0;
+
       progress = false;
 
       for (i = g->count - 1; i >= 0; i--) {
@@ -454,20 +466,28 @@ ra_simplify(struct ra_graph *g)
 	    continue;
 
 	 if (pq_test(g, i)) {
+	    decrement_q(g, i);
 	    g->stack[g->stack_count] = i;
 	    g->stack_count++;
 	    g->nodes[i].in_stack = true;
 	    progress = true;
+	 } else {
+	    unsigned int new_q_total = g->nodes[i].q_total;
+	    if (new_q_total < lowest_q_total) {
+	       best_optimistic_node = i;
+	       lowest_q_total = new_q_total;
+	    }
 	 }
       }
-   }
 
-   for (i = 0; i < g->count; i++) {
-      if (!g->nodes[i].in_stack && g->nodes[i].reg == -1)
-	 return false;
+      if (!progress && best_optimistic_node != ~0) {
+	 decrement_q(g, best_optimistic_node);
+	 g->stack[g->stack_count] = best_optimistic_node;
+	 g->stack_count++;
+	 g->nodes[best_optimistic_node].in_stack = true;
+	 progress = true;
+      }
    }
-
-   return true;
 }
 
 /**
@@ -477,7 +497,7 @@ ra_simplify(struct ra_graph *g)
  * If all nodes were trivially colorable, then this must succeed.  If
  * not (optimistic coloring), then it may return false;
  */
-bool
+static bool
 ra_select(struct ra_graph *g)
 {
    int i;
@@ -509,11 +529,16 @@ ra_select(struct ra_graph *g)
 	 if (i == g->nodes[n].adjacency_count)
 	    break;
       }
+
+      /* set this to false even if we return here so that
+       * ra_get_best_spill_node() considers this node later.
+       */
+      g->nodes[n].in_stack = false;
+
       if (ri == g->regs->count)
 	 return false;
 
       g->nodes[n].reg = r;
-      g->nodes[n].in_stack = false;
       g->stack_count--;
 
       if (g->regs->round_robin)
@@ -523,35 +548,10 @@ ra_select(struct ra_graph *g)
    return true;
 }
 
-/**
- * Optimistic register coloring: Just push the remaining nodes
- * on the stack.  They'll be colored first in ra_select(), and
- * if they succeed then the locally-colorable nodes are still
- * locally-colorable and the rest of the register allocation
- * will succeed.
- */
-void
-ra_optimistic_color(struct ra_graph *g)
-{
-   unsigned int i;
-
-   g->stack_optimistic_start = g->stack_count;
-   for (i = 0; i < g->count; i++) {
-      if (g->nodes[i].in_stack || g->nodes[i].reg != NO_REG)
-	 continue;
-
-      g->stack[g->stack_count] = i;
-      g->stack_count++;
-      g->nodes[i].in_stack = true;
-   }
-}
-
 bool
-ra_allocate_no_spills(struct ra_graph *g)
+ra_allocate(struct ra_graph *g)
 {
-   if (!ra_simplify(g)) {
-      ra_optimistic_color(g);
-   }
+   ra_simplify(g);
    return ra_select(g);
 }
 
@@ -614,15 +614,12 @@ ra_get_best_spill_node(struct ra_graph *g)
 {
    unsigned int best_node = -1;
    float best_benefit = 0.0;
-   unsigned int n, i;
+   unsigned int n;
 
-   /* For any registers not in the stack to be colored, consider them for
-    * spilling.  This will mostly collect nodes that were being optimistally
-    * colored as part of ra_allocate_no_spills() if we didn't successfully
-    * optimistically color.
-    *
-    * It also includes nodes not trivially colorable by ra_simplify() if it
-    * was used directly instead of as part of ra_allocate_no_spills().
+   /* Consider any nodes that we colored successfully or the node we failed to
+    * color for spilling. When we failed to color a node in ra_select(), we
+    * only considered these nodes, so spilling any other ones would not result
+    * in us making progress.
     */
    for (n = 0; n < g->count; n++) {
       float cost = g->nodes[n].spill_cost;
@@ -642,26 +639,6 @@ ra_get_best_spill_node(struct ra_graph *g)
       }
    }
 
-   /* Also consider spilling any nodes that were set up to be optimistically
-    * colored that we couldn't manage to color in ra_select().
-    */
-   for (i = g->stack_optimistic_start; i < g->stack_count; i++) {
-      float cost, benefit;
-
-      n = g->stack[i];
-      cost = g->nodes[n].spill_cost;
-
-      if (cost <= 0.0)
-         continue;
-
-      benefit = ra_get_spill_benefit(g, n);
-
-      if (benefit / cost > best_benefit) {
-         best_benefit = benefit / cost;
-         best_node = n;
-      }
-   }
-
    return best_node;
 }
 
diff --git a/mesalib/src/mesa/program/register_allocate.h b/mesalib/src/mesa/program/register_allocate.h
index 337dcf709..bfc9190dc 100644
--- a/mesalib/src/mesa/program/register_allocate.h
+++ b/mesalib/src/mesa/program/register_allocate.h
@@ -66,10 +66,7 @@ void ra_add_node_interference(struct ra_graph *g,
 /** @} */
 
 /** @{ Graph-coloring register allocation */
-bool ra_simplify(struct ra_graph *g);
-void ra_optimistic_color(struct ra_graph *g);
-bool ra_select(struct ra_graph *g);
-bool ra_allocate_no_spills(struct ra_graph *g);
+bool ra_allocate(struct ra_graph *g);
 
 unsigned int ra_get_node_reg(struct ra_graph *g, unsigned int n);
 void ra_set_node_reg(struct ra_graph * g, unsigned int n, unsigned int reg);
diff --git a/mesalib/src/mesa/program/sampler.cpp b/mesalib/src/mesa/program/sampler.cpp
index e6532be84..29a540871 100644
--- a/mesalib/src/mesa/program/sampler.cpp
+++ b/mesalib/src/mesa/program/sampler.cpp
@@ -134,3 +134,14 @@ _mesa_get_sampler_uniform_value(class ir_dereference *sampler,
    return shader_program->UniformStorage[location].sampler[shader].index +
           getname.offset;
 }
+
+
+extern "C" class ir_rvalue *
+_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler)
+{
+   ir_dereference_array *deref_arr = sampler->as_dereference_array();
+   if (!deref_arr || deref_arr->array_index->as_constant())
+      return NULL;
+
+   return deref_arr->array_index;
+}
diff --git a/mesalib/src/mesa/program/sampler.h b/mesalib/src/mesa/program/sampler.h
index 22467e990..8b7c3b63e 100644
--- a/mesalib/src/mesa/program/sampler.h
+++ b/mesalib/src/mesa/program/sampler.h
@@ -27,3 +27,6 @@ int
 _mesa_get_sampler_uniform_value(class ir_dereference *sampler,
 				struct gl_shader_program *shader_program,
 				const struct gl_program *prog);
+
+class ir_rvalue *
+_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler);
diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c
index 2e10bc3e2..03d05932a 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c
@@ -338,7 +338,7 @@ update_single_texture(struct st_context *st,
    /* Determine the format of the texture sampler view */
    if (texObj->Target == GL_TEXTURE_BUFFER) {
       view_format =
-         st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
+         st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
    }
    else {
       view_format =
diff --git a/mesalib/src/mesa/state_tracker/st_cb_condrender.c b/mesalib/src/mesa/state_tracker/st_cb_condrender.c
index 8776985f9..f02472aec 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_condrender.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_condrender.c
@@ -55,6 +55,8 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
    struct st_query_object *stq = st_query_object(q);
    struct st_context *st = st_context(ctx);
    uint m;
+   /* Don't invert the condition for rendering by default */
+   boolean inverted = FALSE;
 
    st_flush_bitmap_cache(st);
 
@@ -71,12 +73,28 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
    case GL_QUERY_BY_REGION_NO_WAIT:
       m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
       break;
+   case GL_QUERY_WAIT_INVERTED:
+      m = PIPE_RENDER_COND_WAIT;
+      inverted = TRUE;
+      break;
+   case GL_QUERY_NO_WAIT_INVERTED:
+      m = PIPE_RENDER_COND_NO_WAIT;
+      inverted = TRUE;
+      break;
+   case GL_QUERY_BY_REGION_WAIT_INVERTED:
+      m = PIPE_RENDER_COND_BY_REGION_WAIT;
+      inverted = TRUE;
+      break;
+   case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+      m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
+      inverted = TRUE;
+      break;
    default:
       assert(0 && "bad mode in st_BeginConditionalRender");
       m = PIPE_RENDER_COND_WAIT;
    }
 
-   cso_set_render_condition(st->cso_context, stq->pq, FALSE, m);
+   cso_set_render_condition(st->cso_context, stq->pq, inverted, m);
 }
 
 
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index d13a17f50..5ae092b94 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -491,7 +491,7 @@ make_texture(struct st_context *st,
    /* Choose a pixel format for the temp texture which will hold the
     * image to draw.
     */
-   pipeFormat = st_choose_matching_format(pipe->screen, PIPE_BIND_SAMPLER_VIEW,
+   pipeFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
                                           format, type, unpack->SwapBytes);
 
    if (pipeFormat == PIPE_FORMAT_NONE) {
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index ce8d91514..7cfd3dade 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -588,7 +588,7 @@ st_validate_attachment(struct gl_context *ctx,
    if (!ctx->Extensions.EXT_framebuffer_sRGB &&
        _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
       const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
-      format = st_mesa_format_to_pipe_format(linearFormat);
+      format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat);
    }
 
    valid = screen->is_format_supported(screen, format,
diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c
index 3f7bbd973..d95a608d3 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c
@@ -143,7 +143,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
 
    /* Choose the destination format by finding the best match
     * for the format+type combo. */
-   dst_format = st_choose_matching_format(screen, bind, format, type,
+   dst_format = st_choose_matching_format(st, bind, format, type,
                                           pack->SwapBytes);
    if (dst_format == PIPE_FORMAT_NONE) {
       goto fallback;
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index c4b2107ba..ad14bd939 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c
@@ -37,6 +37,7 @@
 #include "main/pbo.h"
 #include "main/pixeltransfer.h"
 #include "main/texcompress.h"
+#include "main/texcompress_etc.h"
 #include "main/texgetimage.h"
 #include "main/teximage.h"
 #include "main/texobj.h"
@@ -207,8 +208,32 @@ st_MapTextureImage(struct gl_context *ctx,
    map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1,
                               &transfer);
    if (map) {
-      *mapOut = map;
-      *rowStrideOut = transfer->stride;
+      if (_mesa_is_format_etc2(texImage->TexFormat) ||
+          (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+         /* ETC isn't supported by gallium and it's represented
+          * by uncompressed formats. Only write transfers with precompressed
+          * data are supported by ES3, which makes this really simple.
+          *
+          * Just create a temporary storage where the ETC texture will
+          * be stored. It will be decompressed in the Unmap function.
+          */
+         unsigned z = transfer->box.z;
+         struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
+
+         itransfer->temp_data =
+            malloc(_mesa_format_image_size(texImage->TexFormat, w, h, 1));
+         itransfer->temp_stride =
+            _mesa_format_row_stride(texImage->TexFormat, w);
+         itransfer->map = map;
+
+         *mapOut = itransfer->temp_data;
+         *rowStrideOut = itransfer->temp_stride;
+      }
+      else {
+         /* supported mapping */
+         *mapOut = map;
+         *rowStrideOut = transfer->stride;
+      }
    }
    else {
       *mapOut = NULL;
@@ -225,6 +250,35 @@ st_UnmapTextureImage(struct gl_context *ctx,
 {
    struct st_context *st = st_context(ctx);
    struct st_texture_image *stImage  = st_texture_image(texImage);
+
+   if (_mesa_is_format_etc2(texImage->TexFormat) ||
+       (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+      /* Decompress the ETC texture to the mapped one. */
+      unsigned z = slice + stImage->base.Face;
+      struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
+      struct pipe_transfer *transfer = itransfer->transfer;
+
+      assert(z == transfer->box.z);
+
+      if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) {
+         _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride,
+                                    itransfer->temp_data,
+                                    itransfer->temp_stride,
+                                    transfer->box.width, transfer->box.height);
+      }
+      else {
+         _mesa_unpack_etc2_format(itransfer->map, transfer->stride,
+                                  itransfer->temp_data, itransfer->temp_stride,
+                                  transfer->box.width, transfer->box.height,
+                                  texImage->TexFormat);
+      }
+
+      free(itransfer->temp_data);
+      itransfer->temp_data = NULL;
+      itransfer->temp_stride = 0;
+      itransfer->map = 0;
+   }
+
    st_texture_image_unmap(st, stImage, slice);
 }
 
@@ -398,7 +452,7 @@ guess_and_alloc_texture(struct st_context *st,
    stObj->height0 = height;
    stObj->depth0 = depth;
 
-   fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);
+   fmt = st_mesa_format_to_pipe_format(st, stImage->base.TexFormat);
 
    bindings = default_bindings(st, fmt);
 
@@ -449,7 +503,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
    /* Look if the parent texture object has space for this image */
    if (stObj->pt &&
        level <= stObj->pt->last_level &&
-       st_texture_match_image(stObj->pt, texImage)) {
+       st_texture_match_image(st, stObj->pt, texImage)) {
       /* this image will fit in the existing texture object's memory */
       pipe_resource_reference(&stImage->pt, stObj->pt);
       return GL_TRUE;
@@ -472,7 +526,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
    }
 
    if (stObj->pt &&
-       st_texture_match_image(stObj->pt, texImage)) {
+       st_texture_match_image(st, stObj->pt, texImage)) {
       /* The image will live in the object's mipmap memory */
       pipe_resource_reference(&stImage->pt, stObj->pt);
       assert(stImage->pt);
@@ -486,7 +540,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
        * level.
        */
       enum pipe_format format =
-         st_mesa_format_to_pipe_format(texImage->TexFormat);
+         st_mesa_format_to_pipe_format(st, texImage->TexFormat);
       GLuint bindings = default_bindings(st, format);
       GLuint ptWidth, ptHeight, ptDepth, ptLayers;
 
@@ -613,6 +667,9 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
    unsigned bind;
    GLubyte *map;
 
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
    if (!st->prefer_blit_based_texture_transfer) {
       goto fallback;
    }
@@ -660,7 +717,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
    }
 
    /* Choose the source format. */
-   src_format = st_choose_matching_format(screen, PIPE_BIND_SAMPLER_VIEW,
+   src_format = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
                                           format, type, unpack->SwapBytes);
    if (!src_format) {
       goto fallback;
@@ -872,6 +929,9 @@ st_GetTexImage(struct gl_context * ctx,
    ubyte *map = NULL;
    boolean done = FALSE;
 
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
    if (!st->prefer_blit_based_texture_transfer &&
        !_mesa_is_format_compressed(texImage->TexFormat)) {
       /* Try to avoid the fallback if we're doing texture decompression here */
@@ -934,7 +994,7 @@ st_GetTexImage(struct gl_context * ctx,
 
    /* Choose the destination format by finding the best match
     * for the format+type combo. */
-   dst_format = st_choose_matching_format(screen, bind, format, type,
+   dst_format = st_choose_matching_format(st, bind, format, type,
 					  ctx->Pack.SwapBytes);
 
    if (dst_format == PIPE_FORMAT_NONE) {
@@ -956,6 +1016,7 @@ st_GetTexImage(struct gl_context * ctx,
       case PIPE_FORMAT_RGTC1_UNORM:
       case PIPE_FORMAT_RGTC2_UNORM:
       case PIPE_FORMAT_ETC1_RGB8:
+      case PIPE_FORMAT_BPTC_RGBA_UNORM:
          dst_glformat = GL_RGBA8;
          break;
       case PIPE_FORMAT_RGTC1_SNORM:
@@ -964,7 +1025,12 @@ st_GetTexImage(struct gl_context * ctx,
             goto fallback;
          dst_glformat = GL_RGBA8_SNORM;
          break;
-      /* TODO: for BPTC_*FLOAT, set RGBA32F and check for ARB_texture_float */
+      case PIPE_FORMAT_BPTC_RGB_FLOAT:
+      case PIPE_FORMAT_BPTC_RGB_UFLOAT:
+         if (!ctx->Extensions.ARB_texture_float)
+            goto fallback;
+         dst_glformat = GL_RGBA32F;
+         break;
       default:
          assert(0);
          goto fallback;
@@ -1308,6 +1374,9 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    unsigned bind;
    GLint srcY0, srcY1;
 
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
    if (!strb || !strb->surface || !stImage->pt) {
       debug_printf("%s: null strb or stImage\n", __FUNCTION__);
       return;
@@ -1531,7 +1600,8 @@ st_finalize_texture(struct gl_context *ctx,
    }
 
    /* Find gallium format for the Mesa texture */
-   firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
+   firstImageFormat =
+      st_mesa_format_to_pipe_format(st, firstImage->base.TexFormat);
 
    /* Find size of level=0 Gallium mipmap image, plus number of texture layers */
    {
@@ -1649,7 +1719,7 @@ st_AllocTextureStorage(struct gl_context *ctx,
    stObj->depth0 = depth;
    stObj->lastLevel = levels - 1;
 
-   fmt = st_mesa_format_to_pipe_format(texImage->TexFormat);
+   fmt = st_mesa_format_to_pipe_format(st, texImage->TexFormat);
 
    bindings = default_bindings(st, fmt);
 
@@ -1728,7 +1798,7 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target,
       memset(&pt, 0, sizeof(pt));
 
       pt.target = gl_target_to_pipe(target);
-      pt.format = st_mesa_format_to_pipe_format(format);
+      pt.format = st_mesa_format_to_pipe_format(st, format);
 
       st_gl_texture_dims_to_pipe_dims(target,
                                       width, height, depth,
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index c805a094b..09b615465 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -189,6 +189,9 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
    st->has_stencil_export =
       screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
    st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3);
+   st->has_etc1 = screen->is_format_supported(screen, PIPE_FORMAT_ETC1_RGB8,
+                                              PIPE_TEXTURE_2D, 0,
+                                              PIPE_BIND_SAMPLER_VIEW);
    st->prefer_blit_based_texture_transfer = screen->get_param(screen,
                               PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER);
 
@@ -198,10 +201,40 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
       !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
          (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 |
           PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600));
+   st->has_time_elapsed =
+      screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
 
    /* GL limits and extensions */
-   st_init_limits(st);
-   st_init_extensions(st);
+   st_init_limits(st->pipe->screen, &ctx->Const, &ctx->Extensions);
+   st_init_extensions(st->pipe->screen, ctx->API, &ctx->Const,
+                      &ctx->Extensions, &st->options, ctx->Mesa_DXTn);
+
+   /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */
+   if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
+      if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
+         st->clamp_vert_color_in_shader = GL_TRUE;
+      }
+
+      if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) {
+         st->clamp_frag_color_in_shader = GL_TRUE;
+      }
+
+      /* For drivers which cannot do color clamping, it's better to just
+       * disable ARB_color_buffer_float in the core profile, because
+       * the clamping is deprecated there anyway. */
+      if (ctx->API == API_OPENGL_CORE &&
+          (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) {
+         st->clamp_vert_color_in_shader = GL_FALSE;
+         st->clamp_frag_color_in_shader = GL_FALSE;
+         ctx->Extensions.ARB_color_buffer_float = GL_FALSE;
+      }
+   }
+
+   /* called after _mesa_create_context/_mesa_init_point, fix default user
+    * settable max point size up
+    */
+   st->ctx->Point.MaxSize = MAX2(ctx->Const.MaxPointSize,
+                                 ctx->Const.MaxPointSizeAA);
 
    _mesa_compute_version(ctx);
 
@@ -241,7 +274,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
     * driver prefers DP4 or MUL/MAD for vertex transformation.
     */
    if (debug_get_option_mesa_mvp_dp4())
-      ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE;
+      ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE;
 
    return st_create_context_priv(ctx, pipe, options);
 }
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 361a24b1d..6d572bd49 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -86,6 +86,7 @@ struct st_context
    boolean has_stencil_export; /**< can do shader stencil export? */
    boolean has_time_elapsed;
    boolean has_shader_model3;
+   boolean has_etc1;
    boolean prefer_blit_based_texture_transfer;
 
    boolean needs_texcoord_semantic;
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 7ac484056..4110eb5dd 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -70,10 +70,9 @@ static int _clamp(int a, int min, int max)
  * Query driver to get implementation limits.
  * Note that we have to limit/clamp against Mesa's internal limits too.
  */
-void st_init_limits(struct st_context *st)
+void st_init_limits(struct pipe_screen *screen,
+                    struct gl_constants *c, struct gl_extensions *extensions)
 {
-   struct pipe_screen *screen = st->pipe->screen;
-   struct gl_constants *c = &st->ctx->Const;
    unsigned sh;
    boolean can_ubo = TRUE;
 
@@ -124,10 +123,7 @@ void st_init_limits(struct st_context *st)
    c->MaxPointSizeAA
       = _maxf(1.0f, screen->get_paramf(screen,
                                        PIPE_CAPF_MAX_POINT_WIDTH_AA));
-   /* called after _mesa_create_context/_mesa_init_point, fix default user
-    * settable max point size up
-    */
-   st->ctx->Point.MaxSize = MAX2(c->MaxPointSize, c->MaxPointSizeAA);
+
    /* these are not queryable. Note that GL basically mandates a 1.0 minimum
     * for non-aa sizes, but we can go down to 0.0 for aa points.
     */
@@ -158,15 +154,15 @@ void st_init_limits(struct st_context *st)
       switch (sh) {
       case PIPE_SHADER_FRAGMENT:
          pc = &c->Program[MESA_SHADER_FRAGMENT];
-         options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
+         options = &c->ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
          break;
       case PIPE_SHADER_VERTEX:
          pc = &c->Program[MESA_SHADER_VERTEX];
-         options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX];
+         options = &c->ShaderCompilerOptions[MESA_SHADER_VERTEX];
          break;
       case PIPE_SHADER_GEOMETRY:
          pc = &c->Program[MESA_SHADER_GEOMETRY];
-         options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_GEOMETRY];
+         options = &c->ShaderCompilerOptions[MESA_SHADER_GEOMETRY];
          break;
       default:
          /* compute shader, etc. */
@@ -191,8 +187,7 @@ void st_init_limits(struct st_context *st)
       pc->MaxTemps           = pc->MaxNativeTemps           =
          screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_TEMPS);
       pc->MaxAddressRegs     = pc->MaxNativeAddressRegs     =
-         _min(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ADDRS),
-              MAX_PROGRAM_ADDRESS_REGS);
+         sh == PIPE_SHADER_VERTEX ? 1 : 0;
       pc->MaxParameters      = pc->MaxNativeParameters      =
          screen->get_shader_param(screen, sh,
                    PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / sizeof(float[4]);
@@ -300,7 +295,7 @@ void st_init_limits(struct st_context *st)
       screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS);
 
    if (can_ubo) {
-      st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE;
+      extensions->ARB_uniform_buffer_object = GL_TRUE;
       c->UniformBufferOffsetAlignment =
          screen->get_param(screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT);
       c->MaxCombinedUniformBlocks = c->MaxUniformBufferBindings =
@@ -340,14 +335,15 @@ struct st_extension_format_mapping {
  *
  * target and bind_flags are passed to is_format_supported.
  */
-static void init_format_extensions(struct st_context *st,
-                           const struct st_extension_format_mapping *mapping,
-                           unsigned num_mappings,
-                           enum pipe_texture_target target,
-                           unsigned bind_flags)
+static void
+init_format_extensions(struct pipe_screen *screen,
+                       struct gl_extensions *extensions,
+                       const struct st_extension_format_mapping *mapping,
+                       unsigned num_mappings,
+                       enum pipe_texture_target target,
+                       unsigned bind_flags)
 {
-   struct pipe_screen *screen = st->pipe->screen;
-   GLboolean *extensions = (GLboolean *) &st->ctx->Extensions;
+   GLboolean *extension_table = (GLboolean *) extensions;
    unsigned i;
    int j;
    int num_formats = Elements(mapping->format);
@@ -371,10 +367,36 @@ static void init_format_extensions(struct st_context *st,
 
       /* Enable all extensions in the list. */
       for (j = 0; j < num_ext && mapping[i].extension_offset[j]; j++)
-         extensions[mapping[i].extension_offset[j]] = GL_TRUE;
+         extension_table[mapping[i].extension_offset[j]] = GL_TRUE;
    }
 }
 
+
+/**
+ * Given a list of formats and bind flags, return the maximum number
+ * of samples supported by any of those formats.
+ */
+static unsigned
+get_max_samples_for_formats(struct pipe_screen *screen,
+                            unsigned num_formats,
+                            enum pipe_format *formats,
+                            unsigned max_samples,
+                            unsigned bind)
+{
+   unsigned i, f;
+
+   for (i = max_samples; i > 0; --i) {
+      for (f = 0; f < num_formats; f++) {
+         if (screen->is_format_supported(screen, formats[f],
+                                         PIPE_TEXTURE_2D, i, bind)) {
+            return i;
+         }
+      }
+   }
+   return 0;
+}
+
+
 /**
  * Use pipe_screen::get_param() to query PIPE_CAP_ values to determine
  * which GL extensions are supported.
@@ -382,12 +404,15 @@ static void init_format_extensions(struct st_context *st,
  * features or can be built on top of other gallium features.
  * Some fine tuning may still be needed.
  */
-void st_init_extensions(struct st_context *st)
+void st_init_extensions(struct pipe_screen *screen,
+                        gl_api api,
+                        struct gl_constants *consts,
+                        struct gl_extensions *extensions,
+                        struct st_config_options *options,
+                        boolean has_lib_dxtc)
 {
-   struct pipe_screen *screen = st->pipe->screen;
-   struct gl_context *ctx = st->ctx;
    int i, glsl_feature_level;
-   GLboolean *extensions = (GLboolean *) &ctx->Extensions;
+   GLboolean *extension_table = (GLboolean *) extensions;
 
    static const struct st_extension_cap_mapping cap_mapping[] = {
       { o(ARB_base_instance),                PIPE_CAP_START_INSTANCE                   },
@@ -433,7 +458,9 @@ void st_init_extensions(struct st_context *st)
       { o(ARB_texture_multisample),          PIPE_CAP_TEXTURE_MULTISAMPLE              },
       { o(ARB_texture_query_lod),            PIPE_CAP_TEXTURE_QUERY_LOD                },
       { o(ARB_sample_shading),               PIPE_CAP_SAMPLE_SHADING                   },
-      { o(ARB_draw_indirect),                PIPE_CAP_DRAW_INDIRECT                    }
+      { o(ARB_draw_indirect),                PIPE_CAP_DRAW_INDIRECT                    },
+      { o(ARB_derivative_control),           PIPE_CAP_TGSI_FS_FINE_DERIVATIVE          },
+      { o(ARB_conditional_render_inverted),  PIPE_CAP_CONDITIONAL_RENDER_INVERTED      },
    };
 
    /* Required: render target and sampler support */
@@ -492,6 +519,12 @@ void st_init_extensions(struct st_context *st)
           PIPE_FORMAT_DXT3_RGBA,
           PIPE_FORMAT_DXT5_RGBA } },
 
+      { { o(ARB_texture_compression_bptc) },
+        { PIPE_FORMAT_BPTC_RGBA_UNORM,
+          PIPE_FORMAT_BPTC_SRGBA,
+          PIPE_FORMAT_BPTC_RGB_FLOAT,
+          PIPE_FORMAT_BPTC_RGB_UFLOAT } },
+
       { { o(EXT_texture_shared_exponent) },
         { PIPE_FORMAT_R9G9B9E5_FLOAT } },
 
@@ -513,7 +546,9 @@ void st_init_extensions(struct st_context *st)
         GL_TRUE }, /* at least one format must be supported */
 
       { { o(OES_compressed_ETC1_RGB8_texture) },
-        { PIPE_FORMAT_ETC1_RGB8 } },
+        { PIPE_FORMAT_ETC1_RGB8,
+          PIPE_FORMAT_R8G8B8A8_UNORM },
+        GL_TRUE }, /* at least one format must be supported */
 
       { { o(ARB_stencil_texturing) },
         { PIPE_FORMAT_X24S8_UINT,
@@ -547,256 +582,248 @@ void st_init_extensions(struct st_context *st)
    /*
     * Extensions that are supported by all Gallium drivers:
     */
-   ctx->Extensions.ARB_ES2_compatibility = GL_TRUE;
-   ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE;
-   ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE;
-   ctx->Extensions.ARB_explicit_uniform_location = GL_TRUE;
-   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
-   ctx->Extensions.ARB_fragment_program = GL_TRUE;
-   ctx->Extensions.ARB_fragment_shader = GL_TRUE;
-   ctx->Extensions.ARB_half_float_vertex = GL_TRUE;
-   ctx->Extensions.ARB_internalformat_query = GL_TRUE;
-   ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
-   ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
-   ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
-   ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
-   ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
-   ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
-   ctx->Extensions.ARB_vertex_program = GL_TRUE;
-   ctx->Extensions.ARB_vertex_shader = GL_TRUE;
-
-   ctx->Extensions.EXT_blend_color = GL_TRUE;
-   ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
-   ctx->Extensions.EXT_blend_minmax = GL_TRUE;
-   ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
-   ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
-   ctx->Extensions.EXT_point_parameters = GL_TRUE;
-   ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
-
-   ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
-   ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
-
-   ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
-
-   ctx->Extensions.MESA_pack_invert = GL_TRUE;
-
-   ctx->Extensions.NV_fog_distance = GL_TRUE;
-   ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
-   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
-   ctx->Extensions.NV_vdpau_interop = GL_TRUE;
-
-   ctx->Extensions.OES_EGL_image = GL_TRUE;
-   ctx->Extensions.OES_EGL_image_external = GL_TRUE;
-   ctx->Extensions.OES_draw_texture = GL_TRUE;
+   extensions->ARB_ES2_compatibility = GL_TRUE;
+   extensions->ARB_draw_elements_base_vertex = GL_TRUE;
+   extensions->ARB_explicit_attrib_location = GL_TRUE;
+   extensions->ARB_explicit_uniform_location = GL_TRUE;
+   extensions->ARB_fragment_coord_conventions = GL_TRUE;
+   extensions->ARB_fragment_program = GL_TRUE;
+   extensions->ARB_fragment_shader = GL_TRUE;
+   extensions->ARB_half_float_vertex = GL_TRUE;
+   extensions->ARB_internalformat_query = GL_TRUE;
+   extensions->ARB_map_buffer_range = GL_TRUE;
+   extensions->ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
+   extensions->ARB_texture_cube_map = GL_TRUE;
+   extensions->ARB_texture_env_combine = GL_TRUE;
+   extensions->ARB_texture_env_crossbar = GL_TRUE;
+   extensions->ARB_texture_env_dot3 = GL_TRUE;
+   extensions->ARB_vertex_program = GL_TRUE;
+   extensions->ARB_vertex_shader = GL_TRUE;
+
+   extensions->EXT_blend_color = GL_TRUE;
+   extensions->EXT_blend_func_separate = GL_TRUE;
+   extensions->EXT_blend_minmax = GL_TRUE;
+   extensions->EXT_gpu_program_parameters = GL_TRUE;
+   extensions->EXT_pixel_buffer_object = GL_TRUE;
+   extensions->EXT_point_parameters = GL_TRUE;
+   extensions->EXT_provoking_vertex = GL_TRUE;
+
+   extensions->EXT_texture_env_dot3 = GL_TRUE;
+   extensions->EXT_vertex_array_bgra = GL_TRUE;
+
+   extensions->ATI_texture_env_combine3 = GL_TRUE;
+
+   extensions->MESA_pack_invert = GL_TRUE;
+
+   extensions->NV_fog_distance = GL_TRUE;
+   extensions->NV_texture_env_combine4 = GL_TRUE;
+   extensions->NV_texture_rectangle = GL_TRUE;
+   extensions->NV_vdpau_interop = GL_TRUE;
+
+   extensions->OES_EGL_image = GL_TRUE;
+   extensions->OES_EGL_image_external = GL_TRUE;
+   extensions->OES_draw_texture = GL_TRUE;
 
    /* Expose the extensions which directly correspond to gallium caps. */
    for (i = 0; i < Elements(cap_mapping); i++) {
       if (screen->get_param(screen, cap_mapping[i].cap)) {
-         extensions[cap_mapping[i].extension_offset] = GL_TRUE;
+         extension_table[cap_mapping[i].extension_offset] = GL_TRUE;
       }
    }
 
    /* Expose the extensions which directly correspond to gallium formats. */
-   init_format_extensions(st, rendertarget_mapping,
+   init_format_extensions(screen, extensions, rendertarget_mapping,
                           Elements(rendertarget_mapping), PIPE_TEXTURE_2D,
                           PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW);
-   init_format_extensions(st, depthstencil_mapping,
+   init_format_extensions(screen, extensions, depthstencil_mapping,
                           Elements(depthstencil_mapping), PIPE_TEXTURE_2D,
                           PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW);
-   init_format_extensions(st, texture_mapping, Elements(texture_mapping),
-                          PIPE_TEXTURE_2D, PIPE_BIND_SAMPLER_VIEW);
-   init_format_extensions(st, vertex_mapping, Elements(vertex_mapping),
-                          PIPE_BUFFER, PIPE_BIND_VERTEX_BUFFER);
+   init_format_extensions(screen, extensions, texture_mapping,
+                          Elements(texture_mapping), PIPE_TEXTURE_2D,
+                          PIPE_BIND_SAMPLER_VIEW);
+   init_format_extensions(screen, extensions, vertex_mapping,
+                          Elements(vertex_mapping), PIPE_BUFFER,
+                          PIPE_BIND_VERTEX_BUFFER);
 
    /* Figure out GLSL support. */
    glsl_feature_level = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL);
 
-   ctx->Const.GLSLVersion = glsl_feature_level;
+   consts->GLSLVersion = glsl_feature_level;
    if (glsl_feature_level >= 330)
-      ctx->Const.GLSLVersion = 330;
+      consts->GLSLVersion = 330;
 
-   _mesa_override_glsl_version(st->ctx);
+   _mesa_override_glsl_version(consts);
 
-   if (st->options.force_glsl_version > 0 &&
-       st->options.force_glsl_version <= ctx->Const.GLSLVersion) {
-      ctx->Const.ForceGLSLVersion = st->options.force_glsl_version;
+   if (options->force_glsl_version > 0 &&
+       options->force_glsl_version <= consts->GLSLVersion) {
+      consts->ForceGLSLVersion = options->force_glsl_version;
    }
 
+   if (glsl_feature_level >= 400)
+      extensions->ARB_gpu_shader5 = GL_TRUE;
+
    /* This extension needs full OpenGL 3.2, but we don't know if that's
     * supported at this point. Only check the GLSL version. */
-   if (ctx->Const.GLSLVersion >= 150 &&
+   if (consts->GLSLVersion >= 150 &&
        screen->get_param(screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT)) {
-      ctx->Extensions.AMD_vertex_shader_layer = GL_TRUE;
+      extensions->AMD_vertex_shader_layer = GL_TRUE;
    }
 
-   if (ctx->Const.GLSLVersion >= 130) {
-      ctx->Const.NativeIntegers = GL_TRUE;
-      ctx->Const.MaxClipPlanes = 8;
+   if (consts->GLSLVersion >= 130) {
+      consts->NativeIntegers = GL_TRUE;
+      consts->MaxClipPlanes = 8;
 
       /* Extensions that either depend on GLSL 1.30 or are a subset thereof. */
-      ctx->Extensions.ARB_conservative_depth = GL_TRUE;
-      ctx->Extensions.ARB_shading_language_packing = GL_TRUE;
-      ctx->Extensions.OES_depth_texture_cube_map = GL_TRUE;
-      ctx->Extensions.ARB_shading_language_420pack = GL_TRUE;
-      ctx->Extensions.ARB_texture_query_levels = GL_TRUE;
-
-      if (!st->options.disable_shader_bit_encoding) {
-         ctx->Extensions.ARB_shader_bit_encoding = GL_TRUE;
+      extensions->ARB_conservative_depth = GL_TRUE;
+      extensions->ARB_shading_language_packing = GL_TRUE;
+      extensions->OES_depth_texture_cube_map = GL_TRUE;
+      extensions->ARB_shading_language_420pack = GL_TRUE;
+      extensions->ARB_texture_query_levels = GL_TRUE;
+
+      if (!options->disable_shader_bit_encoding) {
+         extensions->ARB_shader_bit_encoding = GL_TRUE;
       }
 
-      ctx->Extensions.EXT_shader_integer_mix = GL_TRUE;
+      extensions->EXT_shader_integer_mix = GL_TRUE;
    } else {
       /* Optional integer support for GLSL 1.2. */
       if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
                                    PIPE_SHADER_CAP_INTEGERS) &&
           screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
                                    PIPE_SHADER_CAP_INTEGERS)) {
-         ctx->Const.NativeIntegers = GL_TRUE;
+         consts->NativeIntegers = GL_TRUE;
 
-         ctx->Extensions.EXT_shader_integer_mix = GL_TRUE;
+         extensions->EXT_shader_integer_mix = GL_TRUE;
       }
    }
 
    /* Below are the cases which cannot be moved into tables easily. */
 
-   if (!ctx->Mesa_DXTn && !st->options.force_s3tc_enable) {
-      ctx->Extensions.EXT_texture_compression_s3tc = GL_FALSE;
-      ctx->Extensions.ANGLE_texture_compression_dxt = GL_FALSE;
+   if (!has_lib_dxtc && !options->force_s3tc_enable) {
+      extensions->EXT_texture_compression_s3tc = GL_FALSE;
+      extensions->ANGLE_texture_compression_dxt = GL_FALSE;
    }
 
    if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY,
                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
 #if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */
-      ctx->Extensions.ARB_geometry_shader4 = GL_TRUE;
+      extensions->ARB_geometry_shader4 = GL_TRUE;
 #endif
    }
 
-   ctx->Extensions.NV_primitive_restart = GL_TRUE;
+   extensions->NV_primitive_restart = GL_TRUE;
    if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) {
-      ctx->Const.PrimitiveRestartInSoftware = GL_TRUE;
+      consts->PrimitiveRestartInSoftware = GL_TRUE;
    }
 
    /* ARB_color_buffer_float. */
    if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
-      ctx->Extensions.ARB_color_buffer_float = GL_TRUE;
-
-      if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
-         st->clamp_vert_color_in_shader = TRUE;
-      }
-
-      if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) {
-         st->clamp_frag_color_in_shader = TRUE;
-      }
-
-      /* For drivers which cannot do color clamping, it's better to just
-       * disable ARB_color_buffer_float in the core profile, because
-       * the clamping is deprecated there anyway. */
-      if (ctx->API == API_OPENGL_CORE &&
-          (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) {
-         st->clamp_vert_color_in_shader = GL_FALSE;
-         st->clamp_frag_color_in_shader = GL_FALSE;
-         ctx->Extensions.ARB_color_buffer_float = GL_FALSE;
-      }
+      extensions->ARB_color_buffer_float = GL_TRUE;
    }
 
    if (screen->fence_finish) {
-      ctx->Extensions.ARB_sync = GL_TRUE;
+      extensions->ARB_sync = GL_TRUE;
    }
 
    /* Maximum sample count. */
-   for (i = 16; i > 0; --i) {
-      enum pipe_format pformat = st_choose_format(st, GL_RGBA,
-                                                  GL_NONE, GL_NONE,
-                                                  PIPE_TEXTURE_2D, i,
-                                                  PIPE_BIND_RENDER_TARGET, FALSE);
-      if (pformat != PIPE_FORMAT_NONE) {
-         ctx->Const.MaxSamples = i;
-         ctx->Const.MaxColorTextureSamples = i;
-         break;
-      }
+   {
+      enum pipe_format color_formats[] = {
+         PIPE_FORMAT_R8G8B8A8_UNORM,
+         PIPE_FORMAT_B8G8R8A8_UNORM,
+         PIPE_FORMAT_A8R8G8B8_UNORM,
+         PIPE_FORMAT_A8B8G8R8_UNORM,
+      };
+      enum pipe_format depth_formats[] = {
+         PIPE_FORMAT_Z16_UNORM,
+         PIPE_FORMAT_Z24X8_UNORM,
+         PIPE_FORMAT_X8Z24_UNORM,
+         PIPE_FORMAT_Z32_UNORM,
+         PIPE_FORMAT_Z32_FLOAT
+      };
+      enum pipe_format int_formats[] = {
+         PIPE_FORMAT_R8G8B8A8_SINT
+      };
+
+      consts->MaxSamples =
+         get_max_samples_for_formats(screen, Elements(color_formats),
+                                     color_formats, 16,
+                                     PIPE_BIND_RENDER_TARGET);
+
+      consts->MaxColorTextureSamples =
+         get_max_samples_for_formats(screen, Elements(color_formats),
+                                     color_formats, consts->MaxSamples,
+                                     PIPE_BIND_SAMPLER_VIEW);
+
+      consts->MaxDepthTextureSamples =
+         get_max_samples_for_formats(screen, Elements(depth_formats),
+                                     depth_formats, consts->MaxSamples,
+                                     PIPE_BIND_SAMPLER_VIEW);
+
+      consts->MaxIntegerSamples =
+         get_max_samples_for_formats(screen, Elements(int_formats),
+                                     int_formats, consts->MaxSamples,
+                                     PIPE_BIND_SAMPLER_VIEW);
    }
-   for (i = ctx->Const.MaxSamples; i > 0; --i) {
-      enum pipe_format pformat = st_choose_format(st, GL_DEPTH_STENCIL,
-                                                  GL_NONE, GL_NONE,
-                                                  PIPE_TEXTURE_2D, i,
-                                                  PIPE_BIND_DEPTH_STENCIL, FALSE);
-      if (pformat != PIPE_FORMAT_NONE) {
-         ctx->Const.MaxDepthTextureSamples = i;
-         break;
-      }
-   }
-   for (i = ctx->Const.MaxSamples; i > 0; --i) {
-      enum pipe_format pformat = st_choose_format(st, GL_RGBA_INTEGER,
-                                                  GL_NONE, GL_NONE,
-                                                  PIPE_TEXTURE_2D, i,
-                                                  PIPE_BIND_RENDER_TARGET, FALSE);
-      if (pformat != PIPE_FORMAT_NONE) {
-         ctx->Const.MaxIntegerSamples = i;
-         break;
-      }
-   }
-   if (ctx->Const.MaxSamples == 1) {
+   if (consts->MaxSamples == 1) {
       /* one sample doesn't really make sense */
-      ctx->Const.MaxSamples = 0;
+      consts->MaxSamples = 0;
    }
-   else if (ctx->Const.MaxSamples >= 2) {
-      ctx->Extensions.EXT_framebuffer_multisample = GL_TRUE;
-      ctx->Extensions.EXT_framebuffer_multisample_blit_scaled = GL_TRUE;
+   else if (consts->MaxSamples >= 2) {
+      extensions->EXT_framebuffer_multisample = GL_TRUE;
+      extensions->EXT_framebuffer_multisample_blit_scaled = GL_TRUE;
    }
 
-   if (ctx->Const.MaxSamples == 0 && screen->get_param(screen, PIPE_CAP_FAKE_SW_MSAA)) {
-	ctx->Const.FakeSWMSAA = GL_TRUE;
-        ctx->Extensions.EXT_framebuffer_multisample = GL_TRUE;
-        ctx->Extensions.EXT_framebuffer_multisample_blit_scaled = GL_TRUE;
-        ctx->Extensions.ARB_texture_multisample = GL_TRUE;
+   if (consts->MaxSamples == 0 && screen->get_param(screen, PIPE_CAP_FAKE_SW_MSAA)) {
+	consts->FakeSWMSAA = GL_TRUE;
+        extensions->EXT_framebuffer_multisample = GL_TRUE;
+        extensions->EXT_framebuffer_multisample_blit_scaled = GL_TRUE;
+        extensions->ARB_texture_multisample = GL_TRUE;
    }
 
-   if (ctx->Const.MaxDualSourceDrawBuffers > 0 &&
-       !st->options.disable_blend_func_extended)
-      ctx->Extensions.ARB_blend_func_extended = GL_TRUE;
+   if (consts->MaxDualSourceDrawBuffers > 0 &&
+       !options->disable_blend_func_extended)
+      extensions->ARB_blend_func_extended = GL_TRUE;
 
-   st->has_time_elapsed =
-      screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
-
-   if (st->has_time_elapsed ||
-       ctx->Extensions.ARB_timer_query) {
-      ctx->Extensions.EXT_timer_query = GL_TRUE;
+   if (screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED) ||
+       extensions->ARB_timer_query) {
+      extensions->EXT_timer_query = GL_TRUE;
    }
 
-   if (ctx->Extensions.ARB_transform_feedback2 &&
-       ctx->Extensions.ARB_draw_instanced) {
-      ctx->Extensions.ARB_transform_feedback_instanced = GL_TRUE;
+   if (extensions->ARB_transform_feedback2 &&
+       extensions->ARB_draw_instanced) {
+      extensions->ARB_transform_feedback_instanced = GL_TRUE;
    }
-   if (st->options.force_glsl_extensions_warn)
-      ctx->Const.ForceGLSLExtensionsWarn = 1;
+   if (options->force_glsl_extensions_warn)
+      consts->ForceGLSLExtensionsWarn = 1;
 
-   if (st->options.disable_glsl_line_continuations)
-      ctx->Const.DisableGLSLLineContinuations = 1;
+   if (options->disable_glsl_line_continuations)
+      consts->DisableGLSLLineContinuations = 1;
 
-   if (st->options.allow_glsl_extension_directive_midshader)
-      ctx->Const.AllowGLSLExtensionDirectiveMidShader = GL_TRUE;
+   if (options->allow_glsl_extension_directive_midshader)
+      consts->AllowGLSLExtensionDirectiveMidShader = GL_TRUE;
 
-   ctx->Const.MinMapBufferAlignment =
+   consts->MinMapBufferAlignment =
       screen->get_param(screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT);
 
    if (screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
-      ctx->Extensions.ARB_texture_buffer_object = GL_TRUE;
+      extensions->ARB_texture_buffer_object = GL_TRUE;
 
-      ctx->Const.MaxTextureBufferSize =
+      consts->MaxTextureBufferSize =
          _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE),
               (1u << 31) - 1);
-      ctx->Const.TextureBufferOffsetAlignment =
+      consts->TextureBufferOffsetAlignment =
          screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT);
 
-      if (ctx->Const.TextureBufferOffsetAlignment)
-         ctx->Extensions.ARB_texture_buffer_range = GL_TRUE;
+      if (consts->TextureBufferOffsetAlignment)
+         extensions->ARB_texture_buffer_range = GL_TRUE;
 
-      init_format_extensions(st, tbo_rgb32, Elements(tbo_rgb32),
-                             PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW);
+      init_format_extensions(screen, extensions, tbo_rgb32,
+                             Elements(tbo_rgb32), PIPE_BUFFER,
+                             PIPE_BIND_SAMPLER_VIEW);
    }
 
    if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES)) {
-      ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
+      extensions->ARB_framebuffer_object = GL_TRUE;
    }
 
    /* Unpacking a varying in the fragment shader costs 1 texture indirection.
@@ -809,21 +836,49 @@ void st_init_extensions(struct st_context *st)
       /* We can't disable varying packing if transform feedback is available,
        * because transform feedback code assumes a packed varying layout.
        */
-      if (!ctx->Extensions.EXT_transform_feedback)
-         ctx->Const.DisableVaryingPacking = GL_TRUE;
+      if (!extensions->EXT_transform_feedback)
+         consts->DisableVaryingPacking = GL_TRUE;
    }
 
-   if (ctx->API == API_OPENGL_CORE) {
-      ctx->Const.MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS);
-      if (ctx->Const.MaxViewports >= 16) {
-         ctx->Const.ViewportBounds.Min = -16384.0;
-         ctx->Const.ViewportBounds.Max = 16384.0;
-         ctx->Extensions.ARB_viewport_array = GL_TRUE;
-         ctx->Extensions.ARB_fragment_layer_viewport = GL_TRUE;
-         if (ctx->Extensions.AMD_vertex_shader_layer)
-            ctx->Extensions.AMD_vertex_shader_viewport_index = GL_TRUE;
+   if (api == API_OPENGL_CORE) {
+      consts->MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS);
+      if (consts->MaxViewports >= 16) {
+         consts->ViewportBounds.Min = -16384.0;
+         consts->ViewportBounds.Max = 16384.0;
+         extensions->ARB_viewport_array = GL_TRUE;
+         extensions->ARB_fragment_layer_viewport = GL_TRUE;
+         if (extensions->AMD_vertex_shader_layer)
+            extensions->AMD_vertex_shader_viewport_index = GL_TRUE;
       }
    }
-   if (ctx->Const.MaxProgramTextureGatherComponents > 0)
-      ctx->Extensions.ARB_texture_gather = GL_TRUE;
+   if (consts->MaxProgramTextureGatherComponents > 0)
+      extensions->ARB_texture_gather = GL_TRUE;
+
+   /* GL_ARB_ES3_compatibility.
+    *
+    * Assume that ES3 is supported if GLSL 3.30 is supported.
+    * (OpenGL 3.3 is a requirement for that extension.)
+    */
+   if (consts->GLSLVersion >= 330 &&
+       /* Requirements for ETC2 emulation. */
+       screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_UNORM,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW) &&
+       screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW) &&
+       screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW) &&
+       screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW) &&
+       screen->is_format_supported(screen, PIPE_FORMAT_R16_SNORM,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW) &&
+       screen->is_format_supported(screen, PIPE_FORMAT_R16G16_SNORM,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_SAMPLER_VIEW)) {
+      extensions->ARB_ES3_compatibility = GL_TRUE;
+   }
 }
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.h b/mesalib/src/mesa/state_tracker/st_extensions.h
index d098ed074..8d2724d67 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.h
+++ b/mesalib/src/mesa/state_tracker/st_extensions.h
@@ -31,10 +31,18 @@
 
 
 struct st_context;
-
-extern void st_init_limits(struct st_context *st);
-
-extern void st_init_extensions(struct st_context *st);
+struct pipe_screen;
+
+extern void st_init_limits(struct pipe_screen *screen,
+                           struct gl_constants *c,
+                           struct gl_extensions *extensions);
+
+extern void st_init_extensions(struct pipe_screen *screen,
+                               gl_api api,
+                               struct gl_constants *consts,
+                               struct gl_extensions *extensions,
+                               struct st_config_options *options,
+                               boolean has_lib_dxtc);
 
 
 #endif /* ST_EXTENSIONS_H */
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index 409079bd4..b5e03b0f8 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -54,7 +54,7 @@
  * Translate Mesa format to Gallium format.
  */
 enum pipe_format
-st_mesa_format_to_pipe_format(mesa_format mesaFormat)
+st_mesa_format_to_pipe_format(struct st_context *st, mesa_format mesaFormat)
 {
    switch (mesaFormat) {
    case MESA_FORMAT_A8B8G8R8_UNORM:
@@ -323,8 +323,19 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat)
    case MESA_FORMAT_LA_LATC2_SNORM:
       return PIPE_FORMAT_LATC2_SNORM;
 
+   /* The destination RGBA format mustn't be changed, because it's also
+    * a destination format of the unpack/decompression function. */
    case MESA_FORMAT_ETC1_RGB8:
-      return PIPE_FORMAT_ETC1_RGB8;
+      return st->has_etc1 ? PIPE_FORMAT_ETC1_RGB8 : PIPE_FORMAT_R8G8B8A8_UNORM;
+
+   case MESA_FORMAT_BPTC_RGBA_UNORM:
+      return PIPE_FORMAT_BPTC_RGBA_UNORM;
+   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+      return PIPE_FORMAT_BPTC_SRGBA;
+   case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+      return PIPE_FORMAT_BPTC_RGB_FLOAT;
+   case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+      return PIPE_FORMAT_BPTC_RGB_UFLOAT;
 
    /* signed normalized formats */
    case MESA_FORMAT_R_SNORM8:
@@ -402,6 +413,26 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat)
    case MESA_FORMAT_B8G8R8X8_SRGB:
       return PIPE_FORMAT_B8G8R8X8_SRGB;
 
+   /* ETC2 formats are emulated as uncompressed ones.
+    * The destination formats mustn't be changed, because they are also
+    * destination formats of the unpack/decompression function. */
+   case MESA_FORMAT_ETC2_RGB8:
+   case MESA_FORMAT_ETC2_RGBA8_EAC:
+   case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
+      return PIPE_FORMAT_R8G8B8A8_UNORM;
+   case MESA_FORMAT_ETC2_SRGB8:
+   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
+   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+      return PIPE_FORMAT_B8G8R8A8_SRGB;
+   case MESA_FORMAT_ETC2_R11_EAC:
+      return PIPE_FORMAT_R16_UNORM;
+   case MESA_FORMAT_ETC2_RG11_EAC:
+      return PIPE_FORMAT_R16G16_UNORM;
+   case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
+      return PIPE_FORMAT_R16_SNORM;
+   case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
+      return PIPE_FORMAT_R16G16_SNORM;
+
    default:
       return PIPE_FORMAT_NONE;
    }
@@ -685,6 +716,15 @@ st_pipe_format_to_mesa_format(enum pipe_format format)
    case PIPE_FORMAT_ETC1_RGB8:
       return MESA_FORMAT_ETC1_RGB8;
 
+   case PIPE_FORMAT_BPTC_RGBA_UNORM:
+      return MESA_FORMAT_BPTC_RGBA_UNORM;
+   case PIPE_FORMAT_BPTC_SRGBA:
+      return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
+   case PIPE_FORMAT_BPTC_RGB_FLOAT:
+      return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT;
+   case PIPE_FORMAT_BPTC_RGB_UFLOAT:
+      return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT;
+
    /* signed normalized formats */
    case PIPE_FORMAT_R8_SNORM:
       return MESA_FORMAT_R_SNORM8;
@@ -775,13 +815,21 @@ st_pipe_format_to_mesa_format(enum pipe_format format)
  * Mesa formats to Gallium formats and back again.
  */
 static void
-test_format_conversion(void)
+test_format_conversion(struct st_context *st)
 {
    GLuint i;
 
    /* test all Mesa formats */
    for (i = 1; i < MESA_FORMAT_COUNT; i++) {
-      enum pipe_format pf = st_mesa_format_to_pipe_format(i);
+      enum pipe_format pf;
+
+      /* ETC formats are translated differently, skip them. */
+      if (_mesa_is_format_etc2(i))
+         continue;
+      if (i == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)
+         continue;
+
+      pf = st_mesa_format_to_pipe_format(st, i);
       if (pf != PIPE_FORMAT_NONE) {
          mesa_format mf = st_pipe_format_to_mesa_format(pf);
          assert(mf == i);
@@ -791,8 +839,13 @@ test_format_conversion(void)
    /* Test all Gallium formats */
    for (i = 1; i < PIPE_FORMAT_COUNT; i++) {
       mesa_format mf = st_pipe_format_to_mesa_format(i);
+
+      /* ETC formats are translated differently, skip them. */
+      if (i == PIPE_FORMAT_ETC1_RGB8 && !st->has_etc1)
+         continue;
+
       if (mf != MESA_FORMAT_NONE) {
-         enum pipe_format pf = st_mesa_format_to_pipe_format(mf);
+         enum pipe_format pf = st_mesa_format_to_pipe_format(st, mf);
          assert(pf == i);
       }
    }
@@ -1238,6 +1291,24 @@ static const struct format_mapping format_map[] = {
       { PIPE_FORMAT_ETC1_RGB8, 0 }
    },
 
+   /* BPTC */
+   {
+      { GL_COMPRESSED_RGBA_BPTC_UNORM, 0 },
+      { PIPE_FORMAT_BPTC_RGBA_UNORM, 0 },
+   },
+   {
+      { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, 0 },
+      { PIPE_FORMAT_BPTC_SRGBA, 0 },
+   },
+   {
+      { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, 0 },
+      { PIPE_FORMAT_BPTC_RGB_FLOAT, 0 },
+   },
+   {
+      { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 0 },
+      { PIPE_FORMAT_BPTC_RGB_UFLOAT, 0 },
+   },
+
    /* signed/unsigned integer formats.
     */
    {
@@ -1680,7 +1751,7 @@ st_choose_format(struct st_context *st, GLenum internalFormat,
    {
       static boolean firstCall = TRUE;
       if (firstCall) {
-         test_format_conversion();
+         test_format_conversion(st);
          firstCall = FALSE;
       }
    }
@@ -1746,9 +1817,10 @@ st_choose_renderbuffer_format(struct st_context *st,
  * If no format is supported, return PIPE_FORMAT_NONE.
  */
 enum pipe_format
-st_choose_matching_format(struct pipe_screen *screen, unsigned bind,
+st_choose_matching_format(struct st_context *st, unsigned bind,
 			  GLenum format, GLenum type, GLboolean swapBytes)
 {
+   struct pipe_screen *screen = st->pipe->screen;
    mesa_format mesa_format;
 
    for (mesa_format = 1; mesa_format < MESA_FORMAT_COUNT; mesa_format++) {
@@ -1764,7 +1836,8 @@ st_choose_matching_format(struct pipe_screen *screen, unsigned bind,
 
       if (_mesa_format_matches_format_and_type(mesa_format, format, type,
                                                swapBytes)) {
-         enum pipe_format format = st_mesa_format_to_pipe_format(mesa_format);
+         enum pipe_format format =
+            st_mesa_format_to_pipe_format(st, mesa_format);
 
          if (format &&
              screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0,
@@ -1834,16 +1907,14 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLenum target,
        * with the "format".
        */
       if (iformat == baseFormat && iformat == basePackFormat) {
-         pFormat = st_choose_matching_format(st->pipe->screen, bindings,
-                                             format, type,
+         pFormat = st_choose_matching_format(st, bindings, format, type,
                                              ctx->Unpack.SwapBytes);
 
          if (pFormat != PIPE_FORMAT_NONE)
             return st_pipe_format_to_mesa_format(pFormat);
 
          /* try choosing format again, this time without render target bindings */
-         pFormat = st_choose_matching_format(st->pipe->screen,
-                                             PIPE_BIND_SAMPLER_VIEW,
+         pFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
                                              format, type,
                                              ctx->Unpack.SwapBytes);
          if (pFormat != PIPE_FORMAT_NONE)
diff --git a/mesalib/src/mesa/state_tracker/st_format.h b/mesalib/src/mesa/state_tracker/st_format.h
index ce1e2306d..90e00e8eb 100644
--- a/mesalib/src/mesa/state_tracker/st_format.h
+++ b/mesalib/src/mesa/state_tracker/st_format.h
@@ -41,7 +41,7 @@ struct pipe_screen;
 
 
 extern enum pipe_format
-st_mesa_format_to_pipe_format(mesa_format mesaFormat);
+st_mesa_format_to_pipe_format(struct st_context *st, mesa_format mesaFormat);
 
 extern mesa_format
 st_pipe_format_to_mesa_format(enum pipe_format pipeFormat);
@@ -58,7 +58,7 @@ st_choose_renderbuffer_format(struct st_context *st,
                               GLenum internalFormat, unsigned sample_count);
 
 extern enum pipe_format
-st_choose_matching_format(struct pipe_screen *screen, unsigned bind,
+st_choose_matching_format(struct st_context *st, unsigned bind,
 			  GLenum format, GLenum type, GLboolean swapBytes);
 
 extern mesa_format
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 0290553c6..84bdc4f06 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -245,7 +245,8 @@ public:
    ir_instruction *ir;
    GLboolean cond_update;
    bool saturate;
-   int sampler; /**< sampler index */
+   st_src_reg sampler; /**< sampler register */
+   int sampler_array_size; /**< 1-based size of sampler array, 1 if not array */
    int tex_target; /**< One of TEXTURE_*_INDEX */
    GLboolean tex_shadow;
 
@@ -476,6 +477,7 @@ static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_T
 
 static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 0);
 static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 1);
+static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 2);
 
 static void
 fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
@@ -1460,9 +1462,15 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       break;
 
    case ir_unop_dFdx:
+   case ir_unop_dFdx_coarse:
       emit(ir, TGSI_OPCODE_DDX, result_dst, op[0]);
       break;
+   case ir_unop_dFdx_fine:
+      emit(ir, TGSI_OPCODE_DDX_FINE, result_dst, op[0]);
+      break;
    case ir_unop_dFdy:
+   case ir_unop_dFdy_coarse:
+   case ir_unop_dFdy_fine:
    {
       /* The X component contains 1 or -1 depending on whether the framebuffer
        * is a FBO or the window system buffer, respectively.
@@ -1483,7 +1491,8 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       st_src_reg temp = get_temp(glsl_type::vec4_type);
 
       emit(ir, TGSI_OPCODE_MUL, st_dst_reg(temp), transform_y, op[0]);
-      emit(ir, TGSI_OPCODE_DDY, result_dst, temp);
+      emit(ir, ir->operation == ir_unop_dFdy_fine ?
+           TGSI_OPCODE_DDY_FINE : TGSI_OPCODE_DDY, result_dst, temp);
       break;
    }
 
@@ -2799,6 +2808,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
    glsl_to_tgsi_instruction *inst = NULL;
    unsigned opcode = TGSI_OPCODE_NOP;
    const glsl_type *sampler_type = ir->sampler->type;
+   ir_rvalue *sampler_index =
+      _mesa_get_sampler_array_nonconst_index(ir->sampler);
    bool is_cube_array = false;
    unsigned i;
 
@@ -3016,6 +3027,11 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
       coord_dst.writemask = WRITEMASK_XYZW;
    }
 
+   if (sampler_index) {
+      sampler_index->accept(this);
+      emit_arl(ir, sampler_reladdr, this->result);
+   }
+
    if (opcode == TGSI_OPCODE_TXD)
       inst = emit(ir, opcode, result_dst, coord, dx, dy);
    else if (opcode == TGSI_OPCODE_TXQ) {
@@ -3045,9 +3061,17 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
    if (ir->shadow_comparitor)
       inst->tex_shadow = GL_TRUE;
 
-   inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler,
-        					   this->shader_program,
-        					   this->prog);
+   inst->sampler.index = _mesa_get_sampler_uniform_value(ir->sampler,
+                                                         this->shader_program,
+                                                         this->prog);
+   if (sampler_index) {
+      inst->sampler.reladdr = ralloc(mem_ctx, st_src_reg);
+      memcpy(inst->sampler.reladdr, &sampler_reladdr, sizeof(sampler_reladdr));
+      inst->sampler_array_size =
+         ir->sampler->as_dereference_array()->array->type->array_size();
+   } else {
+      inst->sampler_array_size = 1;
+   }
 
    if (ir->offset) {
       for (i = 0; i < MAX_GLSL_TEXTURE_OFFSET && offset[i].file != PROGRAM_UNDEFINED; i++)
@@ -3215,10 +3239,12 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog)
 
    foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) {
       if (is_tex_instruction(inst->op)) {
-         v->samplers_used |= 1 << inst->sampler;
+         for (int i = 0; i < inst->sampler_array_size; i++) {
+            v->samplers_used |= 1 << (inst->sampler.index + i);
 
-         if (inst->tex_shadow) {
-            prog->ShadowSamplers |= 1 << inst->sampler;
+            if (inst->tex_shadow) {
+               prog->ShadowSamplers |= 1 << (inst->sampler.index + i);
+            }
          }
       }
    }
@@ -3952,7 +3978,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
    src0 = v->get_temp(glsl_type::vec4_type);
    dst0 = st_dst_reg(src0);
    inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
-   inst->sampler = 0;
+   inst->sampler_array_size = 1;
    inst->tex_target = TEXTURE_2D_INDEX;
 
    prog->InputsRead |= VARYING_BIT_TEX0;
@@ -3991,14 +4017,16 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
       /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
       temp_dst.writemask = WRITEMASK_XY; /* write R,G */
       inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
-      inst->sampler = 1;
+      inst->sampler.index = 1;
+      inst->sampler_array_size = 1;
       inst->tex_target = TEXTURE_2D_INDEX;
 
       /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
       src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
       temp_dst.writemask = WRITEMASK_ZW; /* write B,A */
       inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
-      inst->sampler = 1;
+      inst->sampler.index = 1;
+      inst->sampler_array_size = 1;
       inst->tex_target = TEXTURE_2D_INDEX;
 
       prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */
@@ -4079,7 +4107,8 @@ get_bitmap_visitor(struct st_fragment_program *fp,
    src0 = v->get_temp(glsl_type::vec4_type);
    dst0 = st_dst_reg(src0);
    inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
-   inst->sampler = samplerIndex;
+   inst->sampler.index = samplerIndex;
+   inst->sampler_array_size = 1;
    inst->tex_target = TEXTURE_2D_INDEX;
 
    prog->InputsRead |= VARYING_BIT_TEX0;
@@ -4135,7 +4164,7 @@ struct st_translate {
    struct ureg_src *immediates;
    struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
    struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
-   struct ureg_dst address[2];
+   struct ureg_dst address[3];
    struct ureg_src samplers[PIPE_MAX_SAMPLERS];
    struct ureg_src systemValues[SYSTEM_VALUE_MAX];
    struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET];
@@ -4546,7 +4575,11 @@ compile_tgsi_instruction(struct st_translate *t,
    case TGSI_OPCODE_TXL2:
    case TGSI_OPCODE_TG4:
    case TGSI_OPCODE_LODQ:
-      src[num_src++] = t->samplers[inst->sampler];
+      src[num_src] = t->samplers[inst->sampler.index];
+      if (inst->sampler.reladdr)
+         src[num_src] =
+            ureg_src_indirect(src[num_src], ureg_src(t->address[2]));
+      num_src++;
       for (i = 0; i < inst->tex_offset_num_offset; i++) {
          texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i], i);
       }
@@ -4977,10 +5010,9 @@ st_translate_program(
    /* Declare address register.
     */
    if (program->num_address_regs > 0) {
-      assert(program->num_address_regs <= 2);
-      t->address[0] = ureg_DECL_address(ureg);
-      if (program->num_address_regs == 2)
-         t->address[1] = ureg_DECL_address(ureg);
+      assert(program->num_address_regs <= 3);
+      for (int i = 0; i < program->num_address_regs; i++)
+         t->address[i] = ureg_DECL_address(ureg);
    }
 
    /* Declare misc input registers
@@ -5176,7 +5208,7 @@ get_mesa_program(struct gl_context *ctx,
    GLenum target = _mesa_shader_stage_to_program(shader->Stage);
    bool progress;
    struct gl_shader_compiler_options *options =
-         &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)];
+         &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)];
    struct pipe_screen *pscreen = ctx->st->pipe->screen;
    unsigned ptarget = shader_stage_to_ptarget(shader->Stage);
 
@@ -5365,7 +5397,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       bool progress;
       exec_list *ir = prog->_LinkedShaders[i]->ir;
       const struct gl_shader_compiler_options *options =
-            &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)];
+            &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)];
 
       /* If there are forms of indirect addressing that the driver
        * cannot handle, perform the lowering pass.
diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c
index 706af7fd1..7bc33268e 100644
--- a/mesalib/src/mesa/state_tracker/st_manager.c
+++ b/mesalib/src/mesa/state_tracker/st_manager.c
@@ -26,6 +26,7 @@
  */
 
 #include "main/mtypes.h"
+#include "main/extensions.h"
 #include "main/context.h"
 #include "main/texobj.h"
 #include "main/teximage.h"
@@ -38,6 +39,7 @@
 #include "st_texture.h"
 
 #include "st_context.h"
+#include "st_extensions.h"
 #include "st_format.h"
 #include "st_cb_fbo.h"
 #include "st_cb_flush.h"
@@ -910,6 +912,41 @@ st_manager_add_color_renderbuffer(struct st_context *st,
    return TRUE;
 }
 
+static unsigned get_version(struct pipe_screen *screen,
+                            struct st_config_options *options, gl_api api)
+{
+   struct gl_constants consts = {0};
+   struct gl_extensions extensions = {0};
+   GLuint version;
+
+   if ((api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) &&
+       _mesa_override_gl_version_contextless(&consts, &api, &version)) {
+      return version;
+   }
+
+   _mesa_init_constants(&consts, api);
+   _mesa_init_extensions(&extensions);
+
+   st_init_limits(screen, &consts, &extensions);
+   st_init_extensions(screen, api, &consts, &extensions, options, GL_TRUE);
+
+   return _mesa_get_version(&extensions, &consts, api);
+}
+
+static void
+st_api_query_versions(struct st_api *stapi, struct st_manager *sm,
+                      struct st_config_options *options,
+                      int *gl_core_version,
+                      int *gl_compat_version,
+                      int *gl_es1_version,
+                      int *gl_es2_version)
+{
+   *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE);
+   *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT);
+   *gl_es1_version = get_version(sm->screen, options, API_OPENGLES);
+   *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2);
+}
+
 static const struct st_api st_gl_api = {
    "Mesa " PACKAGE_VERSION,
    ST_API_OPENGL,
@@ -920,6 +957,7 @@ static const struct st_api st_gl_api = {
    0,
    ST_API_FEATURE_MS_VISUALS_MASK,
    st_api_destroy,
+   st_api_query_versions,
    st_api_get_proc_address,
    st_api_create_context,
    st_api_make_current,
diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c
index c14882142..af9b7675f 100644
--- a/mesalib/src/mesa/state_tracker/st_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_texture.c
@@ -197,7 +197,8 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture,
  * Check if a texture image can be pulled into a unified mipmap texture.
  */
 GLboolean
-st_texture_match_image(const struct pipe_resource *pt,
+st_texture_match_image(struct st_context *st,
+                       const struct pipe_resource *pt,
                        const struct gl_texture_image *image)
 {
    GLuint ptWidth, ptHeight, ptDepth, ptLayers;
@@ -209,7 +210,7 @@ st_texture_match_image(const struct pipe_resource *pt,
 
    /* Check if this image's format matches the established texture's format.
     */
-   if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
+   if (st_mesa_format_to_pipe_format(st, image->TexFormat) != pt->format)
       return GL_FALSE;
 
    st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
@@ -269,14 +270,15 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
          unsigned new_size = z + 1;
 
          stImage->transfer = realloc(stImage->transfer,
-                                     new_size * sizeof(void*));
+                     new_size * sizeof(struct st_texture_image_transfer));
          memset(&stImage->transfer[stImage->num_transfers], 0,
-               (new_size - stImage->num_transfers) * sizeof(void*));
+                (new_size - stImage->num_transfers) *
+                sizeof(struct st_texture_image_transfer));
          stImage->num_transfers = new_size;
       }
 
-      assert(!stImage->transfer[z]);
-      stImage->transfer[z] = *transfer;
+      assert(!stImage->transfer[z].transfer);
+      stImage->transfer[z].transfer = *transfer;
    }
    return map;
 }
@@ -288,7 +290,7 @@ st_texture_image_unmap(struct st_context *st,
 {
    struct pipe_context *pipe = st->pipe;
    struct pipe_transfer **transfer =
-      &stImage->transfer[slice + stImage->base.Face];
+      &stImage->transfer[slice + stImage->base.Face].transfer;
 
    DBG("%s\n", __FUNCTION__);
 
diff --git a/mesalib/src/mesa/state_tracker/st_texture.h b/mesalib/src/mesa/state_tracker/st_texture.h
index affb56812..ce1cf8b0a 100644
--- a/mesalib/src/mesa/state_tracker/st_texture.h
+++ b/mesalib/src/mesa/state_tracker/st_texture.h
@@ -38,6 +38,16 @@
 struct pipe_resource;
 
 
+struct st_texture_image_transfer {
+   struct pipe_transfer *transfer;
+
+   /* For ETC fallback. */
+   GLubyte *temp_data; /**< Temporary ETC texture storage. */
+   unsigned temp_stride; /**< Stride of the ETC texture storage. */
+   GLubyte *map; /**< Saved map pointer of the uncompressed transfer. */
+};
+
+
 /**
  * Subclass of gl_texure_image.
  */
@@ -59,7 +69,7 @@ struct st_texture_image
    /* List of transfers, allocated on demand.
     * transfer[layer] is a mapping for that layer.
     */
-   struct pipe_transfer **transfer;
+   struct st_texture_image_transfer *transfer;
    unsigned num_transfers;
 };
 
@@ -189,7 +199,8 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture,
 /* Check if an image fits into an existing texture object.
  */
 extern GLboolean
-st_texture_match_image(const struct pipe_resource *pt,
+st_texture_match_image(struct st_context *st,
+                       const struct pipe_resource *pt,
                        const struct gl_texture_image *image);
 
 /* Return a pointer to an image within a texture.  Return image stride as
diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c
index aef023217..38d71caa3 100644
--- a/mesalib/src/mesa/swrast/s_texfetch.c
+++ b/mesalib/src/mesa/swrast/s_texfetch.c
@@ -512,6 +512,30 @@ texfetch_funcs[] =
       fetch_compressed,
       fetch_compressed,
       fetch_compressed
+   },
+   {
+      MESA_FORMAT_BPTC_RGBA_UNORM,
+      fetch_compressed,
+      fetch_compressed,
+      fetch_compressed
+   },
+   {
+      MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM,
+      fetch_compressed,
+      fetch_compressed,
+      fetch_compressed
+   },
+   {
+      MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT,
+      fetch_compressed,
+      fetch_compressed,
+      fetch_compressed
+   },
+   {
+      MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT,
+      fetch_compressed,
+      fetch_compressed,
+      fetch_compressed
    }
 };
 
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index 9c161ccca..3f7058da1 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -1890,6 +1890,12 @@ _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
    vbo_exec_DrawArrays(mode, first, count);
 }
 
+void GLAPIENTRY
+_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+                          GLsizei primcount)
+{
+   vbo_exec_DrawArraysInstanced(mode, first, count, primcount);
+}
 
 void GLAPIENTRY
 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
-- 
cgit v1.2.3