• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
44 void GLAPIENTRY
_mesa_SampleCoverage(GLclampf value,GLboolean invert)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  */
66 void
_mesa_init_multisample(struct gl_context * ctx)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 
84 static void
get_sample_position(struct gl_context * ctx,struct gl_framebuffer * fb,GLuint index,GLfloat * outPos)85 get_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 
102 void GLAPIENTRY
_mesa_GetMultisamplefv(GLenum pname,GLuint index,GLfloat * val)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 
151 static void
sample_maski(struct gl_context * ctx,GLuint index,GLbitfield mask)152 sample_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 
162 void GLAPIENTRY
_mesa_SampleMaski_no_error(GLuint index,GLbitfield mask)163 _mesa_SampleMaski_no_error(GLuint index, GLbitfield mask)
164 {
165    GET_CURRENT_CONTEXT(ctx);
166    sample_maski(ctx, index, mask);
167 }
168 
169 void GLAPIENTRY
_mesa_SampleMaski(GLuint index,GLbitfield mask)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 
187 static void
min_sample_shading(struct gl_context * ctx,GLclampf value)188 min_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  */
203 void GLAPIENTRY
_mesa_MinSampleShading_no_error(GLclampf value)204 _mesa_MinSampleShading_no_error(GLclampf value)
205 {
206    GET_CURRENT_CONTEXT(ctx);
207    min_sample_shading(ctx, value);
208 }
209 
210 void GLAPIENTRY
_mesa_MinSampleShading(GLclampf value)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  */
232 GLenum
_mesa_check_sample_count(struct gl_context * ctx,GLenum target,GLenum internalFormat,GLsizei samples,GLsizei storageSamples)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 
377 void GLAPIENTRY
_mesa_AlphaToCoverageDitherControlNV_no_error(GLenum mode)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 
387 void GLAPIENTRY
_mesa_AlphaToCoverageDitherControlNV(GLenum mode)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 
405 void
_mesa_GetProgrammableSampleCaps(struct gl_context * ctx,const struct gl_framebuffer * fb,GLuint * outBits,GLuint * outWidth,GLuint * outHeight)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