GLuint numImages;
GLenum intFormat = GL_NONE; /* color buffers' internal format */
GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
- GLint numSamples = -1;
+ GLint numColorSamples = -1;
+ GLint numColorStorageSamples = -1;
+ GLint numDepthSamples = -1;
GLint fixedSampleLocations = -1;
GLint i;
GLuint j;
/* get width, height, format of the renderbuffer/texture
*/
+ unsigned attNumSamples, attNumStorageSamples;
+
if (att->Type == GL_TEXTURE) {
const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
att_tex_target = att->Texture->Target;
return;
}
- if (numSamples < 0)
- numSamples = texImg->NumSamples;
- else if (numSamples != texImg->NumSamples) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
- fbo_incomplete(ctx, "inconsistent sample count", -1);
- return;
- }
-
if (fixedSampleLocations < 0)
fixedSampleLocations = texImg->FixedSampleLocations;
else if (fixedSampleLocations != texImg->FixedSampleLocations) {
fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
return;
}
+
+ attNumSamples = texImg->NumSamples;
+ attNumStorageSamples = texImg->NumSamples;
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
minWidth = MIN2(minWidth, att->Renderbuffer->Width);
attFormat = att->Renderbuffer->Format;
numImages++;
- if (numSamples < 0)
- numSamples = att->Renderbuffer->NumSamples;
- else if (numSamples != att->Renderbuffer->NumSamples) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
- fbo_incomplete(ctx, "inconsistent sample count", -1);
- return;
- }
-
/* RENDERBUFFER has fixedSampleLocations implicitly true */
if (fixedSampleLocations < 0)
fixedSampleLocations = GL_TRUE;
fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
return;
}
+
+ attNumSamples = att->Renderbuffer->NumSamples;
+ attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
}
else {
assert(att->Type == GL_NONE);
continue;
}
+ if (i >= 0) {
+ /* Color buffers. */
+ if (numColorSamples < 0) {
+ assert(numColorStorageSamples < 0);
+ numColorSamples = attNumSamples;
+ numColorStorageSamples = attNumStorageSamples;
+ } else if (numColorSamples != attNumSamples ||
+ numColorStorageSamples != attNumStorageSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ } else {
+ /* Depth/stencil buffers. */
+ if (numDepthSamples < 0) {
+ numDepthSamples = attNumSamples;
+ } else if (numDepthSamples != attNumSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ }
+
/* Update flags describing color buffer datatypes */
if (i >= 0) {
GLenum type = _mesa_get_format_datatype(attFormat);
*/
}
+ if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
+ /* See if non-matching sample counts are supported. */
+ if (numColorSamples >= 0 && numDepthSamples >= 0) {
+ bool found = false;
+
+ assert(numColorStorageSamples != -1);
+
+ numColorSamples = MAX2(numColorSamples, 1);
+ numColorStorageSamples = MAX2(numColorStorageSamples, 1);
+ numDepthSamples = MAX2(numDepthSamples, 1);
+
+ if (numColorSamples == 1 && numColorStorageSamples == 1 &&
+ numDepthSamples == 1) {
+ found = true;
+ } else {
+ for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
+ GLint *counts =
+ &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
+
+ if (counts[0] == numColorSamples &&
+ counts[1] == numColorStorageSamples &&
+ counts[2] == numDepthSamples) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "unsupported sample counts", -1);
+ return;
+ }
+ }
+ } else {
+ /* If the extension is unsupported, all sample counts must be equal. */
+ if (numColorSamples >= 0 &&
+ (numColorSamples != numColorStorageSamples ||
+ (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete(ctx, "inconsistent sample counts", -1);
+ return;
+ }
+ }
+
fb->MaxNumLayers = max_layer_count;
if (numImages == 0) {
return GL_INVALID_OPERATION;
}
+ if (ctx->Extensions.AMD_framebuffer_multisample_advanced &&
+ target == GL_RENDERBUFFER) {
+ if (!_mesa_is_depth_or_stencil_format(internalFormat)) {
+ /* From the AMD_framebuffer_multisample_advanced spec:
+ *
+ * "An INVALID_OPERATION error is generated if <internalformat>
+ * is a color format and <storageSamples> is greater than
+ * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_-
+ * STORAGE_SAMPLES_AMD."
+ */
+ if (samples > ctx->Const.MaxColorFramebufferSamples)
+ return GL_INVALID_OPERATION;
+
+ /* From the AMD_framebuffer_multisample_advanced spec:
+ *
+ * "An INVALID_OPERATION error is generated if <internalformat>
+ * is a color format and <storageSamples> is greater than
+ * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_-
+ * STORAGE_SAMPLES_AMD."
+ */
+ if (storageSamples > ctx->Const.MaxColorFramebufferStorageSamples)
+ return GL_INVALID_OPERATION;
+
+ /* From the AMD_framebuffer_multisample_advanced spec:
+ *
+ * "An INVALID_OPERATION error is generated if <storageSamples> is
+ * greater than <samples>."
+ */
+ if (storageSamples > samples)
+ return GL_INVALID_OPERATION;
+
+ /* Color renderbuffer sample counts are now fully validated
+ * according to AMD_framebuffer_multisample_advanced.
+ */
+ return GL_NO_ERROR;
+ } else {
+ /* From the AMD_framebuffer_multisample_advanced spec:
+ *
+ * "An INVALID_OPERATION error is generated if <internalformat> is
+ * a depth or stencil format and <storageSamples> is not equal to
+ * <samples>."
+ */
+ if (storageSamples != samples)
+ return GL_INVALID_OPERATION;
+ }
+ } else {
+ /* If the extension is unsupported, it's not possible to set
+ * storageSamples differently.
+ */
+ assert(samples == storageSamples);
+ }
+
/* If ARB_internalformat_query is supported, then treat its highest
* returned sample count as the absolute maximum for this format; it is
* allowed to exceed MAX_SAMPLES.