mesa: Add an index parameter to _mesa_set_viewport
[mesa.git] / src / mesa / drivers / common / meta.c
index 6ee0986b0c63f9481c1b9cfd788417b2eabfcb9f..9a8f7a5a2d53c956a3cac45a8340b16e6194de1f 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.6
  *
  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /**
@@ -170,7 +170,7 @@ struct save_state
    struct gl_buffer_object *ArrayBufferObj;
 
    /** MESA_META_VIEWPORT */
-   GLint ViewportX, ViewportY, ViewportW, ViewportH;
+   GLfloat ViewportX, ViewportY, ViewportW, ViewportH;
    GLclampd DepthNear, DepthFar;
 
    /** MESA_META_CLAMP_FRAGMENT_COLOR */
@@ -241,9 +241,11 @@ struct clear_state
    GLuint VBO;
    GLuint ShaderProg;
    GLint ColorLocation;
+   GLint LayerLocation;
 
    GLuint IntegerShaderProg;
    GLint IntegerColorLocation;
+   GLint IntegerLayerLocation;
 };
 
 
@@ -615,18 +617,16 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
          _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, GL_FALSE);
       }
 
-      if (ctx->Extensions.ARB_shader_objects) {
-        _mesa_reference_shader_program(ctx, &save->VertexShader,
-                                       ctx->Shader.CurrentVertexProgram);
-        _mesa_reference_shader_program(ctx, &save->GeometryShader,
-                                       ctx->Shader.CurrentGeometryProgram);
-        _mesa_reference_shader_program(ctx, &save->FragmentShader,
-                                       ctx->Shader.CurrentFragmentProgram);
-        _mesa_reference_shader_program(ctx, &save->ActiveShader,
-                                       ctx->Shader.ActiveProgram);
-
-         _mesa_UseProgram(0);
-      }
+      _mesa_reference_shader_program(ctx, &save->VertexShader,
+                                     ctx->Shader.CurrentVertexProgram);
+      _mesa_reference_shader_program(ctx, &save->GeometryShader,
+                                     ctx->Shader.CurrentGeometryProgram);
+      _mesa_reference_shader_program(ctx, &save->FragmentShader,
+                                     ctx->Shader.CurrentFragmentProgram);
+      _mesa_reference_shader_program(ctx, &save->ActiveShader,
+                                     ctx->Shader.ActiveProgram);
+
+      _mesa_UseProgram(0);
    }
 
    if (state & MESA_META_STENCIL_TEST) {
@@ -654,7 +654,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
                _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
                if (ctx->Extensions.ARB_texture_cube_map)
                   _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
-               if (ctx->Extensions.OES_EGL_image_external)
+               if (_mesa_is_gles(ctx) &&
+                   ctx->Extensions.OES_EGL_image_external)
                   _mesa_set_enable(ctx, GL_TEXTURE_EXTERNAL_OES, GL_FALSE);
 
                if (ctx->API == API_OPENGL_COMPAT) {
@@ -705,9 +706,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       _mesa_LoadIdentity();
       _mesa_MatrixMode(GL_PROJECTION);
       _mesa_LoadIdentity();
-      _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
-                  0.0, ctx->DrawBuffer->Height,
-                  -1.0, 1.0);
+
+      /* glOrtho with width = 0 or height = 0 generates GL_INVALID_VALUE.
+       * This can occur when there is no draw buffer.
+       */
+      if (ctx->DrawBuffer->Width != 0 && ctx->DrawBuffer->Height != 0)
+         _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
+                     0.0, ctx->DrawBuffer->Height,
+                     -1.0, 1.0);
    }
 
    if (state & MESA_META_CLIP) {
@@ -731,21 +737,21 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
 
    if (state & MESA_META_VIEWPORT) {
       /* save viewport state */
-      save->ViewportX = ctx->Viewport.X;
-      save->ViewportY = ctx->Viewport.Y;
-      save->ViewportW = ctx->Viewport.Width;
-      save->ViewportH = ctx->Viewport.Height;
+      save->ViewportX = ctx->ViewportArray[0].X;
+      save->ViewportY = ctx->ViewportArray[0].Y;
+      save->ViewportW = ctx->ViewportArray[0].Width;
+      save->ViewportH = ctx->ViewportArray[0].Height;
       /* set viewport to match window size */
-      if (ctx->Viewport.X != 0 ||
-          ctx->Viewport.Y != 0 ||
-          ctx->Viewport.Width != ctx->DrawBuffer->Width ||
-          ctx->Viewport.Height != ctx->DrawBuffer->Height) {
-         _mesa_set_viewport(ctx, 0, 0,
+      if (ctx->ViewportArray[0].X != 0 ||
+          ctx->ViewportArray[0].Y != 0 ||
+          ctx->ViewportArray[0].Width != (float) ctx->DrawBuffer->Width ||
+          ctx->ViewportArray[0].Height != (float) ctx->DrawBuffer->Height) {
+         _mesa_set_viewport(ctx, 0, 0, 0,
                             ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
       }
       /* save depth range state */
-      save->DepthNear = ctx->Viewport.Near;
-      save->DepthFar = ctx->Viewport.Far;
+      save->DepthNear = ctx->ViewportArray[0].Near;
+      save->DepthFar = ctx->ViewportArray[0].Far;
       /* set depth range to default */
       _mesa_DepthRange(0.0, 1.0);
    }
@@ -927,9 +933,9 @@ _mesa_meta_end(struct gl_context *ctx)
    }
 
    if (state & MESA_META_SCISSOR) {
-      _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
-      _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
-                    save->Scissor.Width, save->Scissor.Height);
+      _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.EnableFlags);
+      _mesa_Scissor(save->Scissor.ScissorArray[0].X, save->Scissor.ScissorArray[0].Y,
+                    save->Scissor.ScissorArray[0].Width, save->Scissor.ScissorArray[0].Height);
    }
 
    if (state & MESA_META_SHADER) {
@@ -957,7 +963,7 @@ _mesa_meta_end(struct gl_context *ctx)
       if (ctx->Extensions.ARB_vertex_shader)
         _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
 
-      if (ctx->Extensions.ARB_geometry_shader4)
+      if (_mesa_has_geometry_shaders(ctx))
         _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
                                  save->GeometryShader);
 
@@ -1083,11 +1089,11 @@ _mesa_meta_end(struct gl_context *ctx)
    }
 
    if (state & MESA_META_VIEWPORT) {
-      if (save->ViewportX != ctx->Viewport.X ||
-          save->ViewportY != ctx->Viewport.Y ||
-          save->ViewportW != ctx->Viewport.Width ||
-          save->ViewportH != ctx->Viewport.Height) {
-         _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
+      if (save->ViewportX != ctx->ViewportArray[0].X ||
+          save->ViewportY != ctx->ViewportArray[0].Y ||
+          save->ViewportW != ctx->ViewportArray[0].Width ||
+          save->ViewportH != ctx->ViewportArray[0].Height) {
+         _mesa_set_viewport(ctx, 0, save->ViewportX, save->ViewportY,
                             save->ViewportW, save->ViewportH);
       }
       _mesa_DepthRange(save->DepthNear, save->DepthFar);
@@ -1511,6 +1517,9 @@ setup_glsl_blit_framebuffer(struct gl_context *ctx,
                                    sizeof(struct vertex), OFFSET(x));
       _mesa_VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
                                    sizeof(struct vertex), OFFSET(s));
+
+      _mesa_EnableVertexAttribArray(0);
+      _mesa_EnableVertexAttribArray(1);
    }
 
    /* Generate a relevant fragment shader program for the texture target */
@@ -1533,6 +1542,9 @@ setup_glsl_blit_framebuffer(struct gl_context *ctx,
          "}\n";
 
       fs_source = ralloc_asprintf(mem_ctx,
+                                  "#ifdef GL_ES\n"
+                                  "precision highp float;\n"
+                                  "#endif\n"
                                   "uniform %s texSampler;\n"
                                   "varying vec2 texCoords;\n"
                                   "void main()\n"
@@ -1557,6 +1569,9 @@ setup_glsl_blit_framebuffer(struct gl_context *ctx,
                                   _mesa_is_desktop_gl(ctx) ? "130" : "300 es");
       fs_source = ralloc_asprintf(mem_ctx,
                                   "#version %s\n"
+                                  "#ifdef GL_ES\n"
+                                  "precision highp float;\n"
+                                  "#endif\n"
                                   "uniform %s texSampler;\n"
                                   "in vec2 texCoords;\n"
                                   "out vec4 out_color;\n"
@@ -1581,8 +1596,6 @@ setup_glsl_blit_framebuffer(struct gl_context *ctx,
    _mesa_DeleteObjectARB(vs);
    _mesa_BindAttribLocation(ShaderProg, 0, "position");
    _mesa_BindAttribLocation(ShaderProg, 1, "texcoords");
-   _mesa_EnableVertexAttribArray(0);
-   _mesa_EnableVertexAttribArray(1);
    link_program_with_debug(ctx, ShaderProg);
    ralloc_free(mem_ctx);
    if (texture_2d)
@@ -1719,10 +1732,10 @@ blitframebuffer_texture(struct gl_context *ctx,
             }
             else {
                assert(target == GL_TEXTURE_RECTANGLE_ARB);
-               s0 = srcX0;
-               s1 = srcX1;
-               t0 = srcY0;
-               t1 = srcY1;
+               s0 = (float) srcX0;
+               s1 = (float) srcX1;
+               t0 = (float) srcY0;
+               t1 = (float) srcY1;
             }
 
             /* setup vertex positions */
@@ -1748,7 +1761,7 @@ blitframebuffer_texture(struct gl_context *ctx,
          }
 
          /* setup viewport */
-         _mesa_set_viewport(ctx, dstX, dstY, dstW, dstH);
+         _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
          _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
          _mesa_DepthMask(GL_FALSE);
          _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1880,25 +1893,30 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx,
       const GLenum rb_base_format =
          _mesa_base_tex_format(ctx, colorReadRb->InternalFormat);
 
-      newTex = alloc_texture(tex, srcW, srcH, rb_base_format);
-      setup_copypix_texture(ctx, tex, newTex, srcX, srcY, srcW, srcH,
+      /* Using  the exact source rectangle to create the texture does incorrect
+       * linear filtering along the edges. So, allocate the texture extended along
+       * edges by one pixel in x, y directions.
+       */
+      newTex = alloc_texture(tex, srcW + 2, srcH + 2, rb_base_format);
+      setup_copypix_texture(ctx, tex, newTex,
+                            srcX - 1, srcY - 1, srcW + 2, srcH + 2,
                             rb_base_format, filter);
       /* texcoords (after texture allocation!) */
       {
-         verts[0].s = 0.0F;
-         verts[0].t = 0.0F;
-         verts[1].s = tex->Sright;
-         verts[1].t = 0.0F;
-         verts[2].s = tex->Sright;
-         verts[2].t = tex->Ttop;
-         verts[3].s = 0.0F;
-         verts[3].t = tex->Ttop;
+         verts[0].s = 1.0F;
+         verts[0].t = 1.0F;
+         verts[1].s = tex->Sright - 1.0F;
+         verts[1].t = 1.0F;
+         verts[2].s = tex->Sright - 1.0F;
+         verts[2].t = tex->Ttop - 1.0F;
+         verts[3].s = 1.0F;
+         verts[3].t = tex->Ttop - 1.0F;
 
          /* upload new vertex data */
          _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
       }
 
-      _mesa_set_viewport(ctx, dstX, dstY, dstW, dstH);
+      _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
       _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
       _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
       _mesa_DepthMask(GL_FALSE);
@@ -1947,7 +1965,7 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx,
          _mesa_DepthFunc(GL_ALWAYS);
          _mesa_DepthMask(GL_TRUE);
 
-         _mesa_set_viewport(ctx, dstX, dstY, dstW, dstH);
+         _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
          _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
          _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
          mask &= ~GL_DEPTH_BUFFER_BIT;
@@ -2129,13 +2147,29 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
       "{\n"
       "   gl_Position = position;\n"
       "}\n";
+   const char *gs_source =
+      "#version 150\n"
+      "layout(triangles) in;\n"
+      "layout(triangle_strip, max_vertices = 4) out;\n"
+      "uniform int layer;\n"
+      "void main()\n"
+      "{\n"
+      "  for (int i = 0; i < 3; i++) {\n"
+      "    gl_Layer = layer;\n"
+      "    gl_Position = gl_in[i].gl_Position;\n"
+      "    EmitVertex();\n"
+      "  }\n"
+      "}\n";
    const char *fs_source =
+      "#ifdef GL_ES\n"
+      "precision highp float;\n"
+      "#endif\n"
       "uniform vec4 color;\n"
       "void main()\n"
       "{\n"
       "   gl_FragColor = color;\n"
       "}\n";
-   GLuint vs, fs;
+   GLuint vs, gs = 0, fs;
    bool has_integer_textures;
 
    if (clear->ArrayObj != 0)
@@ -2157,6 +2191,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
    _mesa_ShaderSource(vs, 1, &vs_source, NULL);
    _mesa_CompileShader(vs);
 
+   if (_mesa_has_geometry_shaders(ctx)) {
+      gs = _mesa_CreateShaderObjectARB(GL_GEOMETRY_SHADER);
+      _mesa_ShaderSource(gs, 1, &gs_source, NULL);
+      _mesa_CompileShader(gs);
+   }
+
    fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
    _mesa_ShaderSource(fs, 1, &fs_source, NULL);
    _mesa_CompileShader(fs);
@@ -2164,6 +2204,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
    clear->ShaderProg = _mesa_CreateProgramObjectARB();
    _mesa_AttachShader(clear->ShaderProg, fs);
    _mesa_DeleteObjectARB(fs);
+   if (gs != 0)
+      _mesa_AttachShader(clear->ShaderProg, gs);
    _mesa_AttachShader(clear->ShaderProg, vs);
    _mesa_DeleteObjectARB(vs);
    _mesa_BindAttribLocation(clear->ShaderProg, 0, "position");
@@ -2171,6 +2213,10 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
 
    clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg,
                                                      "color");
+   if (gs != 0) {
+      clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg,
+                                                     "layer");
+   }
 
    has_integer_textures = _mesa_is_gles3(ctx) ||
       (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130);
@@ -2189,6 +2235,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 %s\n"
+                         "#ifdef GL_ES\n"
+                         "precision highp float;\n"
+                         "#endif\n"
                          "uniform ivec4 color;\n"
                          "out ivec4 out_color;\n"
                          "\n"
@@ -2205,6 +2254,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
       clear->IntegerShaderProg = _mesa_CreateProgramObjectARB();
       _mesa_AttachShader(clear->IntegerShaderProg, fs);
       _mesa_DeleteObjectARB(fs);
+      if (gs != 0)
+         _mesa_AttachShader(clear->IntegerShaderProg, gs);
       _mesa_AttachShader(clear->IntegerShaderProg, vs);
       _mesa_DeleteObjectARB(vs);
       _mesa_BindAttribLocation(clear->IntegerShaderProg, 0, "position");
@@ -2218,7 +2269,13 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
 
       clear->IntegerColorLocation =
         _mesa_GetUniformLocation(clear->IntegerShaderProg, "color");
+      if (gs != 0) {
+         clear->IntegerLayerLocation =
+            _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer");
+      }
    }
+   if (gs != 0)
+      _mesa_DeleteObjectARB(gs);
 }
 
 static void
@@ -2349,8 +2406,19 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
    _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
                       GL_DYNAMIC_DRAW_ARB);
 
-   /* draw quad */
-   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+   /* draw quad(s) */
+   if (fb->MaxNumLayers > 0) {
+      unsigned layer;
+      for (layer = 0; layer < fb->MaxNumLayers; layer++) {
+         if (fb->_IntegerColor)
+            _mesa_Uniform1i(clear->IntegerLayerLocation, layer);
+         else
+            _mesa_Uniform1i(clear->LayerLocation, layer);
+         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      }
+   } else {
+      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+   }
 
    _mesa_meta_end(ctx);
 }
@@ -2804,7 +2872,7 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
             _mesa_StencilMask(mask);
 
             _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
-                                             255.0 / mask, 0.5, 0.0, 0.0);
+                                             255.0f / mask, 0.5f, 0.0f, 0.0f);
 
             _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
          }
@@ -3048,12 +3116,6 @@ _mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
    GLenum status;
 
    /* check for fallbacks */
-   if (!ctx->Extensions.EXT_framebuffer_object) {
-      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
-                       "glGenerateMipmap() without FBOs\n");
-      return GL_TRUE;
-   }
-
    if (target == GL_TEXTURE_3D ||
        target == GL_TEXTURE_1D_ARRAY ||
        target == GL_TEXTURE_2D_ARRAY) {
@@ -3169,7 +3231,7 @@ setup_texture_coords(GLenum faceTarget,
          r = (slice + 0.5f) / depth;
       }
       else if (faceTarget == GL_TEXTURE_2D_ARRAY)
-         r = slice;
+         r = (float) slice;
       else
          r = 0.0F;
       coords0[0] = 0.0F; /* s */
@@ -3189,28 +3251,28 @@ setup_texture_coords(GLenum faceTarget,
       coords0[0] = 0.0F; /* s */
       coords0[1] = 0.0F; /* t */
       coords0[2] = 0.0F; /* r */
-      coords1[0] = width;
+      coords1[0] = (float) width;
       coords1[1] = 0.0F;
       coords1[2] = 0.0F;
-      coords2[0] = width;
-      coords2[1] = height;
+      coords2[0] = (float) width;
+      coords2[1] = (float) height;
       coords2[2] = 0.0F;
       coords3[0] = 0.0F;
-      coords3[1] = height;
+      coords3[1] = (float) height;
       coords3[2] = 0.0F;
       break;
    case GL_TEXTURE_1D_ARRAY:
       coords0[0] = 0.0F; /* s */
-      coords0[1] = slice; /* t */
+      coords0[1] = (float) slice; /* t */
       coords0[2] = 0.0F; /* r */
       coords1[0] = 1.0f;
-      coords1[1] = slice;
+      coords1[1] = (float) slice;
       coords1[2] = 0.0F;
       coords2[0] = 1.0F;
-      coords2[1] = slice;
+      coords2[1] = (float) slice;
       coords2[2] = 0.0F;
       coords3[0] = 0.0F;
-      coords3[1] = slice;
+      coords3[1] = (float) slice;
       coords3[2] = 0.0F;
       break;
 
@@ -3396,6 +3458,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
                                    sizeof(struct vertex), OFFSET(x));
       _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
                                    sizeof(struct vertex), OFFSET(tex));
+      _mesa_EnableVertexAttribArray(0);
+      _mesa_EnableVertexAttribArray(1);
    }
 
    /* Generate a fragment shader program appropriate for the texture target */
@@ -3421,6 +3485,9 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
 
       fs_source = ralloc_asprintf(mem_ctx,
                                   "#extension GL_EXT_texture_array : enable\n"
+                                  "#ifdef GL_ES\n"
+                                  "precision highp float;\n"
+                                  "#endif\n"
                                   "uniform %s texSampler;\n"
                                   "varying vec3 texCoords;\n"
                                   "void main()\n"
@@ -3444,6 +3511,9 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
                                   _mesa_is_desktop_gl(ctx) ? "130" : "300 es");
       fs_source = ralloc_asprintf(mem_ctx,
                                   "#version %s\n"
+                                  "#ifdef GL_ES\n"
+                                  "precision highp float;\n"
+                                  "#endif\n"
                                   "uniform %s texSampler;\n"
                                   "in vec3 texCoords;\n"
                                   "out vec4 out_color;\n"
@@ -3467,8 +3537,6 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
    _mesa_DeleteObjectARB(vs);
    _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position");
    _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords");
-   _mesa_EnableVertexAttribArray(0);
-   _mesa_EnableVertexAttribArray(1);
    link_program_with_debug(ctx, mipmap->ShaderProg);
    sampler->shader_prog = mipmap->ShaderProg;
    ralloc_free(mem_ctx);
@@ -3714,7 +3782,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       assert(dstHeight == ctx->DrawBuffer->Height);
 
       /* setup viewport */
-      _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight);
+      _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
 
       _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }
@@ -3763,10 +3831,20 @@ get_temp_image_type(struct gl_context *ctx, gl_format format)
             return datatype;
          return GL_FLOAT;
       }
-   case GL_DEPTH_COMPONENT:
-      return GL_UNSIGNED_INT;
-   case GL_DEPTH_STENCIL:
-      return GL_UNSIGNED_INT_24_8;
+   case GL_DEPTH_COMPONENT: {
+      GLenum datatype = _mesa_get_format_datatype(format);
+      if (datatype == GL_FLOAT)
+         return GL_FLOAT;
+      else
+         return GL_UNSIGNED_INT;
+   }
+   case GL_DEPTH_STENCIL: {
+      GLenum datatype = _mesa_get_format_datatype(format);
+      if (datatype == GL_FLOAT)
+         return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
+      else
+         return GL_UNSIGNED_INT_24_8;
+   }
    default:
       _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()",
                    baseFormat);
@@ -3840,9 +3918,16 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
     */
    _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
 
-   ctx->Driver.TexSubImage(ctx, dims, texImage,
-                           xoffset, yoffset, zoffset, width, height, 1,
-                           format, type, buf, &ctx->Unpack);
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      assert(yoffset == 0);
+      ctx->Driver.TexSubImage(ctx, dims, texImage,
+                              xoffset, zoffset, 0, width, 1, 1,
+                              format, type, buf, &ctx->Unpack);
+   } else {
+      ctx->Driver.TexSubImage(ctx, dims, texImage,
+                              xoffset, yoffset, zoffset, width, height, 1,
+                              format, type, buf, &ctx->Unpack);
+   }
 
    _mesa_meta_end(ctx);
 
@@ -3984,6 +4069,11 @@ decompress_texture_image(struct gl_context *ctx,
    verts[3].x = 0.0F;
    verts[3].y = height;
 
+   _mesa_MatrixMode(GL_PROJECTION);
+   _mesa_LoadIdentity();
+   _mesa_Ortho(0.0, width, 0.0, height, -1.0, 1.0);
+   _mesa_set_viewport(ctx, 0, 0, 0, width, height);
+
    /* upload new vertex data */
    _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
 
@@ -4085,10 +4175,29 @@ _mesa_meta_GetTexImage(struct gl_context *ctx,
        _mesa_get_format_datatype(texImage->TexFormat)
        == GL_UNSIGNED_NORMALIZED) {
       struct gl_texture_object *texObj = texImage->TexObject;
-      const GLuint slice = 0; /* only 2D compressed textures for now */
+      GLuint slice;
       /* Need to unlock the texture here to prevent deadlock... */
       _mesa_unlock_texture(ctx, texObj);
-      decompress_texture_image(ctx, texImage, slice, format, type, pixels);
+      for (slice = 0; slice < texImage->Depth; slice++) {
+         void *dst;
+         if (texImage->TexObject->Target == GL_TEXTURE_2D_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
+             * here (according to SkipImages and ImageHeight).
+             */
+            struct gl_pixelstore_attrib packing = ctx->Pack;
+            packing.SkipPixels = 0;
+            packing.SkipRows = 0;
+            dst = _mesa_image_address3d(&packing, pixels, texImage->Width,
+                                        texImage->Height, format, type,
+                                        slice, 0, 0);
+         }
+         else {
+            dst = pixels;
+         }
+         decompress_texture_image(ctx, texImage, slice, format, type, dst);
+      }
       /* ... and relock it */
       _mesa_lock_texture(ctx, texObj);
    }