meta: Use the _mesa_meta_compile_and_link_program helper more places.
[mesa.git] / src / mesa / drivers / common / meta.c
index b38ac902264fd80a101350a1c02d8c5f33e93663..bdcf316e455b81f3a13e4bd4a755dbed461c707a 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"
@@ -95,47 +97,28 @@ 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 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;
-
-      _mesa_FramebufferTexture2D(fboTarget,
-                                 attachment,
-                                 texTarget,
-                                 texObj->Name,
-                                 level);
-   }
+   _mesa_framebuffer_texture(ctx, fb, attachment, texObj, texTarget,
+                             level, layer, false, __func__);
 }
 
 GLuint
@@ -224,8 +207,6 @@ _mesa_meta_compile_and_link_program(struct gl_context *ctx,
    _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);
@@ -247,19 +228,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";
@@ -276,15 +253,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"
@@ -435,12 +413,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);
+   _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->Meta->TempTex);
-   meta_decompress_cleanup(&ctx->Meta->Decompress);
-   meta_drawpix_cleanup(&ctx->Meta->DrawPix);
+   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
@@ -657,7 +635,6 @@ _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;
 
       /* Disable all texture units */
@@ -690,7 +667,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);
    }
 
@@ -742,8 +718,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? */
    }
 
@@ -847,10 +821,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);
    }
 }
 
@@ -1119,7 +1091,6 @@ _mesa_meta_end(struct gl_context *ctx)
 
       /* restore current unit state */
       _mesa_ActiveTexture(GL_TEXTURE0 + save->ActiveUnit);
-      _mesa_ClientActiveTexture(GL_TEXTURE0 + save->ClientActiveUnit);
    }
 
    if (state & MESA_META_TRANSFORM) {
@@ -1153,10 +1124,6 @@ _mesa_meta_end(struct gl_context *ctx)
    }
 
    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);
@@ -1241,15 +1208,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,
@@ -1550,7 +1511,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"
@@ -1559,7 +1521,9 @@ 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"
@@ -1573,24 +1537,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
    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);
@@ -1602,7 +1550,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"
@@ -1613,7 +1562,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"
@@ -1621,42 +1572,26 @@ 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->buf_obj->Name);
-   clear->buf_obj = NULL;
+   _mesa_reference_buffer_object(ctx, &clear->buf_obj, NULL);
    _mesa_DeleteProgram(clear->ShaderProg);
    clear->ShaderProg = 0;
 
@@ -1777,12 +1712,10 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
    if (fb->_IntegerColor) {
       assert(glsl);
       _mesa_UseProgram(clear->IntegerShaderProg);
-      _mesa_Uniform4iv(clear->IntegerColorLocation, 1,
-                         ctx->Color.ClearColor.i);
+      _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_Uniform4fv(0, 1, ctx->Color.ClearColor.f);
    }
 
    /* GL_COLOR_BUFFER_BIT */
@@ -1950,14 +1883,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->buf_obj->Name);
-      drawpix->buf_obj = NULL;
+      _mesa_reference_buffer_object(ctx, &drawpix->buf_obj, NULL);
    }
 
    if (drawpix->StencilFP != 0) {
@@ -2823,7 +2755,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;
@@ -2831,32 +2763,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;
 
@@ -2882,7 +2819,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;
 }
@@ -2977,27 +2914,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->buf_obj->Name);
+      _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));
 }
@@ -3027,7 +2964,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;
@@ -3077,30 +3014,38 @@ decompress_texture_image(struct gl_context *ctx,
    _mesa_meta_begin(ctx, MESA_META_ALL & ~(MESA_META_PIXEL_STORE |
                                            MESA_META_DRAW_BUFFERS));
 
-   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->rb->RefCount = 1;
+
+      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);
+      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
@@ -3123,22 +3068,32 @@ decompress_texture_image(struct gl_context *ctx,
                                        &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));
 
@@ -3180,8 +3135,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 */
@@ -3191,8 +3148,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);
       }
 
    }
@@ -3228,7 +3187,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);
 
@@ -3309,45 +3269,42 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
 
    if (drawtex->VAO == 0) {
       /* one-time setup */
-      GLint active_texture;
-      GLuint VBO;
+      struct gl_vertex_array_object *array_obj;
 
       /* create vertex array object */
       _mesa_GenVertexArrays(1, &drawtex->VAO);
       _mesa_BindVertexArray(drawtex->VAO);
 
-      /* create vertex array buffer */
-      _mesa_CreateBuffers(1, &VBO);
-      drawtex->buf_obj = _mesa_lookup_bufferobj(ctx, VBO);
+      array_obj = _mesa_lookup_vao(ctx, drawtex->VAO);
+      assert(array_obj != NULL);
 
-      /* _mesa_lookup_bufferobj only returns NULL if name is 0.  If the object
-       * does not yet exist (i.e., hasn't been bound) it will return a dummy
-       * object that you can't do anything with.
-       */
-      assert(drawtex->buf_obj != NULL && (drawtex->buf_obj)->Name == VBO);
-      assert(drawtex->buf_obj == ctx->Array.ArrayBufferObj);
+      /* create vertex array buffer */
+      drawtex->buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF);
+      if (drawtex->buf_obj == NULL)
+         return;
 
       _mesa_buffer_data(ctx, drawtex->buf_obj, GL_NONE, sizeof(verts), verts,
                         GL_DYNAMIC_DRAW, __func__);
 
-      assert(drawtex->buf_obj->Size == sizeof(verts));
-
-      /* client active texture is not part of the array object */
-      active_texture = ctx->Array.ActiveTexture;
+      /* setup vertex arrays */
+      _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), true);
+      _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_POS,
+                               drawtex->buf_obj, 0, sizeof(struct vertex));
+      _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_POS);
 
-      _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, VBO);
 
-      /* setup vertex arrays */
-      _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
-      _mesa_EnableClientState(GL_VERTEX_ARRAY);
       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);
+         _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]), true);
+         _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_TEX(i),
+                                  drawtex->buf_obj, 0, sizeof(struct vertex));
+         _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_TEX(i));
       }
-
-      /* restore client active texture */
-      _mesa_ClientActiveTexture(GL_TEXTURE0 + active_texture);
    }
    else {
       _mesa_BindVertexArray(drawtex->VAO);
@@ -3435,10 +3392,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;
 
@@ -3482,14 +3440,16 @@ cleartexsubimage_depth_stencil(struct gl_context *ctx,
    GLfloat depthValue;
    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;
 
@@ -3527,11 +3487,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:
@@ -3544,7 +3507,7 @@ cleartexsubimage_for_zoffset(struct gl_context *ctx,
       break;
    }
 
-   _mesa_DeleteFramebuffers(1, &fbo);
+   _mesa_reference_framebuffer(&drawFb, NULL);
 
    return success;
 }