multisample.c revision 7ec681f3
1c1f859d4Smrg/* 2c1f859d4Smrg * Mesa 3-D graphics library 3c1f859d4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5c1f859d4Smrg * 6c1f859d4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7c1f859d4Smrg * copy of this software and associated documentation files (the "Software"), 8c1f859d4Smrg * to deal in the Software without restriction, including without limitation 9c1f859d4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10c1f859d4Smrg * and/or sell copies of the Software, and to permit persons to whom the 11c1f859d4Smrg * Software is furnished to do so, subject to the following conditions: 12c1f859d4Smrg * 13c1f859d4Smrg * The above copyright notice and this permission notice shall be included 14c1f859d4Smrg * in all copies or substantial portions of the Software. 15c1f859d4Smrg * 16c1f859d4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17c1f859d4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18c1f859d4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 23c1f859d4Smrg */ 24c1f859d4Smrg 25c1f859d4Smrg 26c1f859d4Smrg#include "main/glheader.h" 27c1f859d4Smrg#include "main/context.h" 28c1f859d4Smrg#include "main/macros.h" 29c1f859d4Smrg#include "main/multisample.h" 303464ebd5Sriastradh#include "main/mtypes.h" 31af69d88dSmrg#include "main/fbobject.h" 32af69d88dSmrg#include "main/glformats.h" 33af69d88dSmrg#include "main/state.h" 34c1f859d4Smrg 35c1f859d4Smrg 36c1f859d4Smrg/** 37c1f859d4Smrg * Called via glSampleCoverageARB 38c1f859d4Smrg */ 39c1f859d4Smrgvoid GLAPIENTRY 40af69d88dSmrg_mesa_SampleCoverage(GLclampf value, GLboolean invert) 41c1f859d4Smrg{ 42c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 43c1f859d4Smrg 447ec681f3Smrg value = SATURATE(value); 45c1f859d4Smrg 4601e04c3fSmrg if (ctx->Multisample.SampleCoverageInvert == invert && 4701e04c3fSmrg ctx->Multisample.SampleCoverageValue == value) 4801e04c3fSmrg return; 4901e04c3fSmrg 507ec681f3Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewSampleMask ? 0 : _NEW_MULTISAMPLE, 517ec681f3Smrg GL_MULTISAMPLE_BIT); 5201e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewSampleMask; 5301e04c3fSmrg ctx->Multisample.SampleCoverageValue = value; 54c1f859d4Smrg ctx->Multisample.SampleCoverageInvert = invert; 55c1f859d4Smrg} 56c1f859d4Smrg 57c1f859d4Smrg 58c1f859d4Smrg/** 59c1f859d4Smrg * Initialize the context's multisample state. 60c1f859d4Smrg * \param ctx the GL context. 61c1f859d4Smrg */ 62c1f859d4Smrgvoid 633464ebd5Sriastradh_mesa_init_multisample(struct gl_context *ctx) 64c1f859d4Smrg{ 65c1f859d4Smrg ctx->Multisample.Enabled = GL_TRUE; 66c1f859d4Smrg ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 677ec681f3Smrg ctx->Multisample.SampleAlphaToCoverageDitherControl = GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV; 68c1f859d4Smrg ctx->Multisample.SampleAlphaToOne = GL_FALSE; 69c1f859d4Smrg ctx->Multisample.SampleCoverage = GL_FALSE; 70c1f859d4Smrg ctx->Multisample.SampleCoverageValue = 1.0; 71c1f859d4Smrg ctx->Multisample.SampleCoverageInvert = GL_FALSE; 7201e04c3fSmrg ctx->Multisample.SampleShading = GL_FALSE; 7301e04c3fSmrg ctx->Multisample.MinSampleShadingValue = 0.0f; 74af69d88dSmrg 75af69d88dSmrg /* ARB_texture_multisample / GL3.2 additions */ 76af69d88dSmrg ctx->Multisample.SampleMask = GL_FALSE; 77af69d88dSmrg ctx->Multisample.SampleMaskValue = ~(GLbitfield)0; 78af69d88dSmrg} 79af69d88dSmrg 80af69d88dSmrg 81af69d88dSmrgvoid GLAPIENTRY 82af69d88dSmrg_mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val) 83af69d88dSmrg{ 84af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 85af69d88dSmrg 86af69d88dSmrg if (ctx->NewState & _NEW_BUFFERS) { 87af69d88dSmrg _mesa_update_state(ctx); 88af69d88dSmrg } 89af69d88dSmrg 90af69d88dSmrg switch (pname) { 91af69d88dSmrg case GL_SAMPLE_POSITION: { 9201e04c3fSmrg if (index >= ctx->DrawBuffer->Visual.samples) { 93af69d88dSmrg _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" ); 94af69d88dSmrg return; 95af69d88dSmrg } 96af69d88dSmrg 97af69d88dSmrg ctx->Driver.GetSamplePosition(ctx, ctx->DrawBuffer, index, val); 98af69d88dSmrg 9901e04c3fSmrg /* FBOs can be upside down (winsys always are)*/ 10001e04c3fSmrg if (ctx->DrawBuffer->FlipY) 101af69d88dSmrg val[1] = 1.0f - val[1]; 102af69d88dSmrg 103af69d88dSmrg return; 104af69d88dSmrg } 105af69d88dSmrg 10601e04c3fSmrg case GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB: 10701e04c3fSmrg if (!ctx->Extensions.ARB_sample_locations) { 10801e04c3fSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" ); 10901e04c3fSmrg return; 11001e04c3fSmrg } 11101e04c3fSmrg 11201e04c3fSmrg if (index >= MAX_SAMPLE_LOCATION_TABLE_SIZE * 2) { 11301e04c3fSmrg _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" ); 11401e04c3fSmrg return; 11501e04c3fSmrg } 11601e04c3fSmrg 11701e04c3fSmrg if (ctx->DrawBuffer->SampleLocationTable) 11801e04c3fSmrg *val = ctx->DrawBuffer->SampleLocationTable[index]; 11901e04c3fSmrg else 12001e04c3fSmrg *val = 0.5f; 12101e04c3fSmrg 12201e04c3fSmrg return; 12301e04c3fSmrg 124af69d88dSmrg default: 125af69d88dSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" ); 126af69d88dSmrg return; 127af69d88dSmrg } 128af69d88dSmrg} 129af69d88dSmrg 13001e04c3fSmrgstatic void 13101e04c3fSmrgsample_maski(struct gl_context *ctx, GLuint index, GLbitfield mask) 13201e04c3fSmrg{ 13301e04c3fSmrg if (ctx->Multisample.SampleMaskValue == mask) 13401e04c3fSmrg return; 13501e04c3fSmrg 1367ec681f3Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewSampleMask ? 0 : _NEW_MULTISAMPLE, 0); 13701e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewSampleMask; 13801e04c3fSmrg ctx->Multisample.SampleMaskValue = mask; 13901e04c3fSmrg} 14001e04c3fSmrg 14101e04c3fSmrgvoid GLAPIENTRY 14201e04c3fSmrg_mesa_SampleMaski_no_error(GLuint index, GLbitfield mask) 14301e04c3fSmrg{ 14401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 14501e04c3fSmrg sample_maski(ctx, index, mask); 14601e04c3fSmrg} 14701e04c3fSmrg 148af69d88dSmrgvoid GLAPIENTRY 149af69d88dSmrg_mesa_SampleMaski(GLuint index, GLbitfield mask) 150af69d88dSmrg{ 151af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 152af69d88dSmrg 153af69d88dSmrg if (!ctx->Extensions.ARB_texture_multisample) { 154af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMaski"); 155af69d88dSmrg return; 156af69d88dSmrg } 157af69d88dSmrg 158af69d88dSmrg if (index != 0) { 159af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glSampleMaski(index)"); 160af69d88dSmrg return; 161af69d88dSmrg } 162af69d88dSmrg 16301e04c3fSmrg sample_maski(ctx, index, mask); 16401e04c3fSmrg} 16501e04c3fSmrg 16601e04c3fSmrgstatic void 16701e04c3fSmrgmin_sample_shading(struct gl_context *ctx, GLclampf value) 16801e04c3fSmrg{ 1697ec681f3Smrg value = SATURATE(value); 17001e04c3fSmrg 17101e04c3fSmrg if (ctx->Multisample.MinSampleShadingValue == value) 17201e04c3fSmrg return; 17301e04c3fSmrg 17401e04c3fSmrg FLUSH_VERTICES(ctx, 1757ec681f3Smrg ctx->DriverFlags.NewSampleShading ? 0 : _NEW_MULTISAMPLE, 1767ec681f3Smrg GL_MULTISAMPLE_BIT); 17701e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewSampleShading; 17801e04c3fSmrg ctx->Multisample.MinSampleShadingValue = value; 179af69d88dSmrg} 180af69d88dSmrg 181af69d88dSmrg/** 182af69d88dSmrg * Called via glMinSampleShadingARB 183af69d88dSmrg */ 18401e04c3fSmrgvoid GLAPIENTRY 18501e04c3fSmrg_mesa_MinSampleShading_no_error(GLclampf value) 18601e04c3fSmrg{ 18701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 18801e04c3fSmrg min_sample_shading(ctx, value); 18901e04c3fSmrg} 19001e04c3fSmrg 191af69d88dSmrgvoid GLAPIENTRY 192af69d88dSmrg_mesa_MinSampleShading(GLclampf value) 193af69d88dSmrg{ 194af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 195af69d88dSmrg 19601e04c3fSmrg if (!_mesa_has_ARB_sample_shading(ctx) && 19701e04c3fSmrg !_mesa_has_OES_sample_shading(ctx)) { 198af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading"); 199af69d88dSmrg return; 200af69d88dSmrg } 201af69d88dSmrg 20201e04c3fSmrg min_sample_shading(ctx, value); 203af69d88dSmrg} 204af69d88dSmrg 205af69d88dSmrg/** 206af69d88dSmrg * Helper for checking a requested sample count against the limit 207af69d88dSmrg * for a particular (target, internalFormat) pair. The limit imposed, 208af69d88dSmrg * and the error generated, both depend on which extensions are supported. 209af69d88dSmrg * 210af69d88dSmrg * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is 211af69d88dSmrg * acceptable. 212af69d88dSmrg */ 213af69d88dSmrgGLenum 214af69d88dSmrg_mesa_check_sample_count(struct gl_context *ctx, GLenum target, 21501e04c3fSmrg GLenum internalFormat, GLsizei samples, 21601e04c3fSmrg GLsizei storageSamples) 217af69d88dSmrg{ 21801e04c3fSmrg /* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0 21901e04c3fSmrg * specification says: 22001e04c3fSmrg * 22101e04c3fSmrg * "If internalformat is a signed or unsigned integer format and samples 22201e04c3fSmrg * is greater than zero, then the error INVALID_OPERATION is generated." 22301e04c3fSmrg * 22401e04c3fSmrg * This restriction is relaxed for OpenGL ES 3.1. 22501e04c3fSmrg */ 22601e04c3fSmrg if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) && 22701e04c3fSmrg _mesa_is_enum_format_integer(internalFormat) 22801e04c3fSmrg && samples > 0) { 22901e04c3fSmrg return GL_INVALID_OPERATION; 23001e04c3fSmrg } 23101e04c3fSmrg 23201e04c3fSmrg if (ctx->Extensions.AMD_framebuffer_multisample_advanced && 23301e04c3fSmrg target == GL_RENDERBUFFER) { 23401e04c3fSmrg if (!_mesa_is_depth_or_stencil_format(internalFormat)) { 23501e04c3fSmrg /* From the AMD_framebuffer_multisample_advanced spec: 23601e04c3fSmrg * 23701e04c3fSmrg * "An INVALID_OPERATION error is generated if <internalformat> 23801e04c3fSmrg * is a color format and <storageSamples> is greater than 23901e04c3fSmrg * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_- 24001e04c3fSmrg * STORAGE_SAMPLES_AMD." 24101e04c3fSmrg */ 24201e04c3fSmrg if (samples > ctx->Const.MaxColorFramebufferSamples) 24301e04c3fSmrg return GL_INVALID_OPERATION; 24401e04c3fSmrg 24501e04c3fSmrg /* From the AMD_framebuffer_multisample_advanced spec: 24601e04c3fSmrg * 24701e04c3fSmrg * "An INVALID_OPERATION error is generated if <internalformat> 24801e04c3fSmrg * is a color format and <storageSamples> is greater than 24901e04c3fSmrg * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_- 25001e04c3fSmrg * STORAGE_SAMPLES_AMD." 25101e04c3fSmrg */ 25201e04c3fSmrg if (storageSamples > ctx->Const.MaxColorFramebufferStorageSamples) 25301e04c3fSmrg return GL_INVALID_OPERATION; 25401e04c3fSmrg 25501e04c3fSmrg /* From the AMD_framebuffer_multisample_advanced spec: 25601e04c3fSmrg * 25701e04c3fSmrg * "An INVALID_OPERATION error is generated if <storageSamples> is 25801e04c3fSmrg * greater than <samples>." 25901e04c3fSmrg */ 26001e04c3fSmrg if (storageSamples > samples) 26101e04c3fSmrg return GL_INVALID_OPERATION; 26201e04c3fSmrg 26301e04c3fSmrg /* Color renderbuffer sample counts are now fully validated 26401e04c3fSmrg * according to AMD_framebuffer_multisample_advanced. 26501e04c3fSmrg */ 26601e04c3fSmrg return GL_NO_ERROR; 26701e04c3fSmrg } else { 26801e04c3fSmrg /* From the AMD_framebuffer_multisample_advanced spec: 26901e04c3fSmrg * 27001e04c3fSmrg * "An INVALID_OPERATION error is generated if <internalformat> is 27101e04c3fSmrg * a depth or stencil format and <storageSamples> is not equal to 27201e04c3fSmrg * <samples>." 27301e04c3fSmrg */ 27401e04c3fSmrg if (storageSamples != samples) 27501e04c3fSmrg return GL_INVALID_OPERATION; 27601e04c3fSmrg } 27701e04c3fSmrg } else { 27801e04c3fSmrg /* If the extension is unsupported, it's not possible to set 27901e04c3fSmrg * storageSamples differently. 28001e04c3fSmrg */ 28101e04c3fSmrg assert(samples == storageSamples); 28201e04c3fSmrg } 28301e04c3fSmrg 284af69d88dSmrg /* If ARB_internalformat_query is supported, then treat its highest 285af69d88dSmrg * returned sample count as the absolute maximum for this format; it is 286af69d88dSmrg * allowed to exceed MAX_SAMPLES. 287af69d88dSmrg * 288af69d88dSmrg * From the ARB_internalformat_query spec: 289af69d88dSmrg * 290af69d88dSmrg * "If <samples is greater than the maximum number of samples supported 291af69d88dSmrg * for <internalformat> then the error INVALID_OPERATION is generated." 292af69d88dSmrg */ 293af69d88dSmrg if (ctx->Extensions.ARB_internalformat_query) { 29401e04c3fSmrg GLint buffer[16] = {-1}; 29501e04c3fSmrg GLint limit; 29601e04c3fSmrg 29701e04c3fSmrg ctx->Driver.QueryInternalFormat(ctx, target, internalFormat, 29801e04c3fSmrg GL_SAMPLES, buffer); 29901e04c3fSmrg /* since the query returns samples sorted in descending order, 30001e04c3fSmrg * the first element is the greatest supported sample value. 30101e04c3fSmrg */ 30201e04c3fSmrg limit = buffer[0]; 303af69d88dSmrg 304af69d88dSmrg return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR; 305af69d88dSmrg } 306af69d88dSmrg 307af69d88dSmrg /* If ARB_texture_multisample is supported, we have separate limits, 308af69d88dSmrg * which may be lower than MAX_SAMPLES: 309af69d88dSmrg * 310af69d88dSmrg * From the ARB_texture_multisample spec, when describing the operation 311af69d88dSmrg * of RenderbufferStorageMultisample: 312af69d88dSmrg * 313af69d88dSmrg * "If <internalformat> is a signed or unsigned integer format and 314af69d88dSmrg * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the 315af69d88dSmrg * error INVALID_OPERATION is generated" 316af69d88dSmrg * 317af69d88dSmrg * And when describing the operation of TexImage*Multisample: 318af69d88dSmrg * 319af69d88dSmrg * "The error INVALID_OPERATION may be generated if any of the following 320af69d88dSmrg * are true: 321af69d88dSmrg * 322af69d88dSmrg * * <internalformat> is a depth/stencil-renderable format and <samples> 323af69d88dSmrg * is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES 324af69d88dSmrg * * <internalformat> is a color-renderable format and <samples> is 325af69d88dSmrg * grater than the value of MAX_COLOR_TEXTURE_SAMPLES 326af69d88dSmrg * * <internalformat> is a signed or unsigned integer format and 327af69d88dSmrg * <samples> is greater than the value of MAX_INTEGER_SAMPLES 328af69d88dSmrg */ 329af69d88dSmrg 330af69d88dSmrg if (ctx->Extensions.ARB_texture_multisample) { 331af69d88dSmrg if (_mesa_is_enum_format_integer(internalFormat)) 332af69d88dSmrg return samples > ctx->Const.MaxIntegerSamples 333af69d88dSmrg ? GL_INVALID_OPERATION : GL_NO_ERROR; 334af69d88dSmrg 335af69d88dSmrg if (target == GL_TEXTURE_2D_MULTISAMPLE || 336af69d88dSmrg target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { 337af69d88dSmrg 338af69d88dSmrg if (_mesa_is_depth_or_stencil_format(internalFormat)) 339af69d88dSmrg return samples > ctx->Const.MaxDepthTextureSamples 340af69d88dSmrg ? GL_INVALID_OPERATION : GL_NO_ERROR; 341af69d88dSmrg else 342af69d88dSmrg return samples > ctx->Const.MaxColorTextureSamples 343af69d88dSmrg ? GL_INVALID_OPERATION : GL_NO_ERROR; 344af69d88dSmrg } 345af69d88dSmrg } 346af69d88dSmrg 347af69d88dSmrg /* No more specific limit is available, so just use MAX_SAMPLES: 348af69d88dSmrg * 349af69d88dSmrg * On p205 of the GL3.1 spec: 350af69d88dSmrg * 351af69d88dSmrg * "... or if samples is greater than MAX_SAMPLES, then the error 352af69d88dSmrg * INVALID_VALUE is generated" 353af69d88dSmrg */ 354af69d88dSmrg return (GLuint) samples > ctx->Const.MaxSamples 355af69d88dSmrg ? GL_INVALID_VALUE : GL_NO_ERROR; 356c1f859d4Smrg} 3577ec681f3Smrg 3587ec681f3Smrgvoid GLAPIENTRY 3597ec681f3Smrg_mesa_AlphaToCoverageDitherControlNV_no_error(GLenum mode) 3607ec681f3Smrg{ 3617ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 3627ec681f3Smrg 3637ec681f3Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewSampleAlphaToXEnable ? 0 : 3647ec681f3Smrg _NEW_MULTISAMPLE, 3657ec681f3Smrg GL_MULTISAMPLE_BIT); 3667ec681f3Smrg ctx->NewDriverState |= ctx->DriverFlags.NewSampleAlphaToXEnable; 3677ec681f3Smrg ctx->Multisample.SampleAlphaToCoverageDitherControl = mode; 3687ec681f3Smrg} 3697ec681f3Smrg 3707ec681f3Smrgvoid GLAPIENTRY 3717ec681f3Smrg_mesa_AlphaToCoverageDitherControlNV(GLenum mode) 3727ec681f3Smrg{ 3737ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 3747ec681f3Smrg 3757ec681f3Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewSampleAlphaToXEnable ? 0 : 3767ec681f3Smrg _NEW_MULTISAMPLE, 3777ec681f3Smrg GL_MULTISAMPLE_BIT); 3787ec681f3Smrg ctx->NewDriverState |= ctx->DriverFlags.NewSampleAlphaToXEnable; 3797ec681f3Smrg switch (mode) { 3807ec681f3Smrg case GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV: 3817ec681f3Smrg case GL_ALPHA_TO_COVERAGE_DITHER_ENABLE_NV: 3827ec681f3Smrg case GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV: 3837ec681f3Smrg ctx->Multisample.SampleAlphaToCoverageDitherControl = mode; 3847ec681f3Smrg break; 3857ec681f3Smrg default: 3867ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glAlphaToCoverageDitherControlNV(invalid parameter)"); 3877ec681f3Smrg } 3887ec681f3Smrg} 389