mesa: Add flush_vertices to _mesa_bind_vertex_buffer.
[mesa.git] / src / mesa / drivers / common / meta.c
index 798639f7069c0bbd5c78ee023e7a1b6d256d7881..830d82ad49b56f25d0b4d3edc8c41ec071baafb4 100644 (file)
@@ -48,6 +48,7 @@
 #include "main/feedback.h"
 #include "main/formats.h"
 #include "main/format_unpack.h"
+#include "main/framebuffer.h"
 #include "main/glformats.h"
 #include "main/image.h"
 #include "main/macros.h"
@@ -61,6 +62,7 @@
 #include "main/polygon.h"
 #include "main/queryobj.h"
 #include "main/readpix.h"
+#include "main/renderbuffer.h"
 #include "main/scissor.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
@@ -83,7 +85,9 @@
 #include "drivers/common/meta.h"
 #include "main/enums.h"
 #include "main/glformats.h"
+#include "util/bitscan.h"
 #include "util/ralloc.h"
+#include "compiler/nir/nir.h"
 
 /** Return offset in bytes of the field within a vertex struct */
 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
@@ -94,116 +98,82 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl);
 static struct blit_shader *
 choose_blit_shader(GLenum target, struct blit_shader_table *table);
 
-static void cleanup_temp_texture(struct temp_texture *tex);
-static void meta_glsl_clear_cleanup(struct clear_state *clear);
-static void meta_decompress_cleanup(struct decompress_state *decompress);
-static void meta_drawpix_cleanup(struct drawpix_state *drawpix);
+static void cleanup_temp_texture(struct gl_context *ctx,
+                                 struct temp_texture *tex);
+static void meta_glsl_clear_cleanup(struct gl_context *ctx,
+                                    struct clear_state *clear);
+static void meta_decompress_cleanup(struct gl_context *ctx,
+                                    struct decompress_state *decompress);
+static void meta_drawpix_cleanup(struct gl_context *ctx,
+                                 struct drawpix_state *drawpix);
 
 void
-_mesa_meta_bind_fbo_image(GLenum fboTarget, GLenum attachment,
-                          struct gl_texture_image *texImage, GLuint layer)
+_mesa_meta_framebuffer_texture_image(struct gl_context *ctx,
+                                     struct gl_framebuffer *fb,
+                                     GLenum attachment,
+                                     struct gl_texture_image *texImage,
+                                     GLuint layer)
 {
    struct gl_texture_object *texObj = texImage->TexObject;
    int level = texImage->Level;
-   GLenum texTarget = texObj->Target;
+   const GLenum texTarget = texObj->Target == GL_TEXTURE_CUBE_MAP
+      ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face
+      : texObj->Target;
 
-   switch (texTarget) {
-   case GL_TEXTURE_1D:
-      _mesa_FramebufferTexture1D(fboTarget,
-                                 attachment,
-                                 texTarget,
-                                 texObj->Name,
-                                 level);
-      break;
-   case GL_TEXTURE_1D_ARRAY:
-   case GL_TEXTURE_2D_ARRAY:
-   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
-   case GL_TEXTURE_CUBE_MAP_ARRAY:
-   case GL_TEXTURE_3D:
-      _mesa_FramebufferTextureLayer(fboTarget,
-                                    attachment,
-                                    texObj->Name,
-                                    level,
-                                    layer);
-      break;
-   default: /* 2D / cube */
-      if (texTarget == GL_TEXTURE_CUBE_MAP)
-         texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face;
+   struct gl_renderbuffer_attachment *att =
+      _mesa_get_and_validate_attachment(ctx, fb, attachment, __func__);
+   assert(att);
 
-      _mesa_FramebufferTexture2D(fboTarget,
-                                 attachment,
-                                 texTarget,
-                                 texObj->Name,
-                                 level);
-   }
+   _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, texTarget,
+                             level, layer, false);
 }
 
-GLuint
-_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target,
-                                     const GLcharARB *source)
+static struct gl_shader *
+meta_compile_shader_with_debug(struct gl_context *ctx, gl_shader_stage stage,
+                               const GLcharARB *source)
 {
-   GLuint shader;
-   GLint ok, size;
-   GLchar *info;
-
-   shader = _mesa_CreateShader(target);
-   _mesa_ShaderSource(shader, 1, &source, NULL);
-   _mesa_CompileShader(shader);
-
-   _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &ok);
-   if (ok)
-      return shader;
-
-   _mesa_GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
-   if (size == 0) {
-      _mesa_DeleteShader(shader);
-      return 0;
-   }
+   const GLuint name = ~0;
+   struct gl_shader *sh;
+
+   sh = _mesa_new_shader(name, stage);
+   sh->Source = strdup(source);
+   sh->CompileStatus = COMPILE_FAILURE;
+   _mesa_compile_shader(ctx, sh);
+
+   if (!sh->CompileStatus) {
+      if (sh->InfoLog) {
+         _mesa_problem(ctx,
+                       "meta program compile failed:\n%s\nsource:\n%s\n",
+                       sh->InfoLog, source);
+      }
 
-   info = malloc(size);
-   if (!info) {
-      _mesa_DeleteShader(shader);
-      return 0;
+      _mesa_reference_shader(ctx, &sh, NULL);
    }
 
-   _mesa_GetShaderInfoLog(shader, size, NULL, info);
-   _mesa_problem(ctx,
-                "meta program compile failed:\n%s\n"
-                "source:\n%s\n",
-                info, source);
-
-   free(info);
-   _mesa_DeleteShader(shader);
-
-   return 0;
+   return sh;
 }
 
-GLuint
-_mesa_meta_link_program_with_debug(struct gl_context *ctx, GLuint program)
+void
+_mesa_meta_link_program_with_debug(struct gl_context *ctx,
+                                   struct gl_shader_program *sh_prog)
 {
-   GLint ok, size;
-   GLchar *info;
-
-   _mesa_LinkProgram(program);
-
-   _mesa_GetProgramiv(program, GL_LINK_STATUS, &ok);
-   if (ok)
-      return program;
-
-   _mesa_GetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
-   if (size == 0)
-      return 0;
+   _mesa_link_program(ctx, sh_prog);
 
-   info = malloc(size);
-   if (!info)
-      return 0;
-
-   _mesa_GetProgramInfoLog(program, size, NULL, info);
-   _mesa_problem(ctx, "meta program link failed:\n%s", info);
+   if (!sh_prog->data->LinkStatus) {
+      _mesa_problem(ctx, "meta program link failed:\n%s",
+                    sh_prog->data->InfoLog);
+   }
+}
 
-   free(info);
+void
+_mesa_meta_use_program(struct gl_context *ctx,
+                       struct gl_shader_program *sh_prog)
+{
+   /* Attach shader state to the binding point */
+   _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader);
 
-   return 0;
+   /* Update the program */
+   _mesa_use_shader_program(ctx, sh_prog);
 }
 
 void
@@ -211,24 +181,37 @@ _mesa_meta_compile_and_link_program(struct gl_context *ctx,
                                     const char *vs_source,
                                     const char *fs_source,
                                     const char *name,
-                                    GLuint *program)
+                                    struct gl_shader_program **out_sh_prog)
 {
-   GLuint vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER,
-                                                    vs_source);
-   GLuint fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER,
-                                                    fs_source);
-
-   *program = _mesa_CreateProgram();
-   _mesa_ObjectLabel(GL_PROGRAM, *program, -1, name);
-   _mesa_AttachShader(*program, fs);
-   _mesa_DeleteShader(fs);
-   _mesa_AttachShader(*program, vs);
-   _mesa_DeleteShader(vs);
-   _mesa_BindAttribLocation(*program, 0, "position");
-   _mesa_BindAttribLocation(*program, 1, "texcoords");
-   _mesa_meta_link_program_with_debug(ctx, *program);
-
-   _mesa_UseProgram(*program);
+   struct gl_shader_program *sh_prog;
+   const GLuint id = ~0;
+
+   sh_prog = _mesa_new_shader_program(id);
+   sh_prog->Label = strdup(name);
+   sh_prog->NumShaders = 2;
+   sh_prog->Shaders = malloc(2 * sizeof(struct gl_shader *));
+   sh_prog->Shaders[0] =
+      meta_compile_shader_with_debug(ctx, MESA_SHADER_VERTEX, vs_source);
+   sh_prog->Shaders[1] =
+      meta_compile_shader_with_debug(ctx, MESA_SHADER_FRAGMENT, fs_source);
+
+   _mesa_meta_link_program_with_debug(ctx, sh_prog);
+
+   struct gl_program *fp =
+      sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
+
+   /* texelFetch() can break GL_SKIP_DECODE_EXT, but many meta passes want
+    * to use both together; pretend that we're not using texelFetch to hack
+    * around this bad interaction.  This is a bit fragile as it may break
+    * if you re-run the pass that gathers this info, but we probably won't...
+    */
+   fp->info.textures_used_by_txf = 0;
+   if (fp->nir)
+      fp->nir->info.textures_used_by_txf = 0;
+
+   _mesa_meta_use_program(ctx, sh_prog);
+
+   *out_sh_prog = sh_prog;
 }
 
 /**
@@ -247,19 +230,15 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx,
 {
    char *vs_source, *fs_source;
    struct blit_shader *shader = choose_blit_shader(target, table);
-   const char *vs_input, *vs_output, *fs_input, *vs_preprocess, *fs_preprocess;
+   const char *fs_input, *vs_preprocess, *fs_preprocess;
    void *mem_ctx;
 
    if (ctx->Const.GLSLVersion < 130) {
       vs_preprocess = "";
-      vs_input = "attribute";
-      vs_output = "varying";
       fs_preprocess = "#extension GL_EXT_texture_array : enable";
       fs_input = "varying";
    } else {
       vs_preprocess = "#version 130";
-      vs_input = "in";
-      vs_output = "out";
       fs_preprocess = "#version 130";
       fs_input = "in";
       shader->func = "texture";
@@ -267,8 +246,8 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx,
 
    assert(shader != NULL);
 
-   if (shader->shader_prog != 0) {
-      _mesa_UseProgram(shader->shader_prog);
+   if (shader->shader_prog != NULL) {
+      _mesa_meta_use_program(ctx, shader->shader_prog);
       return;
    }
 
@@ -276,15 +255,16 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx,
 
    vs_source = ralloc_asprintf(mem_ctx,
                 "%s\n"
-                "%s vec2 position;\n"
-                "%s vec4 textureCoords;\n"
-                "%s vec4 texCoords;\n"
+                "#extension GL_ARB_explicit_attrib_location: enable\n"
+                "layout(location = 0) in vec2 position;\n"
+                "layout(location = 1) in vec4 textureCoords;\n"
+                "out vec4 texCoords;\n"
                 "void main()\n"
                 "{\n"
                 "   texCoords = textureCoords;\n"
                 "   gl_Position = vec4(position, 0.0, 1.0);\n"
                 "}\n",
-                vs_preprocess, vs_input, vs_input, vs_output);
+                vs_preprocess);
 
    fs_source = ralloc_asprintf(mem_ctx,
                 "%s\n"
@@ -316,7 +296,7 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx,
  *
  * \param VAO       Storage for vertex array object handle.  If 0, a new VAO
  *                  will be created.
- * \param VBO       Storage for vertex buffer object handle.  If 0, a new VBO
+ * \param buf_obj   Storage for vertex buffer object pointer.  If \c NULL, a new VBO
  *                  will be created.  The new VBO will have storage for 4
  *                  \c vertex structures.
  * \param use_generic_attributes  Should generic attributes 0 and 1 be used,
@@ -334,64 +314,85 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx,
  */
 void
 _mesa_meta_setup_vertex_objects(struct gl_context *ctx,
-                                GLuint *VAO, GLuint *VBO,
+                                GLuint *VAO, struct gl_buffer_object **buf_obj,
                                 bool use_generic_attributes,
                                 unsigned vertex_size, unsigned texcoord_size,
                                 unsigned color_size)
 {
    if (*VAO == 0) {
-      assert(*VBO == 0);
+      struct gl_vertex_array_object *array_obj;
+      assert(*buf_obj == NULL);
 
       /* create vertex array object */
       _mesa_GenVertexArrays(1, VAO);
       _mesa_BindVertexArray(*VAO);
 
+      array_obj = _mesa_lookup_vao(ctx, *VAO);
+      assert(array_obj != NULL);
+
       /* create vertex array buffer */
-      _mesa_GenBuffers(1, VBO);
-      _mesa_BindBuffer(GL_ARRAY_BUFFER, *VBO);
-      _mesa_BufferData(GL_ARRAY_BUFFER, 4 * sizeof(struct vertex), NULL,
-                       GL_DYNAMIC_DRAW);
+      *buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF);
+      if (*buf_obj == NULL)
+         return;
+
+      _mesa_buffer_data(ctx, *buf_obj, GL_NONE, 4 * sizeof(struct vertex), NULL,
+                        GL_DYNAMIC_DRAW, __func__);
 
       /* setup vertex arrays */
+      FLUSH_VERTICES(ctx, 0);
       if (use_generic_attributes) {
          assert(color_size == 0);
 
-         _mesa_VertexAttribPointer(0, vertex_size, GL_FLOAT, GL_FALSE,
-                                   sizeof(struct vertex), OFFSET(x));
-         _mesa_EnableVertexAttribArray(0);
-
+         _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_GENERIC(0),
+                                   vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                   GL_FALSE, GL_FALSE,
+                                   offsetof(struct vertex, x));
+         _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_GENERIC(0),
+                                  *buf_obj, 0, sizeof(struct vertex), true);
+         _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                          VERT_ATTRIB_GENERIC(0), true);
          if (texcoord_size > 0) {
-            _mesa_VertexAttribPointer(1, texcoord_size, GL_FLOAT, GL_FALSE,
-                                      sizeof(struct vertex), OFFSET(tex));
-            _mesa_EnableVertexAttribArray(1);
+            _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_GENERIC(1),
+                                      texcoord_size, GL_FLOAT, GL_RGBA,
+                                      GL_FALSE, GL_FALSE, GL_FALSE,
+                                      offsetof(struct vertex, tex));
+            _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_GENERIC(1),
+                                     *buf_obj, 0, sizeof(struct vertex), true);
+            _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                             VERT_ATTRIB_GENERIC(1), true);
          }
       } else {
-         _mesa_VertexPointer(vertex_size, GL_FLOAT, sizeof(struct vertex),
-                             OFFSET(x));
-         _mesa_EnableClientState(GL_VERTEX_ARRAY);
+         _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_POS,
+                                   vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                   GL_FALSE, GL_FALSE,
+                                   offsetof(struct vertex, x));
+         _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_POS,
+                                  *buf_obj, 0, sizeof(struct vertex), true);
+         _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                          VERT_ATTRIB_POS, true);
 
          if (texcoord_size > 0) {
-            _mesa_TexCoordPointer(texcoord_size, GL_FLOAT,
-                                  sizeof(struct vertex), OFFSET(tex));
-            _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+            _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_TEX(0),
+                                      vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                      GL_FALSE, GL_FALSE,
+                                      offsetof(struct vertex, tex));
+            _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_TEX(0),
+                                     *buf_obj, 0, sizeof(struct vertex), true);
+            _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                             VERT_ATTRIB_TEX(0), true);
          }
 
          if (color_size > 0) {
-            _mesa_ColorPointer(color_size, GL_FLOAT,
-                               sizeof(struct vertex), OFFSET(r));
-            _mesa_EnableClientState(GL_COLOR_ARRAY);
+            _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_COLOR0,
+                                      vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                      GL_FALSE, GL_FALSE,
+                                      offsetof(struct vertex, r));
+            _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_COLOR0,
+                                     *buf_obj, 0, sizeof(struct vertex), true);
+            _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                             VERT_ATTRIB_COLOR0, true);
          }
       }
-
-      /* Restore the old VBO.  This is done because we don't want the new VBO
-       * to be bound on exit.  It would be nicer to use DSA type functions,
-       * but there are no DSA functions to bind a VBO to a VAO for
-       * fixed-function vertex attributes.
-       */
-      {
-         struct save_state *save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth - 1];
-         _mesa_BindBuffer(GL_ARRAY_BUFFER, save->ArrayBufferObj->Name);
-      }
    } else {
       _mesa_BindVertexArray(*VAO);
    }
@@ -418,12 +419,12 @@ _mesa_meta_free(struct gl_context *ctx)
 {
    GET_CURRENT_CONTEXT(old_context);
    _mesa_make_current(ctx, NULL, NULL);
-   _mesa_meta_glsl_blit_cleanup(&ctx->Meta->Blit);
-   meta_glsl_clear_cleanup(&ctx->Meta->Clear);
-   _mesa_meta_glsl_generate_mipmap_cleanup(&ctx->Meta->Mipmap);
-   cleanup_temp_texture(&ctx->Meta->TempTex);
-   meta_decompress_cleanup(&ctx->Meta->Decompress);
-   meta_drawpix_cleanup(&ctx->Meta->DrawPix);
+   _mesa_meta_glsl_blit_cleanup(ctx, &ctx->Meta->Blit);
+   meta_glsl_clear_cleanup(ctx, &ctx->Meta->Clear);
+   _mesa_meta_glsl_generate_mipmap_cleanup(ctx, &ctx->Meta->Mipmap);
+   cleanup_temp_texture(ctx, &ctx->Meta->TempTex);
+   meta_decompress_cleanup(ctx, &ctx->Meta->Decompress);
+   meta_drawpix_cleanup(ctx, &ctx->Meta->DrawPix);
    if (old_context)
       _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer);
    else
@@ -517,15 +518,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       _mesa_set_enable(ctx, GL_DITHER, GL_TRUE);
    }
 
-   if (state & MESA_META_COLOR_MASK) {
-      memcpy(save->ColorMask, ctx->Color.ColorMask,
-             sizeof(ctx->Color.ColorMask));
-      if (!ctx->Color.ColorMask[0][0] ||
-          !ctx->Color.ColorMask[0][1] ||
-          !ctx->Color.ColorMask[0][2] ||
-          !ctx->Color.ColorMask[0][3])
-         _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-   }
+   if (state & MESA_META_COLOR_MASK)
+      save->ColorMask = ctx->Color.ColorMask;
 
    if (state & MESA_META_DEPTH_TEST) {
       save->Depth = ctx->Depth; /* struct copy */
@@ -593,15 +587,15 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
 
       if (ctx->Extensions.ARB_vertex_program) {
          save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
-         _mesa_reference_vertprog(ctx, &save->VertexProgram,
-                                 ctx->VertexProgram.Current);
+         _mesa_reference_program(ctx, &save->VertexProgram,
+                                 ctx->VertexProgram.Current);
          _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
       }
 
       if (ctx->Extensions.ARB_fragment_program) {
          save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
-         _mesa_reference_fragprog(ctx, &save->FragmentProgram,
-                                 ctx->FragmentProgram.Current);
+         _mesa_reference_program(ctx, &save->FragmentProgram,
+                                 ctx->FragmentProgram.Current);
          _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
       }
 
@@ -620,8 +614,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
        * that we don't have to worry about the current pipeline state.
        */
       for (i = 0; i < MESA_SHADER_STAGES; i++) {
-         _mesa_reference_shader_program(ctx, &save->Shader[i],
-                                        ctx->Shader.CurrentProgram[i]);
+         _mesa_reference_program(ctx, &save->Program[i],
+                                 ctx->Shader.CurrentProgram[i]);
       }
       _mesa_reference_shader_program(ctx, &save->ActiveShader,
                                      ctx->Shader.ActiveProgram);
@@ -640,15 +634,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       GLuint u, tgt;
 
       save->ActiveUnit = ctx->Texture.CurrentUnit;
-      save->ClientActiveUnit = ctx->Array.ActiveTexture;
-      save->EnvMode = ctx->Texture.Unit[0].EnvMode;
+      save->EnvMode = ctx->Texture.FixedFuncUnit[0].EnvMode;
 
       /* Disable all texture units */
       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
-         save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
-         if (ctx->Texture.Unit[u].Enabled ||
-             ctx->Texture.Unit[u].TexGenEnabled) {
+         save->TexEnabled[u] = ctx->Texture.FixedFuncUnit[u].Enabled;
+         save->TexGenEnabled[u] = ctx->Texture.FixedFuncUnit[u].TexGenEnabled;
+         if (ctx->Texture.FixedFuncUnit[u].Enabled ||
+             ctx->Texture.FixedFuncUnit[u].TexGenEnabled) {
             _mesa_ActiveTexture(GL_TEXTURE0 + u);
             _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
             if (ctx->Extensions.ARB_texture_cube_map)
@@ -673,7 +666,6 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
 
       /* set defaults for unit[0] */
       _mesa_ActiveTexture(GL_TEXTURE0);
-      _mesa_ClientActiveTexture(GL_TEXTURE0);
       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    }
 
@@ -712,12 +704,12 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
    }
 
    if (state & MESA_META_CLIP) {
+      GLbitfield mask;
       save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
-      if (ctx->Transform.ClipPlanesEnabled) {
-         GLuint i;
-         for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
-            _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
-         }
+      mask = ctx->Transform.ClipPlanesEnabled;
+      while (mask) {
+         const int i = u_bit_scan(&mask);
+         _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
       }
    }
 
@@ -725,8 +717,6 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       /* save vertex array object state */
       _mesa_reference_vao(ctx, &save->VAO,
                                    ctx->Array.VAO);
-      _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
-                                    ctx->Array.ArrayBufferObj);
       /* set some default state? */
    }
 
@@ -760,7 +750,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
        */
       if (ctx->Color.ClampFragmentColor != GL_TRUE &&
           ctx->Extensions.ARB_color_buffer_float)
-        _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
+         _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
    }
 
    if (state & MESA_META_CLAMP_VERTEX_COLOR) {
@@ -778,17 +768,17 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       save->CondRenderMode = ctx->Query.CondRenderMode;
 
       if (ctx->Query.CondRenderQuery)
-        _mesa_EndConditionalRender();
+         _mesa_EndConditionalRender();
    }
 
    if (state & MESA_META_SELECT_FEEDBACK) {
       save->RenderMode = ctx->RenderMode;
       if (ctx->RenderMode == GL_SELECT) {
-        save->Select = ctx->Select; /* struct copy */
-        _mesa_RenderMode(GL_RENDER);
+         save->Select = ctx->Select; /* struct copy */
+         _mesa_RenderMode(GL_RENDER);
       } else if (ctx->RenderMode == GL_FEEDBACK) {
-        save->Feedback = ctx->Feedback; /* struct copy */
-        _mesa_RenderMode(GL_RENDER);
+         save->Feedback = ctx->Feedback; /* struct copy */
+         _mesa_RenderMode(GL_RENDER);
       }
    }
 
@@ -830,10 +820,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       if (ctx->RasterDiscard)
          _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE);
 
-      save->DrawBufferName = ctx->DrawBuffer->Name;
-      save->ReadBufferName = ctx->ReadBuffer->Name;
-      save->RenderbufferName = (ctx->CurrentRenderbuffer ?
-                                ctx->CurrentRenderbuffer->Name : 0);
+      _mesa_reference_framebuffer(&save->DrawBuffer, ctx->DrawBuffer);
+      _mesa_reference_framebuffer(&save->ReadBuffer, ctx->ReadBuffer);
    }
 }
 
@@ -893,17 +881,20 @@ _mesa_meta_end(struct gl_context *ctx)
    if (state & MESA_META_COLOR_MASK) {
       GLuint i;
       for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-         if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
+         if (GET_COLORMASK(ctx->Color.ColorMask, i) !=
+             GET_COLORMASK(save->ColorMask, i)) {
             if (i == 0) {
-               _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
-                               save->ColorMask[i][2], save->ColorMask[i][3]);
+               _mesa_ColorMask(GET_COLORMASK_BIT(save->ColorMask, i, 0),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 1),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 2),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 3));
             }
             else {
                _mesa_ColorMaski(i,
-                                      save->ColorMask[i][0],
-                                      save->ColorMask[i][1],
-                                      save->ColorMask[i][2],
-                                      save->ColorMask[i][3]);
+                                GET_COLORMASK_BIT(save->ColorMask, i, 0),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 1),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 2),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 3));
             }
          }
       }
@@ -963,32 +954,22 @@ _mesa_meta_end(struct gl_context *ctx)
    }
 
    if (state & MESA_META_SHADER) {
-      static const GLenum targets[] = {
-         GL_VERTEX_SHADER,
-         GL_TESS_CONTROL_SHADER,
-         GL_TESS_EVALUATION_SHADER,
-         GL_GEOMETRY_SHADER,
-         GL_FRAGMENT_SHADER,
-         GL_COMPUTE_SHADER,
-      };
-      STATIC_ASSERT(MESA_SHADER_STAGES == ARRAY_SIZE(targets));
-
       bool any_shader;
 
       if (ctx->Extensions.ARB_vertex_program) {
          _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
                           save->VertexProgramEnabled);
-         _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 
-                                  save->VertexProgram);
-        _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL);
+         _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
+                                 save->VertexProgram);
+         _mesa_reference_program(ctx, &save->VertexProgram, NULL);
       }
 
       if (ctx->Extensions.ARB_fragment_program) {
          _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
                           save->FragmentProgramEnabled);
-         _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
-                                  save->FragmentProgram);
-        _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
+         _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
+                                 save->FragmentProgram);
+         _mesa_reference_program(ctx, &save->FragmentProgram, NULL);
       }
 
       if (ctx->Extensions.ATI_fragment_shader) {
@@ -998,22 +979,20 @@ _mesa_meta_end(struct gl_context *ctx)
 
       any_shader = false;
       for (i = 0; i < MESA_SHADER_STAGES; i++) {
-         /* It is safe to call _mesa_use_shader_program even if the extension
+         /* It is safe to call _mesa_use_program even if the extension
           * necessary for that program state is not supported.  In that case,
           * the saved program object must be NULL and the currently bound
-          * program object must be NULL.  _mesa_use_shader_program is a no-op
+          * program object must be NULL.  _mesa_use_program is a no-op
           * in that case.
           */
-         _mesa_use_shader_program(ctx, targets[i],
-                                  save->Shader[i],
-                                  &ctx->Shader);
+         _mesa_use_program(ctx, i, NULL, save->Program[i],  &ctx->Shader);
 
          /* Do this *before* killing the reference. :)
           */
-         if (save->Shader[i] != NULL)
+         if (save->Program[i] != NULL)
             any_shader = true;
 
-         _mesa_reference_shader_program(ctx, &save->Shader[i], NULL);
+         _mesa_reference_program(ctx, &save->Program[i], NULL);
       }
 
       _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
@@ -1036,6 +1015,8 @@ _mesa_meta_end(struct gl_context *ctx)
 
          _mesa_reference_pipeline_object(ctx, &save->Pipeline, NULL);
       }
+
+      _mesa_update_vertex_processing_mode(ctx);
    }
 
    if (state & MESA_META_STENCIL_TEST) {
@@ -1079,30 +1060,29 @@ _mesa_meta_end(struct gl_context *ctx)
 
       /* restore texture objects for unit[0] only */
       for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
-        if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) {
-           FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
-                                  save->CurrentTexture[tgt]);
-        }
+         if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+            _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
+                                   save->CurrentTexture[tgt]);
+         }
          _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
       }
 
       /* Restore fixed function texture enables, texgen */
       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) {
+         if (ctx->Texture.FixedFuncUnit[u].Enabled != save->TexEnabled[u]) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            ctx->Texture.Unit[u].Enabled = save->TexEnabled[u];
+            ctx->Texture.FixedFuncUnit[u].Enabled = save->TexEnabled[u];
          }
 
-         if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) {
+         if (ctx->Texture.FixedFuncUnit[u].TexGenEnabled != save->TexGenEnabled[u]) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u];
+            ctx->Texture.FixedFuncUnit[u].TexGenEnabled = save->TexGenEnabled[u];
          }
       }
 
       /* restore current unit state */
       _mesa_ActiveTexture(GL_TEXTURE0 + save->ActiveUnit);
-      _mesa_ClientActiveTexture(GL_TEXTURE0 + save->ClientActiveUnit);
    }
 
    if (state & MESA_META_TRANSFORM) {
@@ -1125,21 +1105,14 @@ _mesa_meta_end(struct gl_context *ctx)
    }
 
    if (state & MESA_META_CLIP) {
-      if (save->ClipPlanesEnabled) {
-         GLuint i;
-         for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
-            if (save->ClipPlanesEnabled & (1 << i)) {
-               _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
-            }
-         }
+      GLbitfield mask = save->ClipPlanesEnabled;
+      while (mask) {
+         const int i = u_bit_scan(&mask);
+         _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
       }
    }
 
    if (state & MESA_META_VERTEX) {
-      /* restore vertex buffer object */
-      _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
-      _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
-
       /* restore vertex array object */
       _mesa_BindVertexArray(save->VAO->Name);
       _mesa_reference_vao(ctx, &save->VAO, NULL);
@@ -1168,17 +1141,17 @@ _mesa_meta_end(struct gl_context *ctx)
 
    if (state & MESA_META_CONDITIONAL_RENDER) {
       if (save->CondRenderQuery)
-        _mesa_BeginConditionalRender(save->CondRenderQuery->Id,
-                                     save->CondRenderMode);
+         _mesa_BeginConditionalRender(save->CondRenderQuery->Id,
+                                      save->CondRenderMode);
    }
 
    if (state & MESA_META_SELECT_FEEDBACK) {
       if (save->RenderMode == GL_SELECT) {
-        _mesa_RenderMode(GL_SELECT);
-        ctx->Select = save->Select;
+         _mesa_RenderMode(GL_SELECT);
+         ctx->Select = save->Select;
       } else if (save->RenderMode == GL_FEEDBACK) {
-        _mesa_RenderMode(GL_FEEDBACK);
-        ctx->Feedback = save->Feedback;
+         _mesa_RenderMode(GL_FEEDBACK);
+         ctx->Feedback = save->Feedback;
       }
    }
 
@@ -1224,15 +1197,9 @@ _mesa_meta_end(struct gl_context *ctx)
    if (save->TransformFeedbackNeedsResume)
       _mesa_ResumeTransformFeedback();
 
-   if (ctx->DrawBuffer->Name != save->DrawBufferName)
-      _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, save->DrawBufferName);
-
-   if (ctx->ReadBuffer->Name != save->ReadBufferName)
-      _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, save->ReadBufferName);
-
-   if (!ctx->CurrentRenderbuffer ||
-       ctx->CurrentRenderbuffer->Name != save->RenderbufferName)
-      _mesa_BindRenderbuffer(GL_RENDERBUFFER, save->RenderbufferName);
+   _mesa_bind_framebuffers(ctx, save->DrawBuffer, save->ReadBuffer);
+   _mesa_reference_framebuffer(&save->DrawBuffer, NULL);
+   _mesa_reference_framebuffer(&save->ReadBuffer, NULL);
 
    if (state & MESA_META_DRAW_BUFFERS) {
       _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
@@ -1283,16 +1250,14 @@ init_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
    tex->MinSize = 16;  /* 16 x 16 at least */
    assert(tex->MaxSize > 0);
 
-   _mesa_GenTextures(1, &tex->TexObj);
+   tex->tex_obj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, tex->Target);
 }
 
 static void
-cleanup_temp_texture(struct temp_texture *tex)
+cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
 {
-   if (!tex->TexObj)
-     return;
-   _mesa_DeleteTextures(1, &tex->TexObj);
-   tex->TexObj = 0;
+   _mesa_delete_nameless_texture(ctx, tex->tex_obj);
+   tex->tex_obj = NULL;
 }
 
 
@@ -1305,7 +1270,7 @@ _mesa_meta_get_temp_texture(struct gl_context *ctx)
 {
    struct temp_texture *tex = &ctx->Meta->TempTex;
 
-   if (!tex->TexObj) {
+   if (tex->tex_obj == NULL) {
       init_temp_texture(ctx, tex);
    }
 
@@ -1323,7 +1288,7 @@ get_bitmap_temp_texture(struct gl_context *ctx)
 {
    struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
 
-   if (!tex->TexObj) {
+   if (tex->tex_obj == NULL) {
       init_temp_texture(ctx, tex);
    }
 
@@ -1339,7 +1304,7 @@ _mesa_meta_get_temp_depth_texture(struct gl_context *ctx)
 {
    struct temp_texture *tex = &ctx->Meta->Blit.depthTex;
 
-   if (!tex->TexObj) {
+   if (tex->tex_obj == NULL) {
       init_temp_texture(ctx, tex);
    }
 
@@ -1418,9 +1383,11 @@ _mesa_meta_setup_copypix_texture(struct gl_context *ctx,
 {
    bool newTex;
 
-   _mesa_BindTexture(tex->Target, tex->TexObj);
-   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
-   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
+   _mesa_bind_texture(ctx, tex->Target, tex->tex_obj);
+   _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MIN_FILTER,
+                             (GLint *) &filter, false);
+   _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MAG_FILTER,
+                             (GLint *) &filter, false);
    _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
    newTex = _mesa_meta_alloc_texture(tex, width, height, intFormat);
@@ -1462,9 +1429,16 @@ _mesa_meta_setup_drawpix_texture(struct gl_context *ctx,
                                  GLenum format, GLenum type,
                                  const GLvoid *pixels)
 {
-   _mesa_BindTexture(tex->Target, tex->TexObj);
-   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-   _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   /* GLint so the compiler won't complain about type signedness mismatch in
+    * the call to _mesa_texture_parameteriv below.
+    */
+   static const GLint filter = GL_NEAREST;
+
+   _mesa_bind_texture(ctx, tex->Target, tex->tex_obj);
+   _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MIN_FILTER, &filter,
+                             false);
+   _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MAG_FILTER, &filter,
+                             false);
    _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
    /* copy pixel data to texture */
@@ -1476,17 +1450,17 @@ _mesa_meta_setup_drawpix_texture(struct gl_context *ctx,
                           tex->Width, tex->Height, 0, format, type, pixels);
       }
       else {
-        struct gl_buffer_object *save_unpack_obj = NULL;
+         struct gl_buffer_object *save_unpack_obj = NULL;
 
-        _mesa_reference_buffer_object(ctx, &save_unpack_obj,
-                                      ctx->Unpack.BufferObj);
-        _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+         _mesa_reference_buffer_object(ctx, &save_unpack_obj,
+                                       ctx->Unpack.BufferObj);
+         _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
          /* create empty texture */
          _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
                           tex->Width, tex->Height, 0, format, type, NULL);
-        if (save_unpack_obj != NULL)
-           _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
-                               save_unpack_obj->Name);
+         if (save_unpack_obj != NULL)
+            _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
+                             save_unpack_obj->Name);
          /* load image */
          _mesa_TexSubImage2D(tex->Target, 0,
                              0, 0, width, height, format, type, pixels);
@@ -1501,10 +1475,11 @@ _mesa_meta_setup_drawpix_texture(struct gl_context *ctx,
 
 void
 _mesa_meta_setup_ff_tnl_for_blit(struct gl_context *ctx,
-                                 GLuint *VAO, GLuint *VBO,
+                                 GLuint *VAO, struct gl_buffer_object **buf_obj,
                                  unsigned texcoord_size)
 {
-   _mesa_meta_setup_vertex_objects(ctx, VAO, VBO, false, 2, texcoord_size, 0);
+   _mesa_meta_setup_vertex_objects(ctx, VAO, buf_obj, false, 2, texcoord_size,
+                                   0);
 
    /* setup projection matrix */
    _mesa_MatrixMode(GL_PROJECTION);
@@ -1532,7 +1507,8 @@ 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"
+      "#extension GL_ARB_explicit_attrib_location :enable\n"
+      "layout(location = 0) in vec4 position;\n"
       "void main()\n"
       "{\n"
       "#ifdef GL_AMD_vertex_shader_layer\n"
@@ -1541,38 +1517,23 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
       "   gl_Position = position;\n"
       "}\n";
    const char *fs_source =
-      "uniform vec4 color;\n"
+      "#extension GL_ARB_explicit_attrib_location :enable\n"
+      "#extension GL_ARB_explicit_uniform_location :enable\n"
+      "layout(location = 0) uniform vec4 color;\n"
       "void main()\n"
       "{\n"
       "   gl_FragColor = color;\n"
       "}\n";
-   GLuint vs, fs;
    bool has_integer_textures;
 
-   _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->VBO, true,
+   _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->buf_obj, true,
                                    3, 0, 0);
 
    if (clear->ShaderProg != 0)
       return;
 
-   vs = _mesa_CreateShader(GL_VERTEX_SHADER);
-   _mesa_ShaderSource(vs, 1, &vs_source, NULL);
-   _mesa_CompileShader(vs);
-
-   fs = _mesa_CreateShader(GL_FRAGMENT_SHADER);
-   _mesa_ShaderSource(fs, 1, &fs_source, NULL);
-   _mesa_CompileShader(fs);
-
-   clear->ShaderProg = _mesa_CreateProgram();
-   _mesa_AttachShader(clear->ShaderProg, fs);
-   _mesa_DeleteShader(fs);
-   _mesa_AttachShader(clear->ShaderProg, vs);
-   _mesa_DeleteShader(vs);
-   _mesa_BindAttribLocation(clear->ShaderProg, 0, "position");
-   _mesa_ObjectLabel(GL_PROGRAM, clear->ShaderProg, -1, "meta clear");
-   _mesa_LinkProgram(clear->ShaderProg);
-
-   clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, "color");
+   _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, "meta clear",
+                                       &clear->ShaderProg);
 
    has_integer_textures = _mesa_is_gles3(ctx) ||
       (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130);
@@ -1584,7 +1545,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
                          "#version 130\n"
                          "#extension GL_AMD_vertex_shader_layer : enable\n"
                          "#extension GL_ARB_draw_instanced : enable\n"
-                         "in vec4 position;\n"
+                         "#extension GL_ARB_explicit_attrib_location :enable\n"
+                         "layout(location = 0) in vec4 position;\n"
                          "void main()\n"
                          "{\n"
                          "#ifdef GL_AMD_vertex_shader_layer\n"
@@ -1595,7 +1557,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
       const char *fs_int_source =
          ralloc_asprintf(shader_source_mem_ctx,
                          "#version 130\n"
-                         "uniform ivec4 color;\n"
+                         "#extension GL_ARB_explicit_attrib_location :enable\n"
+                         "#extension GL_ARB_explicit_uniform_location :enable\n"
+                         "layout(location = 0) uniform ivec4 color;\n"
                          "out ivec4 out_color;\n"
                          "\n"
                          "void main()\n"
@@ -1603,48 +1567,30 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
                          "   out_color = color;\n"
                          "}\n");
 
-      vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER,
-                                                vs_int_source);
-      fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER,
-                                                fs_int_source);
+      _mesa_meta_compile_and_link_program(ctx, vs_int_source, fs_int_source,
+                                          "integer clear",
+                                          &clear->IntegerShaderProg);
       ralloc_free(shader_source_mem_ctx);
 
-      clear->IntegerShaderProg = _mesa_CreateProgram();
-      _mesa_AttachShader(clear->IntegerShaderProg, fs);
-      _mesa_DeleteShader(fs);
-      _mesa_AttachShader(clear->IntegerShaderProg, vs);
-      _mesa_DeleteShader(vs);
-      _mesa_BindAttribLocation(clear->IntegerShaderProg, 0, "position");
-
       /* Note that user-defined out attributes get automatically assigned
        * locations starting from 0, so we don't need to explicitly
        * BindFragDataLocation to 0.
        */
-
-      _mesa_ObjectLabel(GL_PROGRAM, clear->IntegerShaderProg, -1,
-                        "integer clear");
-      _mesa_meta_link_program_with_debug(ctx, clear->IntegerShaderProg);
-
-      clear->IntegerColorLocation =
-        _mesa_GetUniformLocation(clear->IntegerShaderProg, "color");
    }
 }
 
 static void
-meta_glsl_clear_cleanup(struct clear_state *clear)
+meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear)
 {
    if (clear->VAO == 0)
       return;
    _mesa_DeleteVertexArrays(1, &clear->VAO);
    clear->VAO = 0;
-   _mesa_DeleteBuffers(1, &clear->VBO);
-   clear->VBO = 0;
-   _mesa_DeleteProgram(clear->ShaderProg);
-   clear->ShaderProg = 0;
+   _mesa_reference_buffer_object(ctx, &clear->buf_obj, NULL);
+   _mesa_reference_shader_program(ctx, &clear->ShaderProg, NULL);
 
    if (clear->IntegerShaderProg) {
-      _mesa_DeleteProgram(clear->IntegerShaderProg);
-      clear->IntegerShaderProg = 0;
+      _mesa_reference_shader_program(ctx, &clear->IntegerShaderProg, NULL);
    }
 }
 
@@ -1690,6 +1636,69 @@ _mesa_meta_drawbuffers_from_bitfield(GLbitfield bits)
    _mesa_DrawBuffers(i, enums);
 }
 
+/**
+ * Given a bitfield of BUFFER_BIT_x draw buffers, call glDrawBuffers to
+ * set GL to only draw to those buffers.  Also, update color masks to
+ * reflect the new draw buffer ordering.
+ */
+static void
+_mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask)
+{
+   GLenum enums[MAX_DRAW_BUFFERS];
+   GLubyte colormask[MAX_DRAW_BUFFERS][4];
+   int num_bufs = 0;
+
+   /* This function is only legal for color buffer bitfields. */
+   assert((mask & ~BUFFER_BITS_COLOR) == 0);
+
+   /* Make sure we don't overflow any arrays. */
+   assert(_mesa_bitcount(mask) <= MAX_DRAW_BUFFERS);
+
+   enums[0] = GL_NONE;
+
+   for (int i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+      gl_buffer_index b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+      int colormask_idx = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
+
+      if (b < 0 || !(mask & (1 << b)) ||
+          GET_COLORMASK(ctx->Color.ColorMask, colormask_idx) == 0)
+         continue;
+
+      switch (b) {
+      case BUFFER_FRONT_LEFT:
+         enums[num_bufs] = GL_FRONT_LEFT;
+         break;
+      case BUFFER_FRONT_RIGHT:
+         enums[num_bufs] = GL_FRONT_RIGHT;
+         break;
+      case BUFFER_BACK_LEFT:
+         enums[num_bufs] = GL_BACK_LEFT;
+         break;
+      case BUFFER_BACK_RIGHT:
+         enums[num_bufs] = GL_BACK_RIGHT;
+         break;
+      default:
+         assert(b >= BUFFER_COLOR0 && b <= BUFFER_COLOR7);
+         enums[num_bufs] = GL_COLOR_ATTACHMENT0 + (b - BUFFER_COLOR0);
+         break;
+      }
+
+      for (int k = 0; k < 4; k++)
+         colormask[num_bufs][k] = GET_COLORMASK_BIT(ctx->Color.ColorMask,
+                                                    colormask_idx, k);
+
+      num_bufs++;
+   }
+
+   _mesa_DrawBuffers(num_bufs, enums);
+
+   for (int i = 0; i < num_bufs; i++) {
+      _mesa_ColorMaski(i, colormask[i][0], colormask[i][1],
+                          colormask[i][2], colormask[i][3]);
+   }
+}
+
+
 /**
  * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
  */
@@ -1705,15 +1714,16 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
    int i;
 
    metaSave = (MESA_META_ALPHA_TEST |
-              MESA_META_BLEND |
-              MESA_META_DEPTH_TEST |
-              MESA_META_RASTERIZATION |
-              MESA_META_SHADER |
-              MESA_META_STENCIL_TEST |
-              MESA_META_VERTEX |
-              MESA_META_VIEWPORT |
-              MESA_META_CLIP |
-              MESA_META_CLAMP_FRAGMENT_COLOR |
+               MESA_META_BLEND |
+               MESA_META_COLOR_MASK |
+               MESA_META_DEPTH_TEST |
+               MESA_META_RASTERIZATION |
+               MESA_META_SHADER |
+               MESA_META_STENCIL_TEST |
+               MESA_META_VERTEX |
+               MESA_META_VIEWPORT |
+               MESA_META_CLIP |
+               MESA_META_CLAMP_FRAGMENT_COLOR |
                MESA_META_MULTISAMPLE |
                MESA_META_OCCLUSION_QUERY);
 
@@ -1728,11 +1738,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
 
    if (buffers & BUFFER_BITS_COLOR) {
       metaSave |= MESA_META_DRAW_BUFFERS;
-   } else {
-      /* We'll use colormask to disable color writes.  Otherwise,
-       * respect color mask
-       */
-      metaSave |= MESA_META_COLOR_MASK;
    }
 
    _mesa_meta_begin(ctx, metaSave);
@@ -1746,7 +1751,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
       y1 = ((float) fb->_Ymax / fb->Height) * 2.0f - 1.0f;
       z = -invert_z(ctx->Depth.Clear);
    } else {
-      _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->VBO, false,
+      _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->buf_obj, false,
                                       3, 0, 4);
 
       x0 = (float) fb->_Xmin;
@@ -1756,21 +1761,19 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
       z = invert_z(ctx->Depth.Clear);
    }
 
-   if (fb->_IntegerColor) {
+   if (fb->_IntegerBuffers) {
       assert(glsl);
-      _mesa_UseProgram(clear->IntegerShaderProg);
-      _mesa_Uniform4iv(clear->IntegerColorLocation, 1,
-                         ctx->Color.ClearColor.i);
+      _mesa_meta_use_program(ctx, clear->IntegerShaderProg);
+      _mesa_Uniform4iv(0, 1, ctx->Color.ClearColor.i);
    } else if (glsl) {
-      _mesa_UseProgram(clear->ShaderProg);
-      _mesa_Uniform4fv(clear->ColorLocation, 1,
-                         ctx->Color.ClearColor.f);
+      _mesa_meta_use_program(ctx, clear->ShaderProg);
+      _mesa_Uniform4fv(0, 1, ctx->Color.ClearColor.f);
    }
 
    /* GL_COLOR_BUFFER_BIT */
    if (buffers & BUFFER_BITS_COLOR) {
       /* Only draw to the buffers we were asked to clear. */
-      _mesa_meta_drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR);
+      _mesa_meta_drawbuffers_and_colormask(ctx, buffers & BUFFER_BITS_COLOR);
 
       /* leave colormask state as-is */
 
@@ -1779,7 +1782,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
          _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
    }
    else {
-      assert(metaSave & MESA_META_COLOR_MASK);
       _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    }
 
@@ -1830,7 +1832,8 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
    }
 
    /* upload new vertex data */
-   _mesa_NamedBufferData(clear->VBO, sizeof(verts), verts, GL_DYNAMIC_DRAW);
+   _mesa_buffer_data(ctx, clear->buf_obj, GL_NONE, sizeof(verts), verts,
+                     GL_DYNAMIC_DRAW, __func__);
 
    /* draw quad(s) */
    if (fb->MaxNumLayers > 0) {
@@ -1876,7 +1879,7 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
                           MESA_META_VERTEX |
                           MESA_META_VIEWPORT));
 
-   _mesa_meta_setup_vertex_objects(ctx, &copypix->VAO, &copypix->VBO, false,
+   _mesa_meta_setup_vertex_objects(ctx, &copypix->VAO, &copypix->buf_obj, false,
                                    3, 2, 0);
 
    /* Silence valgrind warnings about reading uninitialized stack. */
@@ -1916,7 +1919,7 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
       verts[3].tex[1] = tex->Ttop;
 
       /* upload new vertex data */
-      _mesa_NamedBufferSubData(copypix->VBO, 0, sizeof(verts), verts);
+      _mesa_buffer_sub_data(ctx, copypix->buf_obj, 0, sizeof(verts), verts);
    }
 
    _mesa_set_enable(ctx, tex->Target, GL_TRUE);
@@ -1930,14 +1933,13 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
 }
 
 static void
-meta_drawpix_cleanup(struct drawpix_state *drawpix)
+meta_drawpix_cleanup(struct gl_context *ctx, struct drawpix_state *drawpix)
 {
    if (drawpix->VAO != 0) {
       _mesa_DeleteVertexArrays(1, &drawpix->VAO);
       drawpix->VAO = 0;
 
-      _mesa_DeleteBuffers(1, &drawpix->VBO);
-      drawpix->VBO = 0;
+      _mesa_reference_buffer_object(ctx, &drawpix->buf_obj, NULL);
    }
 
    if (drawpix->StencilFP != 0) {
@@ -2131,8 +2133,8 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
        * point.
        */
       if (ctx->Color.ClampFragmentColor != GL_TRUE &&
-         ctx->Extensions.ARB_texture_float)
-        texIntFormat = GL_RGBA32F;
+          ctx->Extensions.ARB_texture_float)
+         texIntFormat = GL_RGBA32F;
    }
    else if (_mesa_is_stencil_format(format)) {
       if (ctx->Extensions.ARB_fragment_program &&
@@ -2197,7 +2199,7 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
 
    newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat);
 
-   _mesa_meta_setup_vertex_objects(ctx, &drawpix->VAO, &drawpix->VBO, false,
+   _mesa_meta_setup_vertex_objects(ctx, &drawpix->VAO, &drawpix->buf_obj, false,
                                    3, 2, 0);
 
    /* Silence valgrind warnings about reading uninitialized stack. */
@@ -2234,7 +2236,8 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
    }
 
    /* upload new vertex data */
-   _mesa_NamedBufferData(drawpix->VBO, sizeof(verts), verts, GL_DYNAMIC_DRAW);
+   _mesa_buffer_data(ctx, drawpix->buf_obj, GL_NONE, sizeof(verts), verts,
+                     GL_DYNAMIC_DRAW, __func__);
 
    /* set given unpack params */
    ctx->Unpack = *unpack;
@@ -2319,24 +2322,24 @@ alpha_test_raster_color(struct gl_context *ctx)
 
    switch (ctx->Color.AlphaFunc) {
       case GL_NEVER:
-        return GL_FALSE;
+         return GL_FALSE;
       case GL_LESS:
-        return alpha < ref;
+         return alpha < ref;
       case GL_EQUAL:
-        return alpha == ref;
+         return alpha == ref;
       case GL_LEQUAL:
-        return alpha <= ref;
+         return alpha <= ref;
       case GL_GREATER:
-        return alpha > ref;
+         return alpha > ref;
       case GL_NOTEQUAL:
-        return alpha != ref;
+         return alpha != ref;
       case GL_GEQUAL:
-        return alpha >= ref;
+         return alpha >= ref;
       case GL_ALWAYS:
-        return GL_TRUE;
+         return GL_TRUE;
       default:
-        assert(0);
-        return GL_FALSE;
+         assert(0);
+         return GL_FALSE;
    }
 }
 
@@ -2364,7 +2367,7 @@ _mesa_meta_Bitmap(struct gl_context *ctx,
     * Check if swrast fallback is needed.
     */
    if (ctx->_ImageTransferState ||
-       ctx->FragmentProgram._Enabled ||
+       _mesa_arb_fragment_program_enabled(ctx) ||
        ctx->Fog.Enabled ||
        ctx->Texture._MaxEnabledTexImageUnit != -1 ||
        width > tex->MaxSize ||
@@ -2389,7 +2392,7 @@ _mesa_meta_Bitmap(struct gl_context *ctx,
                           MESA_META_VERTEX |
                           MESA_META_VIEWPORT));
 
-   _mesa_meta_setup_vertex_objects(ctx, &bitmap->VAO, &bitmap->VBO, false,
+   _mesa_meta_setup_vertex_objects(ctx, &bitmap->VAO, &bitmap->buf_obj, false,
                                    3, 2, 4);
 
    newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat);
@@ -2435,7 +2438,7 @@ _mesa_meta_Bitmap(struct gl_context *ctx,
       }
 
       /* upload new vertex data */
-      _mesa_NamedBufferSubData(bitmap->VBO, 0, sizeof(verts), verts);
+      _mesa_buffer_sub_data(ctx, bitmap->buf_obj, 0, sizeof(verts), verts);
    }
 
    /* choose different foreground/background alpha values */
@@ -2721,25 +2724,17 @@ choose_blit_shader(GLenum target, struct blit_shader_table *table)
 }
 
 void
-_mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table)
+_mesa_meta_blit_shader_table_cleanup(struct gl_context *ctx,
+                                     struct blit_shader_table *table)
 {
-   _mesa_DeleteProgram(table->sampler_1d.shader_prog);
-   _mesa_DeleteProgram(table->sampler_2d.shader_prog);
-   _mesa_DeleteProgram(table->sampler_3d.shader_prog);
-   _mesa_DeleteProgram(table->sampler_rect.shader_prog);
-   _mesa_DeleteProgram(table->sampler_cubemap.shader_prog);
-   _mesa_DeleteProgram(table->sampler_1d_array.shader_prog);
-   _mesa_DeleteProgram(table->sampler_2d_array.shader_prog);
-   _mesa_DeleteProgram(table->sampler_cubemap_array.shader_prog);
-
-   table->sampler_1d.shader_prog = 0;
-   table->sampler_2d.shader_prog = 0;
-   table->sampler_3d.shader_prog = 0;
-   table->sampler_rect.shader_prog = 0;
-   table->sampler_cubemap.shader_prog = 0;
-   table->sampler_1d_array.shader_prog = 0;
-   table->sampler_2d_array.shader_prog = 0;
-   table->sampler_cubemap_array.shader_prog = 0;
+   _mesa_reference_shader_program(ctx, &table->sampler_1d.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_2d.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_3d.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_rect.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_cubemap.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_1d_array.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_2d_array.shader_prog, NULL);
+   _mesa_reference_shader_program(ctx, &table->sampler_cubemap_array.shader_prog, NULL);
 }
 
 /**
@@ -2782,7 +2777,7 @@ get_temp_image_type(struct gl_context *ctx, mesa_format format)
          return GL_UNSIGNED_INT_24_8;
    default:
       _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()",
-                   baseFormat);
+                    baseFormat);
       return 0;
    }
 }
@@ -2792,7 +2787,7 @@ get_temp_image_type(struct gl_context *ctx, mesa_format format)
  * glBlitFramebuffer() to implement glCopyTexSubImage().
  */
 static bool
-copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
+copytexsubimage_using_blit_framebuffer(struct gl_context *ctx,
                                        struct gl_texture_image *texImage,
                                        GLint xoffset,
                                        GLint yoffset,
@@ -2801,7 +2796,7 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
                                        GLint x, GLint y,
                                        GLsizei width, GLsizei height)
 {
-   GLuint fbo;
+   struct gl_framebuffer *drawFb;
    bool success = false;
    GLbitfield mask;
    GLenum status;
@@ -2809,32 +2804,37 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
    if (!ctx->Extensions.ARB_framebuffer_object)
       return false;
 
-   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
+   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+   if (drawFb == NULL)
+      return false;
 
-   _mesa_GenFramebuffers(1, &fbo);
-   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
+   _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer);
 
    if (rb->_BaseFormat == GL_DEPTH_STENCIL ||
        rb->_BaseFormat == GL_DEPTH_COMPONENT) {
-      _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                                texImage, zoffset);
+      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                           GL_DEPTH_ATTACHMENT,
+                                           texImage, zoffset);
       mask = GL_DEPTH_BUFFER_BIT;
 
       if (rb->_BaseFormat == GL_DEPTH_STENCIL &&
           texImage->_BaseFormat == GL_DEPTH_STENCIL) {
-         _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-                                   texImage, zoffset);
+         _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                              GL_STENCIL_ATTACHMENT,
+                                              texImage, zoffset);
          mask |= GL_STENCIL_BUFFER_BIT;
       }
       _mesa_DrawBuffer(GL_NONE);
    } else {
-      _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                texImage, zoffset);
+      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                           GL_COLOR_ATTACHMENT0,
+                                           texImage, zoffset);
       mask = GL_COLOR_BUFFER_BIT;
       _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
    }
 
-   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
    if (status != GL_FRAMEBUFFER_COMPLETE)
       goto out;
 
@@ -2860,7 +2860,7 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
    success = mask == 0x0;
 
  out:
-   _mesa_DeleteFramebuffers(1, &fbo);
+   _mesa_reference_framebuffer(&drawFb, NULL);
    _mesa_meta_end(ctx);
    return success;
 }
@@ -2881,7 +2881,7 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    GLint bpp;
    void *buf;
 
-   if (copytexsubimage_using_blit_framebuffer(ctx, dims,
+   if (copytexsubimage_using_blit_framebuffer(ctx,
                                               texImage,
                                               xoffset, yoffset, zoffset,
                                               rb,
@@ -2926,7 +2926,7 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
     */
    _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER);
    ctx->Driver.ReadPixels(ctx, x, y, width, height,
-                         format, type, &ctx->Pack, buf);
+                          format, type, &ctx->Pack, buf);
    _mesa_meta_end(ctx);
 
    _mesa_update_state(ctx); /* to update pixel transfer state */
@@ -2955,27 +2955,27 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
 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);
+   if (decompress_fbo->fb != NULL) {
+      _mesa_reference_framebuffer(&decompress_fbo->fb, NULL);
+      _mesa_reference_renderbuffer(&decompress_fbo->rb, NULL);
    }
 
    memset(decompress_fbo, 0, sizeof(*decompress_fbo));
 }
 
 static void
-meta_decompress_cleanup(struct decompress_state *decompress)
+meta_decompress_cleanup(struct gl_context *ctx,
+                        struct decompress_state *decompress)
 {
    meta_decompress_fbo_cleanup(&decompress->byteFBO);
    meta_decompress_fbo_cleanup(&decompress->floatFBO);
 
    if (decompress->VAO != 0) {
       _mesa_DeleteVertexArrays(1, &decompress->VAO);
-      _mesa_DeleteBuffers(1, &decompress->VBO);
+      _mesa_reference_buffer_object(ctx, &decompress->buf_obj, NULL);
    }
 
-   if (decompress->Sampler != 0)
-      _mesa_DeleteSamplers(1, &decompress->Sampler);
+   _mesa_reference_sampler_object(ctx, &decompress->samp_obj, NULL);
 
    memset(decompress, 0, sizeof(*decompress));
 }
@@ -3005,7 +3005,7 @@ decompress_texture_image(struct gl_context *ctx,
    GLenum rbFormat;
    GLenum faceTarget;
    struct vertex verts[4];
-   GLuint samplerSave;
+   struct gl_sampler_object *samp_obj_save = NULL;
    GLenum status;
    const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
                                       ctx->Extensions.ARB_fragment_shader;
@@ -3035,10 +3035,6 @@ decompress_texture_image(struct gl_context *ctx,
       assert(!"No compressed 1D textures.");
       return false;
 
-   case GL_TEXTURE_3D:
-      assert(!"No compressed 3D textures.");
-      return false;
-
    case GL_TEXTURE_CUBE_MAP_ARRAY:
       faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6);
       break;
@@ -3054,31 +3050,43 @@ decompress_texture_image(struct gl_context *ctx,
 
    _mesa_meta_begin(ctx, MESA_META_ALL & ~(MESA_META_PIXEL_STORE |
                                            MESA_META_DRAW_BUFFERS));
+   _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
-   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
-         ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
+   _mesa_reference_sampler_object(ctx, &samp_obj_save,
+                                  ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
 
    /* Create/bind FBO/renderbuffer */
-   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_fbo->RBO);
+   if (decompress_fbo->fb == NULL) {
+      decompress_fbo->rb = ctx->Driver.NewRenderbuffer(ctx, 0xDEADBEEF);
+      if (decompress_fbo->rb == NULL) {
+         _mesa_meta_end(ctx);
+         return false;
+      }
+
+      decompress_fbo->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+      if (decompress_fbo->fb == NULL) {
+         _mesa_meta_end(ctx);
+         return false;
+      }
+
+      _mesa_bind_framebuffers(ctx, decompress_fbo->fb, decompress_fbo->fb);
+      _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0,
+                                     decompress_fbo->rb);
    }
    else {
-      _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO);
+      _mesa_bind_framebuffers(ctx, decompress_fbo->fb, decompress_fbo->fb);
    }
 
    /* alloc dest surface */
    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);
+      _mesa_renderbuffer_storage(ctx, decompress_fbo->rb, rbFormat,
+                                 width, height, 0);
+
+      /* Do the full completeness check to recompute
+       * ctx->DrawBuffer->Width/Height.
+       */
+      ctx->DrawBuffer->_Status = GL_FRAMEBUFFER_UNDEFINED;
+      status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
       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
@@ -3091,30 +3099,42 @@ decompress_texture_image(struct gl_context *ctx,
    }
 
    if (use_glsl_version) {
-      _mesa_meta_setup_vertex_objects(ctx, &decompress->VAO, &decompress->VBO, true,
+      _mesa_meta_setup_vertex_objects(ctx, &decompress->VAO,
+                                      &decompress->buf_obj, true,
                                       2, 4, 0);
 
       _mesa_meta_setup_blit_shader(ctx, target, false, &decompress->shaders);
    } else {
-      _mesa_meta_setup_ff_tnl_for_blit(ctx, &decompress->VAO, &decompress->VBO, 3);
+      _mesa_meta_setup_ff_tnl_for_blit(ctx, &decompress->VAO,
+                                       &decompress->buf_obj, 3);
    }
 
-   if (!decompress->Sampler) {
-      _mesa_GenSamplers(1, &decompress->Sampler);
-      _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler);
-      /* nearest filtering */
-      _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-      _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-      /* No sRGB decode or encode.*/
-      if (ctx->Extensions.EXT_texture_sRGB_decode) {
-         _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_SRGB_DECODE_EXT,
-                             GL_SKIP_DECODE_EXT);
+   if (decompress->samp_obj == NULL) {
+      decompress->samp_obj =  ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
+      if (decompress->samp_obj == NULL) {
+         _mesa_meta_end(ctx);
+
+         /* This is a bit lazy.  Flag out of memory, and then don't bother to
+          * clean up.  Once out of memory is flagged, the only realistic next
+          * move is to destroy the context.  That will trigger all the right
+          * clean up.
+          *
+          * Returning true prevents other GetTexImage methods from attempting
+          * anything since they will likely fail too.
+          */
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+         return true;
       }
 
-   } else {
-      _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler);
+      /* nearest filtering */
+      _mesa_set_sampler_filters(ctx, decompress->samp_obj, GL_NEAREST, GL_NEAREST);
+
+      /* We don't want to encode or decode sRGB values; treat them as linear. */
+      _mesa_set_sampler_srgb_decode(ctx, decompress->samp_obj, GL_SKIP_DECODE_EXT);
    }
 
+   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, decompress->samp_obj);
+
    /* Silence valgrind warnings about reading uninitialized stack. */
    memset(verts, 0, sizeof(verts));
 
@@ -3140,10 +3160,10 @@ decompress_texture_image(struct gl_context *ctx,
    _mesa_set_viewport(ctx, 0, 0, 0, width, height);
 
    /* upload new vertex data */
-   _mesa_NamedBufferSubData(decompress->VBO, 0, sizeof(verts), verts);
+   _mesa_buffer_sub_data(ctx, decompress->buf_obj, 0, sizeof(verts), verts);
 
    /* setup texture state */
-   _mesa_BindTexture(target, texObj->Name);
+   _mesa_bind_texture(ctx, target, texObj);
 
    if (!use_glsl_version)
       _mesa_set_enable(ctx, target, GL_TRUE);
@@ -3155,8 +3175,10 @@ decompress_texture_image(struct gl_context *ctx,
 
       /* restrict sampling to the texture level of interest */
       if (target != GL_TEXTURE_RECTANGLE_ARB) {
-         _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level);
-         _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level);
+         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
+                                   (GLint *) &texImage->Level, false);
+         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
+                                   (GLint *) &texImage->Level, false);
       }
 
       /* render quad w/ texture into renderbuffer */
@@ -3166,8 +3188,10 @@ decompress_texture_image(struct gl_context *ctx,
        * be restored by _mesa_meta_end().
        */
       if (target != GL_TEXTURE_RECTANGLE_ARB) {
-         _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
-         _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
+         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
+                                   &baseLevelSave, false);
+         _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
+                                   &maxLevelSave, false);
       }
 
    }
@@ -3187,8 +3211,8 @@ decompress_texture_image(struct gl_context *ctx,
       if (_mesa_need_luminance_to_rgb_conversion(baseTexFormat,
                                                  destBaseFormat) ||
           /* If we're reading back an RGB(A) texture (using glGetTexImage) as
-          * luminance then we need to return L=tex(R).
-          */
+           * luminance then we need to return L=tex(R).
+           */
           _mesa_need_rgb_to_luminance_conversion(baseTexFormat,
                                                  destBaseFormat)) {
          /* Green and blue must be zero */
@@ -3203,7 +3227,8 @@ decompress_texture_image(struct gl_context *ctx,
    if (!use_glsl_version)
       _mesa_set_enable(ctx, target, GL_FALSE);
 
-   _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
+   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save);
+   _mesa_reference_sampler_object(ctx, &samp_obj_save, NULL);
 
    _mesa_meta_end(ctx);
 
@@ -3229,8 +3254,20 @@ _mesa_meta_GetTexSubImage(struct gl_context *ctx,
 
       for (slice = 0; slice < depth; slice++) {
          void *dst;
-         if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY
-             || texImage->TexObject->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
+         /* Section 8.11.4 (Texture Image Queries) of the GL 4.5 spec says:
+          *
+          *    "For three-dimensional, two-dimensional array, cube map array,
+          *     and cube map textures pixel storage operations are applied as
+          *     if the image were two-dimensional, except that the additional
+          *     pixel storage state values PACK_IMAGE_HEIGHT and
+          *     PACK_SKIP_IMAGES are applied. The correspondence of texels to
+          *     memory locations is as defined for TexImage3D in section 8.5."
+          */
+         switch (texImage->TexObject->Target) {
+         case GL_TEXTURE_3D:
+         case GL_TEXTURE_2D_ARRAY:
+         case GL_TEXTURE_CUBE_MAP:
+         case GL_TEXTURE_CUBE_MAP_ARRAY: {
             /* Setup pixel packing.  SkipPixels and SkipRows will be applied
              * in the decompress_texture_image() function's call to
              * glReadPixels but we need to compute the dest slice's address
@@ -3241,9 +3278,11 @@ _mesa_meta_GetTexSubImage(struct gl_context *ctx,
             packing.SkipRows = 0;
             dst = _mesa_image_address3d(&packing, pixels, width, height,
                                         format, type, slice, 0, 0);
+            break;
          }
-         else {
+         default:
             dst = pixels;
+            break;
          }
          result = decompress_texture_image(ctx, texImage, slice,
                                            xoffset, yoffset, width, height,
@@ -3284,36 +3323,50 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
 
    if (drawtex->VAO == 0) {
       /* one-time setup */
-      GLint active_texture;
+      struct gl_vertex_array_object *array_obj;
 
       /* create vertex array object */
       _mesa_GenVertexArrays(1, &drawtex->VAO);
       _mesa_BindVertexArray(drawtex->VAO);
 
+      array_obj = _mesa_lookup_vao(ctx, drawtex->VAO);
+      assert(array_obj != NULL);
+
       /* create vertex array buffer */
-      _mesa_GenBuffers(1, &drawtex->VBO);
-      _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, drawtex->VBO);
-      _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
-                          NULL, GL_DYNAMIC_DRAW_ARB);
+      drawtex->buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF);
+      if (drawtex->buf_obj == NULL)
+         return;
 
-      /* client active texture is not part of the array object */
-      active_texture = ctx->Array.ActiveTexture;
+      _mesa_buffer_data(ctx, drawtex->buf_obj, GL_NONE, sizeof(verts), verts,
+                        GL_DYNAMIC_DRAW, __func__);
 
       /* setup vertex arrays */
-      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
-      _mesa_EnableClientState(GL_VERTEX_ARRAY);
+      FLUSH_VERTICES(ctx, 0);
+      _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_POS,
+                                3, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                GL_FALSE, GL_FALSE,
+                                offsetof(struct vertex, x));
+      _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_POS,
+                               drawtex->buf_obj, 0,
+                               sizeof(struct vertex), true);
+      _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_POS, true);
+
+
       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
-         _mesa_ClientActiveTexture(GL_TEXTURE0 + i);
-         _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(st[i]));
-         _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+         FLUSH_VERTICES(ctx, 0);
+         _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_TEX(i),
+                                   2, GL_FLOAT, GL_RGBA, GL_FALSE,
+                                   GL_FALSE, GL_FALSE,
+                                   offsetof(struct vertex, st[i]));
+         _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_TEX(i),
+                                  drawtex->buf_obj, 0,
+                                  sizeof(struct vertex), true);
+         _mesa_enable_vertex_array_attrib(ctx, array_obj,
+                                          VERT_ATTRIB_TEX(i), true);
       }
-
-      /* restore client active texture */
-      _mesa_ClientActiveTexture(GL_TEXTURE0 + active_texture);
    }
    else {
       _mesa_BindVertexArray(drawtex->VAO);
-      _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, drawtex->VBO);
    }
 
    /* vertex positions, texcoords */
@@ -3378,7 +3431,7 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
          verts[3].st[i][1] = t1;
       }
 
-      _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+      _mesa_buffer_sub_data(ctx, drawtex->buf_obj, 0, sizeof(verts), verts);
    }
 
    _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -3397,10 +3450,11 @@ cleartexsubimage_color(struct gl_context *ctx,
    GLenum datatype;
    GLenum status;
 
-   _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                             texImage, zoffset);
+   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                        GL_COLOR_ATTACHMENT0,
+                                        texImage, zoffset);
 
-   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
    if (status != GL_FRAMEBUFFER_COMPLETE)
       return false;
 
@@ -3440,18 +3494,20 @@ cleartexsubimage_depth_stencil(struct gl_context *ctx,
                                const GLvoid *clearValue,
                                GLint zoffset)
 {
-   GLint stencilValue;
-   GLfloat depthValue;
+   GLint stencilValue = 0;
+   GLfloat depthValue = 0.0f;
    GLenum status;
 
-   _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                             texImage, zoffset);
+   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                        GL_DEPTH_ATTACHMENT,
+                                        texImage, zoffset);
 
    if (texImage->_BaseFormat == GL_DEPTH_STENCIL)
-      _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-                                texImage, zoffset);
+      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                           GL_STENCIL_ATTACHMENT,
+                                           texImage, zoffset);
 
-   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
    if (status != GL_FRAMEBUFFER_COMPLETE)
       return false;
 
@@ -3461,18 +3517,20 @@ cleartexsubimage_depth_stencil(struct gl_context *ctx,
       /* Convert the clearValue from whatever format it's in to a floating
        * point value for the depth and an integer value for the stencil index
        */
-      _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat,
-                                                        1, /* n */
-                                                        clearValue,
-                                                        depthStencilValue);
-      /* We need a memcpy here instead of a cast because we need to
-       * reinterpret the bytes as a float rather than converting it
-       */
-      memcpy(&depthValue, depthStencilValue, sizeof depthValue);
-      stencilValue = depthStencilValue[1] & 0xff;
-   } else {
-      depthValue = 0.0f;
-      stencilValue = 0;
+      if (texImage->_BaseFormat == GL_DEPTH_STENCIL) {
+         _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat,
+                                                           1, /* n */
+                                                           clearValue,
+                                                           depthStencilValue);
+         /* We need a memcpy here instead of a cast because we need to
+          * reinterpret the bytes as a float rather than converting it
+          */
+         memcpy(&depthValue, depthStencilValue, sizeof depthValue);
+         stencilValue = depthStencilValue[1] & 0xff;
+      } else {
+         _mesa_unpack_float_z_row(texImage->TexFormat, 1 /* n */,
+                                  clearValue, &depthValue);
+      }
    }
 
    if (texImage->_BaseFormat == GL_DEPTH_STENCIL)
@@ -3489,11 +3547,14 @@ cleartexsubimage_for_zoffset(struct gl_context *ctx,
                              GLint zoffset,
                              const GLvoid *clearValue)
 {
-   GLuint fbo;
+   struct gl_framebuffer *drawFb;
    bool success;
 
-   _mesa_GenFramebuffers(1, &fbo);
-   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+   if (drawFb == NULL)
+      return false;
+
+   _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer);
 
    switch(texImage->_BaseFormat) {
    case GL_DEPTH_STENCIL:
@@ -3506,7 +3567,7 @@ cleartexsubimage_for_zoffset(struct gl_context *ctx,
       break;
    }
 
-   _mesa_DeleteFramebuffers(1, &fbo);
+   _mesa_reference_framebuffer(&drawFb, NULL);
 
    return success;
 }
@@ -3527,6 +3588,7 @@ cleartexsubimage_using_fbo(struct gl_context *ctx,
                     MESA_META_DITHER |
                     MESA_META_FRAMEBUFFER_SRGB);
 
+   _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
 
    _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);