multisample.c revision af69d88d
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
35
36/**
37 * Called via glSampleCoverageARB
38 */
39void GLAPIENTRY
40_mesa_SampleCoverage(GLclampf value, GLboolean invert)
41{
42   GET_CURRENT_CONTEXT(ctx);
43
44   FLUSH_VERTICES(ctx, 0);
45
46   ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
47   ctx->Multisample.SampleCoverageInvert = invert;
48   ctx->NewState |= _NEW_MULTISAMPLE;
49}
50
51
52/**
53 * Initialize the context's multisample state.
54 * \param ctx  the GL context.
55 */
56void
57_mesa_init_multisample(struct gl_context *ctx)
58{
59   ctx->Multisample.Enabled = GL_TRUE;
60   ctx->Multisample.SampleAlphaToCoverage = GL_FALSE;
61   ctx->Multisample.SampleAlphaToOne = GL_FALSE;
62   ctx->Multisample.SampleCoverage = GL_FALSE;
63   ctx->Multisample.SampleCoverageValue = 1.0;
64   ctx->Multisample.SampleCoverageInvert = GL_FALSE;
65
66   /* ARB_texture_multisample / GL3.2 additions */
67   ctx->Multisample.SampleMask = GL_FALSE;
68   ctx->Multisample.SampleMaskValue = ~(GLbitfield)0;
69}
70
71
72void GLAPIENTRY
73_mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val)
74{
75   GET_CURRENT_CONTEXT(ctx);
76
77   if (ctx->NewState & _NEW_BUFFERS) {
78      _mesa_update_state(ctx);
79   }
80
81   switch (pname) {
82   case GL_SAMPLE_POSITION: {
83      if ((int) index >= ctx->DrawBuffer->Visual.samples) {
84         _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" );
85         return;
86      }
87
88      ctx->Driver.GetSamplePosition(ctx, ctx->DrawBuffer, index, val);
89
90      /* winsys FBOs are upside down */
91      if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
92         val[1] = 1.0f - val[1];
93
94      return;
95   }
96
97   default:
98      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" );
99      return;
100   }
101}
102
103void GLAPIENTRY
104_mesa_SampleMaski(GLuint index, GLbitfield mask)
105{
106   GET_CURRENT_CONTEXT(ctx);
107
108   if (!ctx->Extensions.ARB_texture_multisample) {
109      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMaski");
110      return;
111   }
112
113   if (index != 0) {
114      _mesa_error(ctx, GL_INVALID_VALUE, "glSampleMaski(index)");
115      return;
116   }
117
118   FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
119   ctx->Multisample.SampleMaskValue = mask;
120}
121
122/**
123 * Called via glMinSampleShadingARB
124 */
125void GLAPIENTRY
126_mesa_MinSampleShading(GLclampf value)
127{
128   GET_CURRENT_CONTEXT(ctx);
129
130   if (!ctx->Extensions.ARB_sample_shading || !_mesa_is_desktop_gl(ctx)) {
131      _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading");
132      return;
133   }
134
135   FLUSH_VERTICES(ctx, 0);
136
137   ctx->Multisample.MinSampleShadingValue = CLAMP(value, 0.0, 1.0);
138   ctx->NewState |= _NEW_MULTISAMPLE;
139}
140
141/**
142 * Helper for checking a requested sample count against the limit
143 * for a particular (target, internalFormat) pair. The limit imposed,
144 * and the error generated, both depend on which extensions are supported.
145 *
146 * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is
147 * acceptable.
148 */
149GLenum
150_mesa_check_sample_count(struct gl_context *ctx, GLenum target,
151                         GLenum internalFormat, GLsizei samples)
152{
153   /* If ARB_internalformat_query is supported, then treat its highest
154    * returned sample count as the absolute maximum for this format; it is
155    * allowed to exceed MAX_SAMPLES.
156    *
157    * From the ARB_internalformat_query spec:
158    *
159    * "If <samples is greater than the maximum number of samples supported
160    * for <internalformat> then the error INVALID_OPERATION is generated."
161    */
162   if (ctx->Extensions.ARB_internalformat_query) {
163      GLint buffer[16];
164      int count = ctx->Driver.QuerySamplesForFormat(ctx, target,
165                                                    internalFormat, buffer);
166      int limit = count ? buffer[0] : -1;
167
168      return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR;
169   }
170
171   /* If ARB_texture_multisample is supported, we have separate limits,
172    * which may be lower than MAX_SAMPLES:
173    *
174    * From the ARB_texture_multisample spec, when describing the operation
175    * of RenderbufferStorageMultisample:
176    *
177    * "If <internalformat> is a signed or unsigned integer format and
178    * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the
179    * error INVALID_OPERATION is generated"
180    *
181    * And when describing the operation of TexImage*Multisample:
182    *
183    * "The error INVALID_OPERATION may be generated if any of the following
184    * are true:
185    *
186    * * <internalformat> is a depth/stencil-renderable format and <samples>
187    *   is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES
188    * * <internalformat> is a color-renderable format and <samples> is
189    *   grater than the value of MAX_COLOR_TEXTURE_SAMPLES
190    * * <internalformat> is a signed or unsigned integer format and
191    *   <samples> is greater than the value of MAX_INTEGER_SAMPLES
192    */
193
194   if (ctx->Extensions.ARB_texture_multisample) {
195      if (_mesa_is_enum_format_integer(internalFormat))
196         return samples > ctx->Const.MaxIntegerSamples
197            ? GL_INVALID_OPERATION : GL_NO_ERROR;
198
199      if (target == GL_TEXTURE_2D_MULTISAMPLE ||
200          target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
201
202         if (_mesa_is_depth_or_stencil_format(internalFormat))
203            return samples > ctx->Const.MaxDepthTextureSamples
204               ? GL_INVALID_OPERATION : GL_NO_ERROR;
205         else
206            return samples > ctx->Const.MaxColorTextureSamples
207               ? GL_INVALID_OPERATION : GL_NO_ERROR;
208      }
209   }
210
211   /* No more specific limit is available, so just use MAX_SAMPLES:
212    *
213    * On p205 of the GL3.1 spec:
214    *
215    * "... or if samples is greater than MAX_SAMPLES, then the error
216    * INVALID_VALUE is generated"
217    */
218   return (GLuint) samples > ctx->Const.MaxSamples
219      ? GL_INVALID_VALUE : GL_NO_ERROR;
220}
221