1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26#include "main/glheader.h" 27#include "main/context.h" 28#include "main/macros.h" 29#include "main/multisample.h" 30#include "main/mtypes.h" 31#include "main/fbobject.h" 32#include "main/glformats.h" 33#include "main/state.h" 34#include "api_exec_decl.h" 35#include "main/framebuffer.h" 36 37#include "state_tracker/st_context.h" 38#include "state_tracker/st_format.h" 39#include "state_tracker/st_context.h" 40 41/** 42 * Called via glSampleCoverageARB 43 */ 44void GLAPIENTRY 45_mesa_SampleCoverage(GLclampf value, GLboolean invert) 46{ 47 GET_CURRENT_CONTEXT(ctx); 48 49 value = SATURATE(value); 50 51 if (ctx->Multisample.SampleCoverageInvert == invert && 52 ctx->Multisample.SampleCoverageValue == value) 53 return; 54 55 FLUSH_VERTICES(ctx, 0, GL_MULTISAMPLE_BIT); 56 ctx->NewDriverState |= ST_NEW_SAMPLE_STATE; 57 ctx->Multisample.SampleCoverageValue = value; 58 ctx->Multisample.SampleCoverageInvert = invert; 59} 60 61 62/** 63 * Initialize the context's multisample state. 64 * \param ctx the GL context. 65 */ 66void 67_mesa_init_multisample(struct gl_context *ctx) 68{ 69 ctx->Multisample.Enabled = GL_TRUE; 70 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 71 ctx->Multisample.SampleAlphaToCoverageDitherControl = GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV; 72 ctx->Multisample.SampleAlphaToOne = GL_FALSE; 73 ctx->Multisample.SampleCoverage = GL_FALSE; 74 ctx->Multisample.SampleCoverageValue = 1.0; 75 ctx->Multisample.SampleCoverageInvert = GL_FALSE; 76 ctx->Multisample.SampleShading = GL_FALSE; 77 ctx->Multisample.MinSampleShadingValue = 0.0f; 78 79 /* ARB_texture_multisample / GL3.2 additions */ 80 ctx->Multisample.SampleMask = GL_FALSE; 81 ctx->Multisample.SampleMaskValue = ~(GLbitfield)0; 82} 83 84static void 85get_sample_position(struct gl_context *ctx, 86 struct gl_framebuffer *fb, 87 GLuint index, 88 GLfloat *outPos) 89{ 90 struct st_context *st = st_context(ctx); 91 92 st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER); 93 94 if (ctx->pipe->get_sample_position) 95 ctx->pipe->get_sample_position(ctx->pipe, 96 _mesa_geometric_samples(fb), 97 index, outPos); 98 else 99 outPos[0] = outPos[1] = 0.5f; 100} 101 102void GLAPIENTRY 103_mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val) 104{ 105 GET_CURRENT_CONTEXT(ctx); 106 107 if (ctx->NewState & _NEW_BUFFERS) { 108 _mesa_update_state(ctx); 109 } 110 111 switch (pname) { 112 case GL_SAMPLE_POSITION: { 113 if (index >= ctx->DrawBuffer->Visual.samples) { 114 _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" ); 115 return; 116 } 117 118 get_sample_position(ctx, ctx->DrawBuffer, index, val); 119 120 /* FBOs can be upside down (winsys always are)*/ 121 if (ctx->DrawBuffer->FlipY) 122 val[1] = 1.0f - val[1]; 123 124 return; 125 } 126 127 case GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB: 128 if (!ctx->Extensions.ARB_sample_locations) { 129 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" ); 130 return; 131 } 132 133 if (index >= MAX_SAMPLE_LOCATION_TABLE_SIZE * 2) { 134 _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" ); 135 return; 136 } 137 138 if (ctx->DrawBuffer->SampleLocationTable) 139 *val = ctx->DrawBuffer->SampleLocationTable[index]; 140 else 141 *val = 0.5f; 142 143 return; 144 145 default: 146 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" ); 147 return; 148 } 149} 150 151static void 152sample_maski(struct gl_context *ctx, GLuint index, GLbitfield mask) 153{ 154 if (ctx->Multisample.SampleMaskValue == mask) 155 return; 156 157 FLUSH_VERTICES(ctx, 0, 0); 158 ctx->NewDriverState |= ST_NEW_SAMPLE_STATE; 159 ctx->Multisample.SampleMaskValue = mask; 160} 161 162void GLAPIENTRY 163_mesa_SampleMaski_no_error(GLuint index, GLbitfield mask) 164{ 165 GET_CURRENT_CONTEXT(ctx); 166 sample_maski(ctx, index, mask); 167} 168 169void GLAPIENTRY 170_mesa_SampleMaski(GLuint index, GLbitfield mask) 171{ 172 GET_CURRENT_CONTEXT(ctx); 173 174 if (!ctx->Extensions.ARB_texture_multisample) { 175 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMaski"); 176 return; 177 } 178 179 if (index != 0) { 180 _mesa_error(ctx, GL_INVALID_VALUE, "glSampleMaski(index)"); 181 return; 182 } 183 184 sample_maski(ctx, index, mask); 185} 186 187static void 188min_sample_shading(struct gl_context *ctx, GLclampf value) 189{ 190 value = SATURATE(value); 191 192 if (ctx->Multisample.MinSampleShadingValue == value) 193 return; 194 195 FLUSH_VERTICES(ctx, 0, GL_MULTISAMPLE_BIT); 196 ctx->NewDriverState |= ctx->DriverFlags.NewSampleShading; 197 ctx->Multisample.MinSampleShadingValue = value; 198} 199 200/** 201 * Called via glMinSampleShadingARB 202 */ 203void GLAPIENTRY 204_mesa_MinSampleShading_no_error(GLclampf value) 205{ 206 GET_CURRENT_CONTEXT(ctx); 207 min_sample_shading(ctx, value); 208} 209 210void GLAPIENTRY 211_mesa_MinSampleShading(GLclampf value) 212{ 213 GET_CURRENT_CONTEXT(ctx); 214 215 if (!_mesa_has_ARB_sample_shading(ctx) && 216 !_mesa_has_OES_sample_shading(ctx)) { 217 _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading"); 218 return; 219 } 220 221 min_sample_shading(ctx, value); 222} 223 224/** 225 * Helper for checking a requested sample count against the limit 226 * for a particular (target, internalFormat) pair. The limit imposed, 227 * and the error generated, both depend on which extensions are supported. 228 * 229 * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is 230 * acceptable. 231 */ 232GLenum 233_mesa_check_sample_count(struct gl_context *ctx, GLenum target, 234 GLenum internalFormat, GLsizei samples, 235 GLsizei storageSamples) 236{ 237 /* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0 238 * specification says: 239 * 240 * "If internalformat is a signed or unsigned integer format and samples 241 * is greater than zero, then the error INVALID_OPERATION is generated." 242 * 243 * This restriction is relaxed for OpenGL ES 3.1. 244 */ 245 if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) && 246 _mesa_is_enum_format_integer(internalFormat) 247 && samples > 0) { 248 return GL_INVALID_OPERATION; 249 } 250 251 if (ctx->Extensions.AMD_framebuffer_multisample_advanced && 252 target == GL_RENDERBUFFER) { 253 if (!_mesa_is_depth_or_stencil_format(internalFormat)) { 254 /* From the AMD_framebuffer_multisample_advanced spec: 255 * 256 * "An INVALID_OPERATION error is generated if <internalformat> 257 * is a color format and <storageSamples> is greater than 258 * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_- 259 * STORAGE_SAMPLES_AMD." 260 */ 261 if (samples > ctx->Const.MaxColorFramebufferSamples) 262 return GL_INVALID_OPERATION; 263 264 /* From the AMD_framebuffer_multisample_advanced spec: 265 * 266 * "An INVALID_OPERATION error is generated if <internalformat> 267 * is a color format and <storageSamples> is greater than 268 * the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_- 269 * STORAGE_SAMPLES_AMD." 270 */ 271 if (storageSamples > ctx->Const.MaxColorFramebufferStorageSamples) 272 return GL_INVALID_OPERATION; 273 274 /* From the AMD_framebuffer_multisample_advanced spec: 275 * 276 * "An INVALID_OPERATION error is generated if <storageSamples> is 277 * greater than <samples>." 278 */ 279 if (storageSamples > samples) 280 return GL_INVALID_OPERATION; 281 282 /* Color renderbuffer sample counts are now fully validated 283 * according to AMD_framebuffer_multisample_advanced. 284 */ 285 return GL_NO_ERROR; 286 } else { 287 /* From the AMD_framebuffer_multisample_advanced spec: 288 * 289 * "An INVALID_OPERATION error is generated if <internalformat> is 290 * a depth or stencil format and <storageSamples> is not equal to 291 * <samples>." 292 */ 293 if (storageSamples != samples) 294 return GL_INVALID_OPERATION; 295 } 296 } else { 297 /* If the extension is unsupported, it's not possible to set 298 * storageSamples differently. 299 */ 300 assert(samples == storageSamples); 301 } 302 303 /* If ARB_internalformat_query is supported, then treat its highest 304 * returned sample count as the absolute maximum for this format; it is 305 * allowed to exceed MAX_SAMPLES. 306 * 307 * From the ARB_internalformat_query spec: 308 * 309 * "If <samples is greater than the maximum number of samples supported 310 * for <internalformat> then the error INVALID_OPERATION is generated." 311 */ 312 if (ctx->Extensions.ARB_internalformat_query) { 313 GLint buffer[16] = {-1}; 314 GLint limit; 315 316 st_QueryInternalFormat(ctx, target, internalFormat, 317 GL_SAMPLES, buffer); 318 /* since the query returns samples sorted in descending order, 319 * the first element is the greatest supported sample value. 320 */ 321 limit = buffer[0]; 322 323 return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR; 324 } 325 326 /* If ARB_texture_multisample is supported, we have separate limits, 327 * which may be lower than MAX_SAMPLES: 328 * 329 * From the ARB_texture_multisample spec, when describing the operation 330 * of RenderbufferStorageMultisample: 331 * 332 * "If <internalformat> is a signed or unsigned integer format and 333 * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the 334 * error INVALID_OPERATION is generated" 335 * 336 * And when describing the operation of TexImage*Multisample: 337 * 338 * "The error INVALID_OPERATION may be generated if any of the following 339 * are true: 340 * 341 * * <internalformat> is a depth/stencil-renderable format and <samples> 342 * is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES 343 * * <internalformat> is a color-renderable format and <samples> is 344 * grater than the value of MAX_COLOR_TEXTURE_SAMPLES 345 * * <internalformat> is a signed or unsigned integer format and 346 * <samples> is greater than the value of MAX_INTEGER_SAMPLES 347 */ 348 349 if (ctx->Extensions.ARB_texture_multisample) { 350 if (_mesa_is_enum_format_integer(internalFormat)) 351 return samples > ctx->Const.MaxIntegerSamples 352 ? GL_INVALID_OPERATION : GL_NO_ERROR; 353 354 if (target == GL_TEXTURE_2D_MULTISAMPLE || 355 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { 356 357 if (_mesa_is_depth_or_stencil_format(internalFormat)) 358 return samples > ctx->Const.MaxDepthTextureSamples 359 ? GL_INVALID_OPERATION : GL_NO_ERROR; 360 else 361 return samples > ctx->Const.MaxColorTextureSamples 362 ? GL_INVALID_OPERATION : GL_NO_ERROR; 363 } 364 } 365 366 /* No more specific limit is available, so just use MAX_SAMPLES: 367 * 368 * On p205 of the GL3.1 spec: 369 * 370 * "... or if samples is greater than MAX_SAMPLES, then the error 371 * INVALID_VALUE is generated" 372 */ 373 return (GLuint) samples > ctx->Const.MaxSamples 374 ? GL_INVALID_VALUE : GL_NO_ERROR; 375} 376 377void GLAPIENTRY 378_mesa_AlphaToCoverageDitherControlNV_no_error(GLenum mode) 379{ 380 GET_CURRENT_CONTEXT(ctx); 381 382 FLUSH_VERTICES(ctx, 0, GL_MULTISAMPLE_BIT); 383 ctx->NewDriverState |= ST_NEW_BLEND; 384 ctx->Multisample.SampleAlphaToCoverageDitherControl = mode; 385} 386 387void GLAPIENTRY 388_mesa_AlphaToCoverageDitherControlNV(GLenum mode) 389{ 390 GET_CURRENT_CONTEXT(ctx); 391 392 FLUSH_VERTICES(ctx, 0, GL_MULTISAMPLE_BIT); 393 ctx->NewDriverState |= ST_NEW_BLEND; 394 switch (mode) { 395 case GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV: 396 case GL_ALPHA_TO_COVERAGE_DITHER_ENABLE_NV: 397 case GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV: 398 ctx->Multisample.SampleAlphaToCoverageDitherControl = mode; 399 break; 400 default: 401 _mesa_error(ctx, GL_INVALID_ENUM, "glAlphaToCoverageDitherControlNV(invalid parameter)"); 402 } 403} 404 405void 406_mesa_GetProgrammableSampleCaps(struct gl_context *ctx, const struct gl_framebuffer *fb, 407 GLuint *outBits, GLuint *outWidth, GLuint *outHeight) 408{ 409 struct st_context *st = st_context(ctx); 410 struct pipe_screen *screen = ctx->pipe->screen; 411 412 st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER); 413 414 *outBits = 4; 415 *outWidth = 1; 416 *outHeight = 1; 417 418 if (ctx->Extensions.ARB_sample_locations) 419 screen->get_sample_pixel_grid(screen, st->state.fb_num_samples, 420 outWidth, outHeight); 421 422 /* We could handle this better in some circumstances, 423 * but it's not really an issue */ 424 if (*outWidth > MAX_SAMPLE_LOCATION_GRID_SIZE || 425 *outHeight > MAX_SAMPLE_LOCATION_GRID_SIZE) { 426 *outWidth = 1; 427 *outHeight = 1; 428 } 429} 430