rb->Height = texImage->Height2;
rb->Depth = texImage->Depth2;
rb->NumSamples = texImage->NumSamples;
+ rb->NumStorageSamples = texImage->NumSamples;
rb->TexImage = texImage;
if (driver_RenderTexture_is_safe(att))
/* Reject additional cases for GLES */
switch (internalFormat) {
+ case GL_R8_SNORM:
+ case GL_RG8_SNORM:
case GL_RGBA8_SNORM:
+ return _mesa_has_EXT_render_snorm(ctx);
+ case GL_R16_SNORM:
+ case GL_RG16_SNORM:
+ case GL_RGBA16_SNORM:
+ return _mesa_has_EXT_texture_norm16(ctx) &&
+ _mesa_has_EXT_render_snorm(ctx);
case GL_RGB32F:
case GL_RGB32I:
case GL_RGB32UI:
case GL_SRGB8:
case GL_RGB10:
case GL_RGB9_E5:
- case GL_RG8_SNORM:
- case GL_R8_SNORM:
return GL_FALSE;
default:
break;
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 ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
? GL_RG : 0;
/* signed normalized texture formats */
- case GL_RED_SNORM:
case GL_R8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RED : 0;
+ case GL_RED_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
case GL_R16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RED : 0;
- case GL_RG_SNORM:
case GL_RG8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RG : 0;
+ case GL_RG_SNORM:
+ _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
case GL_RG16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RG : 0;
case GL_RGB_SNORM:
case GL_RGB8_SNORM:
case GL_RGB16_SNORM:
return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
? GL_RGB : 0;
- case GL_RGBA_SNORM:
case GL_RGBA8_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
+ ? GL_RGBA : 0;
+ case GL_RGBA_SNORM:
+ return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
case GL_RGBA16_SNORM:
- return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
+ return _mesa_has_EXT_texture_snorm(ctx) ||
+ (_mesa_has_EXT_render_snorm(ctx) &&
+ _mesa_has_EXT_texture_norm16(ctx))
? GL_RGBA : 0;
case GL_ALPHA_SNORM:
case GL_ALPHA8_SNORM:
void
_mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei samples)
+ GLsizei height, GLsizei samples,
+ GLsizei storageSamples)
{
const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (samples != 0) {
assert(samples > 0);
assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
- internalFormat, samples) == GL_NO_ERROR);
+ internalFormat, samples,
+ storageSamples) == GL_NO_ERROR);
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (rb->InternalFormat == internalFormat &&
rb->Width == (GLuint) width &&
rb->Height == (GLuint) height &&
- rb->NumSamples == samples) {
+ rb->NumSamples == samples &&
+ rb->NumStorageSamples == storageSamples) {
/* no change in allocation needed */
return;
}
/* These MUST get set by the AllocStorage func */
rb->Format = MESA_FORMAT_NONE;
rb->NumSamples = samples;
+ rb->NumStorageSamples = storageSamples;
/* Now allocate the storage */
assert(rb->AllocStorage);
rb->InternalFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
rb->NumSamples = 0;
+ rb->NumStorageSamples = 0;
}
/* Invalidate the framebuffers the renderbuffer is attached in. */
static void
renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLsizei width,
- GLsizei height, GLsizei samples, const char *func)
+ GLsizei height, GLsizei samples, GLsizei storageSamples,
+ const char *func)
{
GLenum baseFormat;
GLenum sample_count_error;
if (samples == NO_SAMPLES) {
/* NumSamples == 0 indicates non-multisampling */
samples = 0;
+ storageSamples = 0;
}
else {
/* check the sample count;
* note: driver may choose to use more samples than what's requested
*/
sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
- internalFormat, samples);
+ internalFormat, samples, storageSamples);
/* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
*
* "If a negative number is provided where an argument of type sizei or
* sizeiptr is specified, the error INVALID VALUE is generated."
*/
- if (samples < 0) {
+ if (samples < 0 || storageSamples < 0) {
sample_count_error = GL_INVALID_VALUE;
}
if (sample_count_error != GL_NO_ERROR) {
- _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples);
+ _mesa_error(ctx, sample_count_error,
+ "%s(samples=%d, storageSamples=%d)", func, samples,
+ storageSamples);
return;
}
}
- _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples);
+ _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
+ storageSamples);
}
/**
static void
renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei samples,
- const char *func)
+ GLsizei storageSamples, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
return;
}
- renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func);
+ renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
+ storageSamples, func);
}
/**
static void
renderbuffer_storage_target(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei samples,
- const char *func)
+ GLsizei storageSamples, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
}
renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
- height, samples, func);
+ height, samples, storageSamples, func);
}
* a token value here just for error reporting purposes.
*/
renderbuffer_storage_target(target, internalFormat, width, height,
- NO_SAMPLES, "glRenderbufferStorage");
+ NO_SAMPLES, 0, "glRenderbufferStorage");
}
GLsizei width, GLsizei height)
{
renderbuffer_storage_target(target, internalFormat, width, height,
- samples, "glRenderbufferStorageMultisample");
+ samples, samples,
+ "glRenderbufferStorageMultisample");
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageMultisampleAdvancedAMD(
+ GLenum target, GLsizei samples, GLsizei storageSamples,
+ GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ samples, storageSamples,
+ "glRenderbufferStorageMultisampleAdvancedAMD");
}
break;
}
- renderbuffer_storage_target(target, internalFormat, width, height, 0,
+ renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
"glRenderbufferStorageEXT");
}
* a token value here just for error reporting purposes.
*/
renderbuffer_storage_named(renderbuffer, internalformat, width, height,
- NO_SAMPLES, "glNamedRenderbufferStorage");
+ NO_SAMPLES, 0, "glNamedRenderbufferStorage");
}
void GLAPIENTRY
GLsizei width, GLsizei height)
{
renderbuffer_storage_named(renderbuffer, internalformat, width, height,
- samples,
+ samples, samples,
"glNamedRenderbufferStorageMultisample");
}
+void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
+ GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ samples, storageSamples,
+ "glNamedRenderbufferStorageMultisampleAdvancedAMD");
+}
+
+
static void
get_render_buffer_parameteriv(struct gl_context *ctx,
struct gl_renderbuffer *rb, GLenum pname,
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
*params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
- break;
+ return;
case GL_RENDERBUFFER_SAMPLES:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
|| _mesa_is_gles3(ctx)) {
*params = rb->NumSamples;
- break;
+ return;
}
- /* fallthrough */
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
- _mesa_enum_to_string(pname));
- return;
+ break;
+ case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
+ if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
+ *params = rb->NumStorageSamples;
+ return;
+ }
+ break;
}
+
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
+ _mesa_enum_to_string(pname));
}