mesa: Use correct data for MAX_{VERTEX,GEOMETRY}_VARYING_COMPONENTS_ARB queries
[mesa.git] / src / mesa / main / teximage.c
index ccdb95a67d8b8f3fe66914211c52b808724fc0f6..b719fc856a1a1633bf5b18d96b5c936450fd748a 100644 (file)
  * 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.
  */
 
 
@@ -39,7 +40,6 @@
 #include "image.h"
 #include "imports.h"
 #include "macros.h"
-#include "mfeatures.h"
 #include "multisample.h"
 #include "state.h"
 #include "texcompress.h"
@@ -180,7 +180,7 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
    default:
       ; /* fallthrough */
    }
-         
+
    if (ctx->Extensions.TDFX_texture_compression_FXT1) {
       switch (internalFormat) {
          case GL_COMPRESSED_RGB_FXT1_3DFX:
@@ -315,15 +315,17 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
       case GL_SRGB_EXT:
       case GL_SRGB8_EXT:
       case GL_COMPRESSED_SRGB_EXT:
-      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
          return GL_RGB;
+      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+         return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGB : -1;
       case GL_SRGB_ALPHA_EXT:
       case GL_SRGB8_ALPHA8_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_EXT:
+         return GL_RGBA;
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-         return GL_RGBA;
+         return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGBA : -1;
       case GL_SLUMINANCE_ALPHA_EXT:
       case GL_SLUMINANCE8_ALPHA8_EXT:
       case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
@@ -613,7 +615,7 @@ set_tex_image(struct gl_texture_object *tObj,
 
 /**
  * Allocate a texture image structure.
- * 
+ *
  * Called via ctx->Driver.NewTextureImage() unless overriden by a device
  * driver.
  *
@@ -796,7 +798,7 @@ _mesa_select_tex_object(struct gl_context *ctx,
                 ctx->Extensions.ARB_texture_buffer_object ?
                 texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
       case GL_TEXTURE_EXTERNAL_OES:
-         return ctx->Extensions.OES_EGL_image_external
+         return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
             ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
       case GL_TEXTURE_2D_MULTISAMPLE:
          return ctx->Extensions.ARB_texture_multisample
@@ -868,7 +870,7 @@ _mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
 
    if (!texObj)
       return NULL;
-   
+
    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!texImage) {
       texImage = ctx->Driver.NewTextureImage(ctx);
@@ -974,7 +976,7 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
  *
  * \param ctx GL context.
  * \param target texture target.
- * 
+ *
  * \return the maximum number of allowed mipmap levels for the given
  * texture target, or zero if passed a bad target.
  *
@@ -1095,24 +1097,34 @@ _mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height,
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_TEXTURE_1D_ARRAY:
+   case GL_PROXY_TEXTURE_1D:
+   case GL_PROXY_TEXTURE_1D_ARRAY:
       size = width;
       break;
    case GL_TEXTURE_CUBE_MAP:
    case GL_TEXTURE_CUBE_MAP_ARRAY:
+   case GL_PROXY_TEXTURE_CUBE_MAP:
+   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
       ASSERT(width == height);
       size = width;
       break;
    case GL_TEXTURE_2D:
    case GL_TEXTURE_2D_ARRAY:
+   case GL_PROXY_TEXTURE_2D:
+   case GL_PROXY_TEXTURE_2D_ARRAY:
       size = MAX2(width, height);
       break;
    case GL_TEXTURE_3D:
+   case GL_PROXY_TEXTURE_3D:
       size = MAX3(width, height, depth);
       break;
    case GL_TEXTURE_RECTANGLE:
    case GL_TEXTURE_EXTERNAL_OES:
    case GL_TEXTURE_2D_MULTISAMPLE:
    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+   case GL_PROXY_TEXTURE_RECTANGLE:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
       return 1;
    default:
       assert(0);
@@ -1536,13 +1548,13 @@ error_check_subtexture_dimensions(struct gl_context *ctx,
    }
 
    /* check xoffset and width */
-   if (xoffset < -destImage->Border) {
+   if (xoffset < - (GLint) destImage->Border) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset)",
                   function, dims);
       return GL_TRUE;
    }
 
-   if (xoffset + subWidth > destImage->Width) {
+   if (xoffset + subWidth > (GLint) destImage->Width) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset+width)",
                   function, dims);
       return GL_TRUE;
@@ -1556,7 +1568,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx,
                      function, dims);
          return GL_TRUE;
       }
-      if (yoffset + subHeight > destImage->Height) {
+      if (yoffset + subHeight > (GLint) destImage->Height) {
          _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset+height)",
                      function, dims);
          return GL_TRUE;
@@ -1594,18 +1606,24 @@ error_check_subtexture_dimensions(struct gl_context *ctx,
          return GL_TRUE;
       }
 
-      /* size must be multiple of bw by bh or equal to whole texture size */
-      if ((subWidth % bw != 0) && subWidth != destImage->Width) {
+      /* The size must be a multiple of bw x bh, or we must be using a
+       * offset+size that exactly hits the edge of the image.  This
+       * is important for small mipmap levels (1x1, 2x1, etc) and for
+       * NPOT textures.
+       */
+      if ((subWidth % bw != 0) &&
+          (xoffset + subWidth != (GLint) destImage->Width)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s%dD(width = %d)", function, dims, subWidth);
          return GL_TRUE;
       }
 
-      if ((subHeight % bh != 0) && subHeight != destImage->Height) {
+      if ((subHeight % bh != 0) &&
+          (yoffset + subHeight != (GLint) destImage->Height)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s%dD(height = %d)", function, dims, subHeight);
          return GL_TRUE;
-      }         
+      }
    }
 
    return GL_FALSE;
@@ -1705,7 +1723,7 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target,
       return ctx->Extensions.ARB_texture_cube_map_array;
    default:
       return GL_FALSE;
-   }      
+   }
 }
 
 
@@ -1844,12 +1862,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
 static GLboolean
 mutable_tex_object(struct gl_context *ctx, GLenum target)
 {
-   if (ctx->Extensions.ARB_texture_storage) {
-      struct gl_texture_object *texObj =
-         _mesa_get_current_tex_object(ctx, target);
-      return !texObj->Immutable;
-   }
-   return GL_TRUE;
+   struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
+   return !texObj->Immutable;
 }
 
 
@@ -1867,7 +1881,7 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
 
 /**
  * Test the glTexImage[123]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user (already validated).
@@ -1879,7 +1893,7 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
  * \param height image height given by the user.
  * \param depth image depth given by the user.
  * \param border image border given by the user.
- * 
+ *
  * \return GL_TRUE if a error is found, GL_FALSE otherwise
  *
  * Verifies each of the parameters against the constants specified in
@@ -1949,12 +1963,12 @@ texture_error_check( struct gl_context *ctx,
                                                      internalFormat);
       } else {
          if (format != internalFormat) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glTexImage%dD(format = %s, internalFormat = %s)",
-                     dimensions,
-                     _mesa_lookup_enum_by_nr(format),
-                     _mesa_lookup_enum_by_nr(internalFormat));
-         return GL_TRUE;
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glTexImage%dD(format = %s, internalFormat = %s)",
+                        dimensions,
+                        _mesa_lookup_enum_by_nr(format),
+                        _mesa_lookup_enum_by_nr(internalFormat));
+            return GL_TRUE;
          }
 
          err = _mesa_es_error_check_format_and_type(format, type, dimensions);
@@ -2258,7 +2272,7 @@ error:
 
 /**
  * Test glTexSubImage[123]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user (already validated)
@@ -2271,7 +2285,7 @@ error:
  * \param width image width given by the user.
  * \param height image height given by the user.
  * \param depth image depth given by the user.
- * 
+ *
  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
  *
  * Verifies each of the parameters against the constants specified in
@@ -2376,7 +2390,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
 
 /**
  * Test glCopyTexImage[12]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user.
@@ -2385,9 +2399,9 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
  * \param width image width given by the user.
  * \param height image height given by the user.
  * \param border texture border.
- * 
+ *
  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- * 
+ *
  * Verifies each of the parameters against the constants specified in
  * __struct gl_contextRec::Const and the supported extensions, and according
  * to the OpenGL specification.
@@ -2407,7 +2421,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
       _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
                   dimensions, _mesa_lookup_enum_by_nr(target));
       return GL_TRUE;
-   }       
+   }
 
    /* level check */
    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
@@ -2753,9 +2767,8 @@ check_rtt_cb(GLuint key, void *data, void *userData)
              att->Texture == texObj &&
              att->TextureLevel == level &&
              att->CubeMapFace == face) {
-            ASSERT(_mesa_get_attachment_teximage(att));
-            /* Tell driver about the new renderbuffer texture */
-            ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+            _mesa_update_texture_renderbuffer(ctx, ctx->DrawBuffer, att);
+            ASSERT(att->Renderbuffer->TexImage);
             /* Mark fb status as indeterminate to force re-validation */
             fb->_Status = 0;
          }
@@ -2920,6 +2933,7 @@ _mesa_choose_texture_format(struct gl_context *ctx,
    return f;
 }
 
+
 /**
  * Adjust pixel unpack params and image dimensions to strip off the
  * one-pixel texture border.
@@ -2957,7 +2971,9 @@ strip_texture_border(GLenum target,
       *height = *height - 2;  /* reduce the height by two border pixels */
    }
 
-   if (*depth >= 3 && target != GL_TEXTURE_2D_ARRAY && target != GL_TEXTURE_CUBE_MAP_ARRAY) {
+   if (*depth >= 3 &&
+       target != GL_TEXTURE_2D_ARRAY &&
+       target != GL_TEXTURE_CUBE_MAP_ARRAY) {
       unpackNew->SkipImages++;  /* skip the border */
       *depth = *depth - 2;      /* reduce the depth by two border pixels */
    }
@@ -3233,7 +3249,8 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
       valid_target = ctx->Extensions.OES_EGL_image;
       break;
    case GL_TEXTURE_EXTERNAL_OES:
-      valid_target = ctx->Extensions.OES_EGL_image_external;
+      valid_target =
+         _mesa_is_gles(ctx) ? ctx->Extensions.OES_EGL_image_external : false;
       break;
    default:
       valid_target = false;
@@ -3309,7 +3326,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
                   dims, _mesa_lookup_enum_by_nr(target));
       return;
-   }       
+   }
 
    if (ctx->NewState & _NEW_PIXEL)
       _mesa_update_state(ctx);
@@ -3418,6 +3435,35 @@ get_copy_tex_image_source(struct gl_context *ctx, gl_format texFormat)
    }
 }
 
+static void
+copytexsubimage_by_slice(struct gl_context *ctx,
+                         struct gl_texture_image *texImage,
+                         GLuint dims,
+                         GLint xoffset, GLint yoffset, GLint zoffset,
+                         struct gl_renderbuffer *rb,
+                         GLint x, GLint y,
+                         GLsizei width, GLsizei height)
+{
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      int slice;
+
+      /* For 1D arrays, we copy each scanline of the source rectangle into the
+       * next array slice.
+       */
+      assert(zoffset == 0);
+
+      for (slice = 0; slice < height; slice++) {
+         assert(yoffset + slice < texImage->Height);
+         ctx->Driver.CopyTexSubImage(ctx, 2, texImage,
+                                     xoffset, 0, yoffset + slice,
+                                     rb, x, y + slice, width, 1);
+      }
+   } else {
+      ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
+                                  xoffset, yoffset, zoffset,
+                                  rb, x, y, width, height);
+   }
+}
 
 
 /**
@@ -3506,8 +3552,9 @@ copyteximage(struct gl_context *ctx, GLuint dims,
                struct gl_renderbuffer *srcRb =
                   get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-               ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
-                                           srcRb, srcX, srcY, width, height);
+               copytexsubimage_by_slice(ctx, texImage, dims,
+                                        dstX, dstY, dstZ,
+                                        srcRb, srcX, srcY, width, height);
             }
 
             check_gen_mipmap(ctx, target, texObj, level);
@@ -3599,9 +3646,9 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
          struct gl_renderbuffer *srcRb =
             get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-         ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
-                                     xoffset, yoffset, zoffset,
-                                     srcRb, x, y, width, height);
+         copytexsubimage_by_slice(ctx, texImage, dims,
+                                  xoffset, yoffset, zoffset,
+                                  srcRb, x, y, width, height);
 
          check_gen_mipmap(ctx, target, texObj, level);
 
@@ -3694,7 +3741,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
       targetOK = GL_FALSE;
       break;
    }
+
    if (!targetOK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target)",
                   dims);
@@ -4027,6 +4074,7 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    }
 }
 
+
 static gl_format
 validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
 {
@@ -4098,6 +4146,7 @@ texbufferrange(struct gl_context *ctx, GLenum target, GLenum internalFormat,
    _mesa_unlock_texture(ctx, texObj);
 }
 
+
 /** GL_ARB_texture_buffer_object */
 void GLAPIENTRY
 _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
@@ -4124,6 +4173,7 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
    texbufferrange(ctx, target, internalFormat, bufObj, 0, buffer ? -1 : 0);
 }
 
+
 /** GL_ARB_texture_buffer_range */
 void GLAPIENTRY
 _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
@@ -4164,6 +4214,7 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
    texbufferrange(ctx, target, internalFormat, bufObj, offset, size);
 }
 
+
 static GLboolean
 is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
 {
@@ -4174,6 +4225,7 @@ is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
    return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
 }
 
+
 /** GL_ARB_texture_multisample */
 static GLboolean
 check_multisample_target(GLuint dims, GLenum target)
@@ -4192,6 +4244,7 @@ check_multisample_target(GLuint dims, GLenum target)
    }
 }
 
+
 static void
 teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
                     GLint internalformat, GLsizei width, GLsizei height,
@@ -4309,7 +4362,6 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
       texImage->FixedSampleLocations = fixedsamplelocations;
 
       if (width > 0 && height > 0 && depth > 0) {
-
          if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1,
                   width, height, depth)) {
             /* tidy up the texture image state. strictly speaking,
@@ -4326,15 +4378,18 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
    }
 }
 
+
 void GLAPIENTRY
 _mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
                             GLint internalformat, GLsizei width,
                             GLsizei height, GLboolean fixedsamplelocations)
 {
    teximagemultisample(2, target, samples, internalformat,
-         width, height, 1, fixedsamplelocations, GL_FALSE, "glTexImage2DMultisample");
+                       width, height, 1, fixedsamplelocations, GL_FALSE,
+                       "glTexImage2DMultisample");
 }
 
+
 void GLAPIENTRY
 _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
                             GLint internalformat, GLsizei width,
@@ -4342,25 +4397,29 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
                             GLboolean fixedsamplelocations)
 {
    teximagemultisample(3, target, samples, internalformat,
-         width, height, depth, fixedsamplelocations, GL_FALSE, "glTexImage3DMultisample");
+                       width, height, depth, fixedsamplelocations, GL_FALSE,
+                       "glTexImage3DMultisample");
 }
 
 
 void GLAPIENTRY
 _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
-                              GLint internalformat, GLsizei width,
+                              GLenum internalformat, GLsizei width,
                               GLsizei height, GLboolean fixedsamplelocations)
 {
    teximagemultisample(2, target, samples, internalformat,
-         width, height, 1, fixedsamplelocations, GL_TRUE, "glTexStorage2DMultisample");
+                       width, height, 1, fixedsamplelocations, GL_TRUE,
+                       "glTexStorage2DMultisample");
 }
 
+
 void GLAPIENTRY
 _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
-                              GLint internalformat, GLsizei width,
+                              GLenum internalformat, GLsizei width,
                               GLsizei height, GLsizei depth,
                               GLboolean fixedsamplelocations)
 {
    teximagemultisample(3, target, samples, internalformat,
-         width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample");
+                       width, height, depth, fixedsamplelocations, GL_TRUE,
+                       "glTexStorage3DMultisample");
 }