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