mesa: make _mesa_get_framebuffer_attachment_parameter() static
[mesa.git] / src / mesa / main / fbobject.c
index fa5baa3517b19ea1aff8a5f2b3e965e26c5b75a0..ef4fecff2aeac1c5247dc137c0aa676bb7683e4a 100644 (file)
@@ -222,15 +222,21 @@ get_framebuffer_target(struct gl_context *ctx, GLenum target)
  * default / window-system FB object.
  * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
  * the depth buffer attachment point.
+ * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
+ * is_color_attachment, because several callers would return different errors
+ * if they don't find the attachment.
  */
 static struct gl_renderbuffer_attachment *
 get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
-               GLenum attachment)
+               GLenum attachment, bool *is_color_attachment)
 {
    GLuint i;
 
    assert(_mesa_is_user_fbo(fb));
 
+   if (is_color_attachment)
+      *is_color_attachment = false;
+
    switch (attachment) {
    case GL_COLOR_ATTACHMENT0_EXT:
    case GL_COLOR_ATTACHMENT1_EXT:
@@ -248,6 +254,8 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_COLOR_ATTACHMENT13_EXT:
    case GL_COLOR_ATTACHMENT14_EXT:
    case GL_COLOR_ATTACHMENT15_EXT:
+      if (is_color_attachment)
+         *is_color_attachment = true;
       /* Only OpenGL ES 1.x forbids color attachments other than
        * GL_COLOR_ATTACHMENT0.  For all other APIs the limit set by the
        * hardware is used.
@@ -277,8 +285,8 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
  * window-system framebuffer (not user-created framebuffer objects).
  */
 static struct gl_renderbuffer_attachment *
-_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
-                         GLenum attachment)
+get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
+                   GLenum attachment)
 {
    assert(_mesa_is_winsys_fbo(fb));
 
@@ -295,7 +303,7 @@ _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
             return &fb->Attachment[BUFFER_BACK_LEFT];
          return &fb->Attachment[BUFFER_FRONT_LEFT];
       case GL_DEPTH:
-      return &fb->Attachment[BUFFER_DEPTH];
+         return &fb->Attachment[BUFFER_DEPTH];
       case GL_STENCIL:
          return &fb->Attachment[BUFFER_STENCIL];
       }
@@ -303,9 +311,21 @@ _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
 
    switch (attachment) {
    case GL_FRONT_LEFT:
-      return &fb->Attachment[BUFFER_FRONT_LEFT];
+      /* Front buffers can be allocated on the first use, but
+       * glGetFramebufferAttachmentParameteriv must work even if that
+       * allocation hasn't happened yet. In such case, use the back buffer,
+       * which should be the same.
+       */
+      if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
+         return &fb->Attachment[BUFFER_BACK_LEFT];
+      else
+         return &fb->Attachment[BUFFER_FRONT_LEFT];
    case GL_FRONT_RIGHT:
-      return &fb->Attachment[BUFFER_FRONT_RIGHT];
+      /* Same as above. */
+      if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
+         return &fb->Attachment[BUFFER_BACK_RIGHT];
+      else
+         return &fb->Attachment[BUFFER_FRONT_RIGHT];
    case GL_BACK_LEFT:
       return &fb->Attachment[BUFFER_BACK_LEFT];
    case GL_BACK_RIGHT:
@@ -389,7 +409,8 @@ driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
    const struct gl_texture_image *const texImage =
       att->Texture->Image[att->CubeMapFace][att->TextureLevel];
 
-   if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
+   if (!texImage ||
+       texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
       return false;
 
    if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
@@ -430,7 +451,7 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
          return;
       }
-      _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+      att->Renderbuffer = rb;
 
       /* This can't get called on a texture renderbuffer, so set it to NULL
        * for clarity compared to user renderbuffers.
@@ -530,13 +551,13 @@ _mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
 
    mtx_lock(&fb->Mutex);
 
-   att = get_attachment(ctx, fb, attachment);
+   att = get_attachment(ctx, fb, attachment, NULL);
    assert(att);
    if (rb) {
       set_renderbuffer_attachment(ctx, att, rb);
       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
          /* do stencil attachment here (depth already done above) */
-         att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+         att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
          assert(att);
          set_renderbuffer_attachment(ctx, att, rb);
       }
@@ -546,7 +567,7 @@ _mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
       remove_attachment(ctx, att);
       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
          /* detach stencil (depth was detached above) */
-         att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+         att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
          assert(att);
          remove_attachment(ctx, att);
       }
@@ -957,6 +978,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    fb->_AllColorBuffersFixedPoint = GL_TRUE;
    fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
    fb->_HasAttachments = true;
+   fb->_IntegerBuffers = 0;
 
    /* Start at -2 to more easily loop over all attachment points.
     *  -2: depth buffer
@@ -1077,13 +1099,14 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          continue;
       }
 
-      /* check if integer color */
-      fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
-
-      /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */
+      /* Update flags describing color buffer datatypes */
       if (i >= 0) {
          GLenum type = _mesa_get_format_datatype(attFormat);
 
+         /* check if integer color */
+         if (_mesa_is_format_integer_color(attFormat))
+            fb->_IntegerBuffers |= (1 << i);
+
          fb->_AllColorBuffersFixedPoint =
             fb->_AllColorBuffersFixedPoint &&
             (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
@@ -1204,7 +1227,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
       for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
          if (fb->ColorDrawBuffer[j] != GL_NONE) {
             const struct gl_renderbuffer_attachment *att
-               = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+               = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
             assert(att);
             if (att->Type == GL_NONE) {
                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
@@ -1217,7 +1240,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
       /* Check that the ReadBuffer is present */
       if (fb->ColorReadBuffer != GL_NONE) {
          const struct gl_renderbuffer_attachment *att
-            = get_attachment(ctx, fb, fb->ColorReadBuffer);
+            = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
          assert(att);
          if (att->Type == GL_NONE) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
@@ -1274,15 +1297,14 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
 GLboolean GLAPIENTRY
 _mesa_IsRenderbuffer(GLuint renderbuffer)
 {
+   struct gl_renderbuffer *rb;
+
    GET_CURRENT_CONTEXT(ctx);
+
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-   if (renderbuffer) {
-      struct gl_renderbuffer *rb =
-         _mesa_lookup_renderbuffer(ctx, renderbuffer);
-      if (rb != NULL && rb != &DummyRenderbuffer)
-         return GL_TRUE;
-   }
-   return GL_FALSE;
+
+   rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+   return rb != NULL && rb != &DummyRenderbuffer;
 }
 
 
@@ -1300,7 +1322,6 @@ allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
    }
    assert(newRb->AllocStorage);
    _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
-   newRb->RefCount = 1; /* referenced by hash table */
 
    return newRb;
 }
@@ -1454,10 +1475,47 @@ _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
    framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
 }
 
+static bool
+_pname_valid_for_default_framebuffer(struct gl_context *ctx,
+                                     GLenum pname)
+{
+   if (!_mesa_is_desktop_gl(ctx))
+      return false;
+
+   switch (pname) {
+   case GL_DOUBLEBUFFER:
+   case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+   case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+   case GL_SAMPLES:
+   case GL_SAMPLE_BUFFERS:
+   case GL_STEREO:
+      return true;
+   default:
+      return false;
+   }
+}
+
 static void
 get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
                             GLenum pname, GLint *params, const char *func)
 {
+   /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
+    *
+    *    "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
+    *     if the default framebuffer is bound to target and pname is not one
+    *     of the accepted values from table 23.73, other than
+    *     SAMPLE_POSITION."
+    *
+    * For OpenGL ES, using default framebuffer still raises INVALID_OPERATION
+    * for any pname.
+    */
+   if (_mesa_is_winsys_fbo(fb) &&
+       !_pname_valid_for_default_framebuffer(ctx, pname)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid pname=0x%x for default framebuffer)", func, pname);
+      return;
+   }
+
    switch (pname) {
    case GL_FRAMEBUFFER_DEFAULT_WIDTH:
       *params = fb->DefaultGeometry.Width;
@@ -1482,6 +1540,24 @@ get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
    case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
       *params = fb->DefaultGeometry.FixedSampleLocations;
       break;
+   case GL_DOUBLEBUFFER:
+      *params = fb->Visual.doubleBufferMode;
+      break;
+   case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+      *params = _mesa_get_color_read_format(ctx, fb, func);
+      break;
+   case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+      *params = _mesa_get_color_read_type(ctx, fb, func);
+      break;
+   case GL_SAMPLES:
+      *params = _mesa_geometric_samples(fb);
+      break;
+   case GL_SAMPLE_BUFFERS:
+      *params = _mesa_geometric_samples(fb) > 0;
+      break;
+   case GL_STEREO:
+      *params = fb->Visual.stereoMode;
+      break;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "%s(pname=0x%x)", func, pname);
@@ -1508,13 +1584,6 @@ _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
       return;
    }
 
-   /* check framebuffer binding */
-   if (_mesa_is_winsys_fbo(fb)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetFramebufferParameteriv");
-      return;
-   }
-
    get_framebuffer_parameteriv(ctx, fb, pname, params,
                                "glGetFramebufferParameteriv");
 }
@@ -2127,7 +2196,7 @@ renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
       }
 
       if (sample_count_error != GL_NO_ERROR) {
-         _mesa_error(ctx, sample_count_error, "%s(samples)", func);
+         _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples);
          return;
       }
    }
@@ -2835,6 +2904,7 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
    dst_att->Type = src_att->Type;
    dst_att->Complete = src_att->Complete;
    dst_att->TextureLevel = src_att->TextureLevel;
+   dst_att->CubeMapFace = src_att->CubeMapFace;
    dst_att->Zoffset = src_att->Zoffset;
    dst_att->Layered = src_att->Layered;
 }
@@ -2978,54 +3048,49 @@ check_textarget(struct gl_context *ctx, int dims, GLenum target,
 {
    bool err = false;
 
-   switch (dims) {
-   case 1:
-      switch (textarget) {
-      case GL_TEXTURE_1D:
-         break;
-      case GL_TEXTURE_1D_ARRAY:
-         err = !ctx->Extensions.EXT_texture_array;
-         break;
-      default:
-         err = true;
-      }
+   switch (textarget) {
+   case GL_TEXTURE_1D:
+      err = dims != 1;
       break;
-   case 2:
-      switch (textarget) {
-      case GL_TEXTURE_2D:
-         break;
-      case GL_TEXTURE_RECTANGLE:
-         err = _mesa_is_gles(ctx)
-            || !ctx->Extensions.NV_texture_rectangle;
-         break;
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-         err = !ctx->Extensions.ARB_texture_cube_map;
-         break;
-      case GL_TEXTURE_2D_ARRAY:
-         err = (_mesa_is_gles(ctx) && ctx->Version < 30)
-               || !ctx->Extensions.EXT_texture_array;
-         break;
-      case GL_TEXTURE_2D_MULTISAMPLE:
-      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
-         err = (_mesa_is_gles(ctx) ||
-                !ctx->Extensions.ARB_texture_multisample) &&
-               !_mesa_is_gles31(ctx);
-         break;
-      default:
-         err = true;
-      }
+   case GL_TEXTURE_1D_ARRAY:
+      err = dims != 1 || !ctx->Extensions.EXT_texture_array;
       break;
-   case 3:
-      if (textarget != GL_TEXTURE_3D)
-         err = true;
+   case GL_TEXTURE_2D:
+      err = dims != 2;
       break;
-   default:
+   case GL_TEXTURE_2D_ARRAY:
+      err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
+            (_mesa_is_gles(ctx) && ctx->Version < 30);
+      break;
+   case GL_TEXTURE_2D_MULTISAMPLE:
+   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+      err = dims != 2 ||
+            !ctx->Extensions.ARB_texture_multisample ||
+            (_mesa_is_gles(ctx) && ctx->Version < 31);
+      break;
+   case GL_TEXTURE_RECTANGLE:
+      err = dims != 2 || _mesa_is_gles(ctx) ||
+            !ctx->Extensions.NV_texture_rectangle;
+      break;
+   case GL_TEXTURE_CUBE_MAP:
+   case GL_TEXTURE_CUBE_MAP_ARRAY:
       err = true;
+      break;
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
+      break;
+   case GL_TEXTURE_3D:
+      err = dims != 3;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(unknown textarget 0x%x)", caller, textarget);
+      return false;
    }
 
    if (err) {
@@ -3131,6 +3196,7 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
                           const char *caller)
 {
    struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment;
 
    /* The window-system framebuffer object is immutable */
    if (_mesa_is_winsys_fbo(fb)) {
@@ -3140,10 +3206,17 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
    }
 
    /* Not a hash lookup, so we can afford to get the attachment here. */
-   att = get_attachment(ctx, fb, attachment);
+   att = get_attachment(ctx, fb, attachment, &is_color_attachment);
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
-                  _mesa_enum_to_string(attachment));
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(invalid color attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "%s(invalid attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      }
       return;
    }
 
@@ -3476,6 +3549,7 @@ framebuffer_renderbuffer(struct gl_context *ctx,
                          const char *func)
 {
    struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment;
 
    if (_mesa_is_winsys_fbo(fb)) {
       /* Can't attach new renderbuffers to a window system framebuffer */
@@ -3484,11 +3558,29 @@ framebuffer_renderbuffer(struct gl_context *ctx,
       return;
    }
 
-   att = get_attachment(ctx, fb, attachment);
+   att = get_attachment(ctx, fb, attachment, &is_color_attachment);
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(invalid attachment %s)", func,
-                  _mesa_enum_to_string(attachment));
+      /*
+       * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images to
+       * a Framebuffer":
+       *
+       *    "An INVALID_OPERATION error is generated if attachment is COLOR_-
+       *     ATTACHMENTm where m is greater than or equal to the value of
+       *     MAX_COLOR_- ATTACHMENTS ."
+       *
+       * If we are at this point, is because the attachment is not valid, so
+       * if is_color_attachment is true, is because of the previous reason.
+       */
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(invalid color attachment %s)", func,
+                     _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "%s(invalid attachment %s)", func,
+                     _mesa_enum_to_string(attachment));
+      }
+
       return;
    }
 
@@ -3583,13 +3675,14 @@ _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
 }
 
 
-void
-_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
-                                           struct gl_framebuffer *buffer,
-                                           GLenum attachment, GLenum pname,
-                                           GLint *params, const char *caller)
+static void
+get_framebuffer_attachment_parameter(struct gl_context *ctx,
+                                     struct gl_framebuffer *buffer,
+                                     GLenum attachment, GLenum pname,
+                                     GLint *params, const char *caller)
 {
    const struct gl_renderbuffer_attachment *att;
+   bool is_color_attachment = false;
    GLenum err;
 
    /* The error code for an attachment type of GL_NONE differs between APIs.
@@ -3653,16 +3746,31 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
       }
 
       /* the default / window-system FBO */
-      att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
+      att = get_fb0_attachment(ctx, buffer, attachment);
    }
    else {
       /* user-created framebuffer FBO */
-      att = get_attachment(ctx, buffer, attachment);
+      att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
    }
 
    if (att == NULL) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
-                  _mesa_enum_to_string(attachment));
+      /*
+       * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
+       *
+       *    "An INVALID_OPERATION error is generated if a framebuffer object
+       *     is bound to target and attachment is COLOR_ATTACHMENTm where m is
+       *     greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
+       *
+       * If we are at this point, is because the attachment is not valid, so
+       * if is_color_attachment is true, is because of the previous reason.
+       */
+      if (is_color_attachment) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
+                     caller, _mesa_enum_to_string(attachment));
+      } else {
+         _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+                     _mesa_enum_to_string(attachment));
+      }
       return;
    }
 
@@ -3681,8 +3789,8 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
          return;
       }
       /* the depth and stencil attachments must point to the same buffer */
-      depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
-      stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
+      depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
+      stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
       if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s(DEPTH/STENCIL attachments differ)", caller);
@@ -3700,11 +3808,13 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
        *  either no framebuffer is bound to target; or the default framebuffer
        *  is bound, attachment is DEPTH or STENCIL, and the number of depth or
        *  stencil bits, respectively, is zero."
+       *
+       * Note that we don't need explicit checks on DEPTH and STENCIL, because
+       * on the case the spec is pointing, att->Type is already NONE, so we
+       * just need to check att->Type.
        */
-      *params = (_mesa_is_winsys_fbo(buffer) &&
-                 ((attachment != GL_DEPTH && attachment != GL_STENCIL) ||
-                  (att->Type != GL_NONE)))
-         ? GL_FRAMEBUFFER_DEFAULT : att->Type;
+      *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
+         GL_FRAMEBUFFER_DEFAULT : att->Type;
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
       if (att->Type == GL_RENDERBUFFER_EXT) {
@@ -3777,8 +3887,13 @@ _mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
          goto invalid_pname_enum;
       }
       else if (att->Type == GL_NONE) {
-         _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
-                     _mesa_enum_to_string(pname));
+         if (_mesa_is_winsys_fbo(buffer) &&
+             (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
+            *params = GL_LINEAR;
+         } else {
+            _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+                        _mesa_enum_to_string(pname));
+         }
       }
       else {
          if (ctx->Extensions.EXT_framebuffer_sRGB) {
@@ -3915,8 +4030,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
       return;
    }
 
-   _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
-                                              params,
+   get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+                                        params,
                                     "glGetFramebufferAttachmentParameteriv");
 }
 
@@ -3945,8 +4060,8 @@ _mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
       buffer = ctx->WinSysDrawBuffer;
    }
 
-   _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
-                                              params,
+   get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+                                        params,
                               "glGetNamedFramebufferAttachmentParameteriv");
 }