1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Mesa 3-D graphics library
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci/**
27bf215546Sopenharmony_ci * \file viewport.c
28bf215546Sopenharmony_ci * glViewport and glDepthRange functions.
29bf215546Sopenharmony_ci */
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "context.h"
33bf215546Sopenharmony_ci#include "enums.h"
34bf215546Sopenharmony_ci#include "macros.h"
35bf215546Sopenharmony_ci#include "mtypes.h"
36bf215546Sopenharmony_ci#include "viewport.h"
37bf215546Sopenharmony_ci#include "api_exec_decl.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "state_tracker/st_manager.h"
40bf215546Sopenharmony_ci#include "state_tracker/st_context.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic void
43bf215546Sopenharmony_ciclamp_viewport(struct gl_context *ctx, GLfloat *x, GLfloat *y,
44bf215546Sopenharmony_ci               GLfloat *width, GLfloat *height)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   /* clamp width and height to the implementation dependent range */
47bf215546Sopenharmony_ci   *width  = MIN2(*width, (GLfloat) ctx->Const.MaxViewportWidth);
48bf215546Sopenharmony_ci   *height = MIN2(*height, (GLfloat) ctx->Const.MaxViewportHeight);
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   /* The GL_ARB_viewport_array spec says:
51bf215546Sopenharmony_ci    *
52bf215546Sopenharmony_ci    *     "The location of the viewport's bottom-left corner, given by (x,y),
53bf215546Sopenharmony_ci    *     are clamped to be within the implementation-dependent viewport
54bf215546Sopenharmony_ci    *     bounds range.  The viewport bounds range [min, max] tuple may be
55bf215546Sopenharmony_ci    *     determined by calling GetFloatv with the symbolic constant
56bf215546Sopenharmony_ci    *     VIEWPORT_BOUNDS_RANGE (see section 6.1)."
57bf215546Sopenharmony_ci    */
58bf215546Sopenharmony_ci   if (_mesa_has_ARB_viewport_array(ctx) ||
59bf215546Sopenharmony_ci       _mesa_has_OES_viewport_array(ctx)) {
60bf215546Sopenharmony_ci      *x = CLAMP(*x,
61bf215546Sopenharmony_ci                 ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
62bf215546Sopenharmony_ci      *y = CLAMP(*y,
63bf215546Sopenharmony_ci                 ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
64bf215546Sopenharmony_ci   }
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic void
68bf215546Sopenharmony_ciset_viewport_no_notify(struct gl_context *ctx, unsigned idx,
69bf215546Sopenharmony_ci                       GLfloat x, GLfloat y,
70bf215546Sopenharmony_ci                       GLfloat width, GLfloat height)
71bf215546Sopenharmony_ci{
72bf215546Sopenharmony_ci   if (ctx->ViewportArray[idx].X == x &&
73bf215546Sopenharmony_ci       ctx->ViewportArray[idx].Width == width &&
74bf215546Sopenharmony_ci       ctx->ViewportArray[idx].Y == y &&
75bf215546Sopenharmony_ci       ctx->ViewportArray[idx].Height == height)
76bf215546Sopenharmony_ci      return;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, 0, GL_VIEWPORT_BIT);
79bf215546Sopenharmony_ci   ctx->NewDriverState |= ST_NEW_VIEWPORT;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   ctx->ViewportArray[idx].X = x;
82bf215546Sopenharmony_ci   ctx->ViewportArray[idx].Width = width;
83bf215546Sopenharmony_ci   ctx->ViewportArray[idx].Y = y;
84bf215546Sopenharmony_ci   ctx->ViewportArray[idx].Height = height;
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cistruct gl_viewport_inputs {
88bf215546Sopenharmony_ci   GLfloat X, Y;                /**< position */
89bf215546Sopenharmony_ci   GLfloat Width, Height;       /**< size */
90bf215546Sopenharmony_ci};
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_cistruct gl_depthrange_inputs {
93bf215546Sopenharmony_ci   GLdouble Near, Far;          /**< Depth buffer range */
94bf215546Sopenharmony_ci};
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistatic void
97bf215546Sopenharmony_civiewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width,
98bf215546Sopenharmony_ci         GLsizei height)
99bf215546Sopenharmony_ci{
100bf215546Sopenharmony_ci   struct gl_viewport_inputs input = { x, y, width, height };
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   /* Clamp the viewport to the implementation dependent values. */
103bf215546Sopenharmony_ci   clamp_viewport(ctx, &input.X, &input.Y, &input.Width, &input.Height);
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   /* The GL_ARB_viewport_array spec says:
106bf215546Sopenharmony_ci    *
107bf215546Sopenharmony_ci    *     "Viewport sets the parameters for all viewports to the same values
108bf215546Sopenharmony_ci    *     and is equivalent (assuming no errors are generated) to:
109bf215546Sopenharmony_ci    *
110bf215546Sopenharmony_ci    *     for (uint i = 0; i < MAX_VIEWPORTS; i++)
111bf215546Sopenharmony_ci    *         ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h);"
112bf215546Sopenharmony_ci    *
113bf215546Sopenharmony_ci    * Set all of the viewports supported by the implementation, but only
114bf215546Sopenharmony_ci    * signal the driver once at the end.
115bf215546Sopenharmony_ci    */
116bf215546Sopenharmony_ci   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++)
117bf215546Sopenharmony_ci      set_viewport_no_notify(ctx, i, input.X, input.Y, input.Width, input.Height);
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   if (ctx->invalidate_on_gl_viewport)
120bf215546Sopenharmony_ci      st_manager_invalidate_drawables(ctx);
121bf215546Sopenharmony_ci}
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci/**
124bf215546Sopenharmony_ci * Set the viewport.
125bf215546Sopenharmony_ci * \sa Called via glViewport() or display list execution.
126bf215546Sopenharmony_ci *
127bf215546Sopenharmony_ci * Flushes the vertices and calls _mesa_set_viewport() with the given
128bf215546Sopenharmony_ci * parameters.
129bf215546Sopenharmony_ci */
130bf215546Sopenharmony_civoid GLAPIENTRY
131bf215546Sopenharmony_ci_mesa_Viewport_no_error(GLint x, GLint y, GLsizei width, GLsizei height)
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
134bf215546Sopenharmony_ci   viewport(ctx, x, y, width, height);
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_civoid GLAPIENTRY
138bf215546Sopenharmony_ci_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
143bf215546Sopenharmony_ci      _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   if (width < 0 || height < 0) {
146bf215546Sopenharmony_ci      _mesa_error(ctx,  GL_INVALID_VALUE,
147bf215546Sopenharmony_ci                   "glViewport(%d, %d, %d, %d)", x, y, width, height);
148bf215546Sopenharmony_ci      return;
149bf215546Sopenharmony_ci   }
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   viewport(ctx, x, y, width, height);
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci/**
156bf215546Sopenharmony_ci * Set new viewport parameters and update derived state.
157bf215546Sopenharmony_ci * Usually called from _mesa_Viewport().
158bf215546Sopenharmony_ci *
159bf215546Sopenharmony_ci * \param ctx GL context.
160bf215546Sopenharmony_ci * \param idx    Index of the viewport to be updated.
161bf215546Sopenharmony_ci * \param x, y coordinates of the lower left corner of the viewport rectangle.
162bf215546Sopenharmony_ci * \param width width of the viewport rectangle.
163bf215546Sopenharmony_ci * \param height height of the viewport rectangle.
164bf215546Sopenharmony_ci */
165bf215546Sopenharmony_civoid
166bf215546Sopenharmony_ci_mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y,
167bf215546Sopenharmony_ci                    GLfloat width, GLfloat height)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   clamp_viewport(ctx, &x, &y, &width, &height);
170bf215546Sopenharmony_ci   set_viewport_no_notify(ctx, idx, x, y, width, height);
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   if (ctx->invalidate_on_gl_viewport)
173bf215546Sopenharmony_ci      st_manager_invalidate_drawables(ctx);
174bf215546Sopenharmony_ci}
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_cistatic void
177bf215546Sopenharmony_civiewport_array(struct gl_context *ctx, GLuint first, GLsizei count,
178bf215546Sopenharmony_ci               struct gl_viewport_inputs *inputs)
179bf215546Sopenharmony_ci{
180bf215546Sopenharmony_ci   for (GLsizei i = 0; i < count; i++) {
181bf215546Sopenharmony_ci      clamp_viewport(ctx, &inputs[i].X, &inputs[i].Y,
182bf215546Sopenharmony_ci                     &inputs[i].Width, &inputs[i].Height);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci      set_viewport_no_notify(ctx, i + first, inputs[i].X, inputs[i].Y,
185bf215546Sopenharmony_ci                             inputs[i].Width, inputs[i].Height);
186bf215546Sopenharmony_ci   }
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   if (ctx->invalidate_on_gl_viewport)
189bf215546Sopenharmony_ci      st_manager_invalidate_drawables(ctx);
190bf215546Sopenharmony_ci}
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_civoid GLAPIENTRY
193bf215546Sopenharmony_ci_mesa_ViewportArrayv_no_error(GLuint first, GLsizei count, const GLfloat *v)
194bf215546Sopenharmony_ci{
195bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v;
198bf215546Sopenharmony_ci   viewport_array(ctx, first, count, p);
199bf215546Sopenharmony_ci}
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_civoid GLAPIENTRY
202bf215546Sopenharmony_ci_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   int i;
205bf215546Sopenharmony_ci   struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v;
206bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
209bf215546Sopenharmony_ci      _mesa_debug(ctx, "glViewportArrayv %d %d\n", first, count);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   if ((first + count) > ctx->Const.MaxViewports) {
212bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
213bf215546Sopenharmony_ci                  "glViewportArrayv: first (%d) + count (%d) > MaxViewports "
214bf215546Sopenharmony_ci                  "(%d)",
215bf215546Sopenharmony_ci                  first, count, ctx->Const.MaxViewports);
216bf215546Sopenharmony_ci      return;
217bf215546Sopenharmony_ci   }
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   /* Verify width & height */
220bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
221bf215546Sopenharmony_ci      if (p[i].Width < 0 || p[i].Height < 0) {
222bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
223bf215546Sopenharmony_ci                     "glViewportArrayv: index (%d) width or height < 0 "
224bf215546Sopenharmony_ci                     "(%f, %f)",
225bf215546Sopenharmony_ci                     i + first, p[i].Width, p[i].Height);
226bf215546Sopenharmony_ci         return;
227bf215546Sopenharmony_ci      }
228bf215546Sopenharmony_ci   }
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   viewport_array(ctx, first, count, p);
231bf215546Sopenharmony_ci}
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_cistatic void
234bf215546Sopenharmony_civiewport_indexed_err(struct gl_context *ctx, GLuint index, GLfloat x, GLfloat y,
235bf215546Sopenharmony_ci                     GLfloat w, GLfloat h, const char *function)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
238bf215546Sopenharmony_ci      _mesa_debug(ctx, "%s(%d, %f, %f, %f, %f)\n",
239bf215546Sopenharmony_ci                  function, index, x, y, w, h);
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   if (index >= ctx->Const.MaxViewports) {
242bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
243bf215546Sopenharmony_ci                  "%s: index (%d) >= MaxViewports (%d)",
244bf215546Sopenharmony_ci                  function, index, ctx->Const.MaxViewports);
245bf215546Sopenharmony_ci      return;
246bf215546Sopenharmony_ci   }
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   /* Verify width & height */
249bf215546Sopenharmony_ci   if (w < 0 || h < 0) {
250bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
251bf215546Sopenharmony_ci                  "%s: index (%d) width or height < 0 (%f, %f)",
252bf215546Sopenharmony_ci                  function, index, w, h);
253bf215546Sopenharmony_ci      return;
254bf215546Sopenharmony_ci   }
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   _mesa_set_viewport(ctx, index, x, y, w, h);
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_civoid GLAPIENTRY
260bf215546Sopenharmony_ci_mesa_ViewportIndexedf_no_error(GLuint index, GLfloat x, GLfloat y,
261bf215546Sopenharmony_ci                                GLfloat w, GLfloat h)
262bf215546Sopenharmony_ci{
263bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
264bf215546Sopenharmony_ci   _mesa_set_viewport(ctx, index, x, y, w, h);
265bf215546Sopenharmony_ci}
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_civoid GLAPIENTRY
268bf215546Sopenharmony_ci_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
269bf215546Sopenharmony_ci                       GLfloat w, GLfloat h)
270bf215546Sopenharmony_ci{
271bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
272bf215546Sopenharmony_ci   viewport_indexed_err(ctx, index, x, y, w, h, "glViewportIndexedf");
273bf215546Sopenharmony_ci}
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_civoid GLAPIENTRY
276bf215546Sopenharmony_ci_mesa_ViewportIndexedfv_no_error(GLuint index, const GLfloat *v)
277bf215546Sopenharmony_ci{
278bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
279bf215546Sopenharmony_ci   _mesa_set_viewport(ctx, index, v[0], v[1], v[2], v[3]);
280bf215546Sopenharmony_ci}
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_civoid GLAPIENTRY
283bf215546Sopenharmony_ci_mesa_ViewportIndexedfv(GLuint index, const GLfloat *v)
284bf215546Sopenharmony_ci{
285bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
286bf215546Sopenharmony_ci   viewport_indexed_err(ctx, index, v[0], v[1], v[2], v[3],
287bf215546Sopenharmony_ci                        "glViewportIndexedfv");
288bf215546Sopenharmony_ci}
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_cistatic void
291bf215546Sopenharmony_ciset_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
292bf215546Sopenharmony_ci                          GLclampd nearval, GLclampd farval)
293bf215546Sopenharmony_ci{
294bf215546Sopenharmony_ci   if (ctx->ViewportArray[idx].Near == nearval &&
295bf215546Sopenharmony_ci       ctx->ViewportArray[idx].Far == farval)
296bf215546Sopenharmony_ci      return;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   /* The depth range is needed by program state constants. */
299bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, _NEW_VIEWPORT, GL_VIEWPORT_BIT);
300bf215546Sopenharmony_ci   ctx->NewDriverState |= ST_NEW_VIEWPORT;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   ctx->ViewportArray[idx].Near = SATURATE(nearval);
303bf215546Sopenharmony_ci   ctx->ViewportArray[idx].Far = SATURATE(farval);
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_civoid
307bf215546Sopenharmony_ci_mesa_set_depth_range(struct gl_context *ctx, unsigned idx,
308bf215546Sopenharmony_ci                      GLclampd nearval, GLclampd farval)
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   set_depth_range_no_notify(ctx, idx, nearval, farval);
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci/**
314bf215546Sopenharmony_ci * Called by glDepthRange
315bf215546Sopenharmony_ci *
316bf215546Sopenharmony_ci * \param nearval  specifies the Z buffer value which should correspond to
317bf215546Sopenharmony_ci *                 the near clip plane
318bf215546Sopenharmony_ci * \param farval  specifies the Z buffer value which should correspond to
319bf215546Sopenharmony_ci *                the far clip plane
320bf215546Sopenharmony_ci */
321bf215546Sopenharmony_civoid GLAPIENTRY
322bf215546Sopenharmony_ci_mesa_DepthRange(GLclampd nearval, GLclampd farval)
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci   unsigned i;
325bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   if (MESA_VERBOSE&VERBOSE_API)
328bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   /* The GL_ARB_viewport_array spec says:
331bf215546Sopenharmony_ci    *
332bf215546Sopenharmony_ci    *     "DepthRange sets the depth range for all viewports to the same
333bf215546Sopenharmony_ci    *     values and is equivalent (assuming no errors are generated) to:
334bf215546Sopenharmony_ci    *
335bf215546Sopenharmony_ci    *     for (uint i = 0; i < MAX_VIEWPORTS; i++)
336bf215546Sopenharmony_ci    *         DepthRangeIndexed(i, n, f);"
337bf215546Sopenharmony_ci    *
338bf215546Sopenharmony_ci    * Set the depth range for all of the viewports supported by the
339bf215546Sopenharmony_ci    * implementation, but only signal the driver once at the end.
340bf215546Sopenharmony_ci    */
341bf215546Sopenharmony_ci   for (i = 0; i < ctx->Const.MaxViewports; i++)
342bf215546Sopenharmony_ci      set_depth_range_no_notify(ctx, i, nearval, farval);
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_civoid GLAPIENTRY
346bf215546Sopenharmony_ci_mesa_DepthRangef(GLclampf nearval, GLclampf farval)
347bf215546Sopenharmony_ci{
348bf215546Sopenharmony_ci   _mesa_DepthRange(nearval, farval);
349bf215546Sopenharmony_ci}
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci/**
352bf215546Sopenharmony_ci * Update a range DepthRange values
353bf215546Sopenharmony_ci *
354bf215546Sopenharmony_ci * \param first   starting array index
355bf215546Sopenharmony_ci * \param count   count of DepthRange items to update
356bf215546Sopenharmony_ci * \param v       pointer to memory containing
357bf215546Sopenharmony_ci *                GLclampd near and far clip-plane values
358bf215546Sopenharmony_ci */
359bf215546Sopenharmony_cistatic ALWAYS_INLINE void
360bf215546Sopenharmony_cidepth_range_arrayv(struct gl_context *ctx, GLuint first, GLsizei count,
361bf215546Sopenharmony_ci                   const struct gl_depthrange_inputs *const inputs)
362bf215546Sopenharmony_ci{
363bf215546Sopenharmony_ci   for (GLsizei i = 0; i < count; i++)
364bf215546Sopenharmony_ci      set_depth_range_no_notify(ctx, i + first, inputs[i].Near, inputs[i].Far);
365bf215546Sopenharmony_ci}
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_civoid GLAPIENTRY
368bf215546Sopenharmony_ci_mesa_DepthRangeArrayv_no_error(GLuint first, GLsizei count, const GLclampd *v)
369bf215546Sopenharmony_ci{
370bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   const struct gl_depthrange_inputs *const p =
373bf215546Sopenharmony_ci      (struct gl_depthrange_inputs *)v;
374bf215546Sopenharmony_ci   depth_range_arrayv(ctx, first, count, p);
375bf215546Sopenharmony_ci}
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_civoid GLAPIENTRY
378bf215546Sopenharmony_ci_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd *v)
379bf215546Sopenharmony_ci{
380bf215546Sopenharmony_ci   const struct gl_depthrange_inputs *const p =
381bf215546Sopenharmony_ci      (struct gl_depthrange_inputs *) v;
382bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
385bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDepthRangeArrayv %d %d\n", first, count);
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   if ((first + count) > ctx->Const.MaxViewports) {
388bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
389bf215546Sopenharmony_ci                  "glDepthRangev: first (%d) + count (%d) >= MaxViewports (%d)",
390bf215546Sopenharmony_ci                  first, count, ctx->Const.MaxViewports);
391bf215546Sopenharmony_ci      return;
392bf215546Sopenharmony_ci   }
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   depth_range_arrayv(ctx, first, count, p);
395bf215546Sopenharmony_ci}
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_civoid GLAPIENTRY
398bf215546Sopenharmony_ci_mesa_DepthRangeArrayfvOES(GLuint first, GLsizei count, const GLfloat *v)
399bf215546Sopenharmony_ci{
400bf215546Sopenharmony_ci   int i;
401bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
404bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDepthRangeArrayfv %d %d\n", first, count);
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   if ((first + count) > ctx->Const.MaxViewports) {
407bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
408bf215546Sopenharmony_ci                  "glDepthRangeArrayfv: first (%d) + count (%d) >= MaxViewports (%d)",
409bf215546Sopenharmony_ci                  first, count, ctx->Const.MaxViewports);
410bf215546Sopenharmony_ci      return;
411bf215546Sopenharmony_ci   }
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   for (i = 0; i < count; i++)
414bf215546Sopenharmony_ci      set_depth_range_no_notify(ctx, i + first, v[i * 2], v[i * 2 + 1]);
415bf215546Sopenharmony_ci}
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ci/**
418bf215546Sopenharmony_ci * Update a single DepthRange
419bf215546Sopenharmony_ci *
420bf215546Sopenharmony_ci * \param index    array index to update
421bf215546Sopenharmony_ci * \param nearval  specifies the Z buffer value which should correspond to
422bf215546Sopenharmony_ci *                 the near clip plane
423bf215546Sopenharmony_ci * \param farval   specifies the Z buffer value which should correspond to
424bf215546Sopenharmony_ci *                 the far clip plane
425bf215546Sopenharmony_ci */
426bf215546Sopenharmony_civoid GLAPIENTRY
427bf215546Sopenharmony_ci_mesa_DepthRangeIndexed_no_error(GLuint index, GLclampd nearval,
428bf215546Sopenharmony_ci                                 GLclampd farval)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
431bf215546Sopenharmony_ci   _mesa_set_depth_range(ctx, index, nearval, farval);
432bf215546Sopenharmony_ci}
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_civoid GLAPIENTRY
436bf215546Sopenharmony_ci_mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval)
437bf215546Sopenharmony_ci{
438bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
441bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDepthRangeIndexed(%d, %f, %f)\n",
442bf215546Sopenharmony_ci                  index, nearval, farval);
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   if (index >= ctx->Const.MaxViewports) {
445bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
446bf215546Sopenharmony_ci                  "glDepthRangeIndexed: index (%d) >= MaxViewports (%d)",
447bf215546Sopenharmony_ci                  index, ctx->Const.MaxViewports);
448bf215546Sopenharmony_ci      return;
449bf215546Sopenharmony_ci   }
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   _mesa_set_depth_range(ctx, index, nearval, farval);
452bf215546Sopenharmony_ci}
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_civoid GLAPIENTRY
455bf215546Sopenharmony_ci_mesa_DepthRangeIndexedfOES(GLuint index, GLfloat nearval, GLfloat farval)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   _mesa_DepthRangeIndexed(index, nearval, farval);
458bf215546Sopenharmony_ci}
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci/**
461bf215546Sopenharmony_ci * Initialize the context viewport attribute group.
462bf215546Sopenharmony_ci * \param ctx  the GL context.
463bf215546Sopenharmony_ci */
464bf215546Sopenharmony_civoid _mesa_init_viewport(struct gl_context *ctx)
465bf215546Sopenharmony_ci{
466bf215546Sopenharmony_ci   unsigned i;
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   ctx->Transform.ClipOrigin = GL_LOWER_LEFT;
469bf215546Sopenharmony_ci   ctx->Transform.ClipDepthMode = GL_NEGATIVE_ONE_TO_ONE;
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   /* Note: ctx->Const.MaxViewports may not have been set by the driver yet,
472bf215546Sopenharmony_ci    * so just initialize all of them.
473bf215546Sopenharmony_ci    */
474bf215546Sopenharmony_ci   for (i = 0; i < MAX_VIEWPORTS; i++) {
475bf215546Sopenharmony_ci      /* Viewport group */
476bf215546Sopenharmony_ci      ctx->ViewportArray[i].X = 0;
477bf215546Sopenharmony_ci      ctx->ViewportArray[i].Y = 0;
478bf215546Sopenharmony_ci      ctx->ViewportArray[i].Width = 0;
479bf215546Sopenharmony_ci      ctx->ViewportArray[i].Height = 0;
480bf215546Sopenharmony_ci      ctx->ViewportArray[i].Near = 0.0;
481bf215546Sopenharmony_ci      ctx->ViewportArray[i].Far = 1.0;
482bf215546Sopenharmony_ci      ctx->ViewportArray[i].SwizzleX = GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV;
483bf215546Sopenharmony_ci      ctx->ViewportArray[i].SwizzleY = GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV;
484bf215546Sopenharmony_ci      ctx->ViewportArray[i].SwizzleZ = GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV;
485bf215546Sopenharmony_ci      ctx->ViewportArray[i].SwizzleW = GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV;
486bf215546Sopenharmony_ci   }
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   ctx->SubpixelPrecisionBias[0] = 0;
489bf215546Sopenharmony_ci   ctx->SubpixelPrecisionBias[1] = 0;
490bf215546Sopenharmony_ci}
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_cistatic ALWAYS_INLINE void
494bf215546Sopenharmony_ciclip_control(struct gl_context *ctx, GLenum origin, GLenum depth, bool no_error)
495bf215546Sopenharmony_ci{
496bf215546Sopenharmony_ci   if (ctx->Transform.ClipOrigin == origin &&
497bf215546Sopenharmony_ci       ctx->Transform.ClipDepthMode == depth)
498bf215546Sopenharmony_ci      return;
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   if (!no_error &&
501bf215546Sopenharmony_ci       origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) {
502bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl");
503bf215546Sopenharmony_ci      return;
504bf215546Sopenharmony_ci   }
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci   if (!no_error &&
507bf215546Sopenharmony_ci       depth != GL_NEGATIVE_ONE_TO_ONE && depth != GL_ZERO_TO_ONE) {
508bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl");
509bf215546Sopenharmony_ci      return;
510bf215546Sopenharmony_ci   }
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   /* Affects transform state and the viewport transform */
513bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, 0, GL_TRANSFORM_BIT);
514bf215546Sopenharmony_ci   ctx->NewDriverState |= ST_NEW_VIEWPORT | ST_NEW_RASTERIZER;
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci   if (ctx->Transform.ClipOrigin != origin) {
517bf215546Sopenharmony_ci      ctx->Transform.ClipOrigin = origin;
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci      /* Affects the winding order of the front face. */
520bf215546Sopenharmony_ci      ctx->NewDriverState |= ST_NEW_RASTERIZER;
521bf215546Sopenharmony_ci   }
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   if (ctx->Transform.ClipDepthMode != depth) {
524bf215546Sopenharmony_ci      ctx->Transform.ClipDepthMode = depth;
525bf215546Sopenharmony_ci   }
526bf215546Sopenharmony_ci}
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_civoid GLAPIENTRY
530bf215546Sopenharmony_ci_mesa_ClipControl_no_error(GLenum origin, GLenum depth)
531bf215546Sopenharmony_ci{
532bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
533bf215546Sopenharmony_ci   clip_control(ctx, origin, depth, true);
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_civoid GLAPIENTRY
538bf215546Sopenharmony_ci_mesa_ClipControl(GLenum origin, GLenum depth)
539bf215546Sopenharmony_ci{
540bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
543bf215546Sopenharmony_ci      _mesa_debug(ctx, "glClipControl(%s, %s)\n",
544bf215546Sopenharmony_ci	          _mesa_enum_to_string(origin),
545bf215546Sopenharmony_ci                  _mesa_enum_to_string(depth));
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci   ASSERT_OUTSIDE_BEGIN_END(ctx);
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   if (!ctx->Extensions.ARB_clip_control) {
550bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glClipControl");
551bf215546Sopenharmony_ci      return;
552bf215546Sopenharmony_ci   }
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   clip_control(ctx, origin, depth, false);
555bf215546Sopenharmony_ci}
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci/**
558bf215546Sopenharmony_ci * Computes the scaling and the translation part of the
559bf215546Sopenharmony_ci * viewport transform matrix of the \param i-th viewport
560bf215546Sopenharmony_ci * and writes that into \param scale and \param translate.
561bf215546Sopenharmony_ci */
562bf215546Sopenharmony_civoid
563bf215546Sopenharmony_ci_mesa_get_viewport_xform(struct gl_context *ctx, unsigned i,
564bf215546Sopenharmony_ci                         float scale[3], float translate[3])
565bf215546Sopenharmony_ci{
566bf215546Sopenharmony_ci   float x = ctx->ViewportArray[i].X;
567bf215546Sopenharmony_ci   float y = ctx->ViewportArray[i].Y;
568bf215546Sopenharmony_ci   float half_width = 0.5f * ctx->ViewportArray[i].Width;
569bf215546Sopenharmony_ci   float half_height = 0.5f * ctx->ViewportArray[i].Height;
570bf215546Sopenharmony_ci   double n = ctx->ViewportArray[i].Near;
571bf215546Sopenharmony_ci   double f = ctx->ViewportArray[i].Far;
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci   scale[0] = half_width;
574bf215546Sopenharmony_ci   translate[0] = half_width + x;
575bf215546Sopenharmony_ci   if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT) {
576bf215546Sopenharmony_ci      scale[1] = -half_height;
577bf215546Sopenharmony_ci   } else {
578bf215546Sopenharmony_ci      scale[1] = half_height;
579bf215546Sopenharmony_ci   }
580bf215546Sopenharmony_ci   translate[1] = half_height + y;
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   if (ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE) {
583bf215546Sopenharmony_ci      scale[2] = 0.5 * (f - n);
584bf215546Sopenharmony_ci      translate[2] = 0.5 * (n + f);
585bf215546Sopenharmony_ci   } else {
586bf215546Sopenharmony_ci      scale[2] = f - n;
587bf215546Sopenharmony_ci      translate[2] = n;
588bf215546Sopenharmony_ci   }
589bf215546Sopenharmony_ci}
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_cistatic void
593bf215546Sopenharmony_cisubpixel_precision_bias(struct gl_context *ctx, GLuint xbits, GLuint ybits)
594bf215546Sopenharmony_ci{
595bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
596bf215546Sopenharmony_ci      _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, 0, GL_VIEWPORT_BIT);
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   ctx->SubpixelPrecisionBias[0] = xbits;
601bf215546Sopenharmony_ci   ctx->SubpixelPrecisionBias[1] = ybits;
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   ctx->NewDriverState |= ST_NEW_RASTERIZER;
604bf215546Sopenharmony_ci}
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_civoid GLAPIENTRY
607bf215546Sopenharmony_ci_mesa_SubpixelPrecisionBiasNV_no_error(GLuint xbits, GLuint ybits)
608bf215546Sopenharmony_ci{
609bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
612bf215546Sopenharmony_ci      _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits);
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci   subpixel_precision_bias(ctx, xbits, ybits);
615bf215546Sopenharmony_ci}
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_civoid GLAPIENTRY
618bf215546Sopenharmony_ci_mesa_SubpixelPrecisionBiasNV(GLuint xbits, GLuint ybits)
619bf215546Sopenharmony_ci{
620bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
623bf215546Sopenharmony_ci      _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits);
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci   ASSERT_OUTSIDE_BEGIN_END(ctx);
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   if (!ctx->Extensions.NV_conservative_raster) {
628bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
629bf215546Sopenharmony_ci                  "glSubpixelPrecisionBiasNV not supported");
630bf215546Sopenharmony_ci      return;
631bf215546Sopenharmony_ci   }
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   if (xbits > ctx->Const.MaxSubpixelPrecisionBiasBits) {
634bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV");
635bf215546Sopenharmony_ci      return;
636bf215546Sopenharmony_ci   }
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci   if (ybits > ctx->Const.MaxSubpixelPrecisionBiasBits) {
639bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV");
640bf215546Sopenharmony_ci      return;
641bf215546Sopenharmony_ci   }
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci   subpixel_precision_bias(ctx, xbits, ybits);
644bf215546Sopenharmony_ci}
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_cistatic void
647bf215546Sopenharmony_ciset_viewport_swizzle(struct gl_context *ctx, GLuint index,
648bf215546Sopenharmony_ci                     GLenum swizzlex, GLenum swizzley,
649bf215546Sopenharmony_ci                     GLenum swizzlez, GLenum swizzlew)
650bf215546Sopenharmony_ci{
651bf215546Sopenharmony_ci   struct gl_viewport_attrib *viewport = &ctx->ViewportArray[index];
652bf215546Sopenharmony_ci   if (viewport->SwizzleX == swizzlex &&
653bf215546Sopenharmony_ci       viewport->SwizzleY == swizzley &&
654bf215546Sopenharmony_ci       viewport->SwizzleZ == swizzlez &&
655bf215546Sopenharmony_ci       viewport->SwizzleW == swizzlew)
656bf215546Sopenharmony_ci      return;
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, _NEW_VIEWPORT, GL_VIEWPORT_BIT);
659bf215546Sopenharmony_ci   ctx->NewDriverState |= ST_NEW_VIEWPORT;
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci   viewport->SwizzleX = swizzlex;
662bf215546Sopenharmony_ci   viewport->SwizzleY = swizzley;
663bf215546Sopenharmony_ci   viewport->SwizzleZ = swizzlez;
664bf215546Sopenharmony_ci   viewport->SwizzleW = swizzlew;
665bf215546Sopenharmony_ci}
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_civoid GLAPIENTRY
668bf215546Sopenharmony_ci_mesa_ViewportSwizzleNV_no_error(GLuint index,
669bf215546Sopenharmony_ci                                 GLenum swizzlex, GLenum swizzley,
670bf215546Sopenharmony_ci                                 GLenum swizzlez, GLenum swizzlew)
671bf215546Sopenharmony_ci{
672bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
675bf215546Sopenharmony_ci      _mesa_debug(ctx, "glViewportSwizzleNV(%x, %x, %x, %x)\n",
676bf215546Sopenharmony_ci                  swizzlex, swizzley, swizzlez, swizzlew);
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   set_viewport_swizzle(ctx, index, swizzlex, swizzley, swizzlez, swizzlew);
679bf215546Sopenharmony_ci}
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_cistatic bool
682bf215546Sopenharmony_civerify_viewport_swizzle(GLenum swizzle)
683bf215546Sopenharmony_ci{
684bf215546Sopenharmony_ci   return swizzle >= GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV &&
685bf215546Sopenharmony_ci      swizzle <= GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV;
686bf215546Sopenharmony_ci}
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_civoid GLAPIENTRY
689bf215546Sopenharmony_ci_mesa_ViewportSwizzleNV(GLuint index,
690bf215546Sopenharmony_ci                        GLenum swizzlex, GLenum swizzley,
691bf215546Sopenharmony_ci                        GLenum swizzlez, GLenum swizzlew)
692bf215546Sopenharmony_ci{
693bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
696bf215546Sopenharmony_ci      _mesa_debug(ctx, "glViewportSwizzleNV(%x, %x, %x, %x)\n",
697bf215546Sopenharmony_ci                  swizzlex, swizzley, swizzlez, swizzlew);
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci   if (!ctx->Extensions.NV_viewport_swizzle) {
700bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
701bf215546Sopenharmony_ci                  "glViewportSwizzleNV not supported");
702bf215546Sopenharmony_ci      return;
703bf215546Sopenharmony_ci   }
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci   if (index >= ctx->Const.MaxViewports) {
706bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
707bf215546Sopenharmony_ci                  "glViewportSwizzleNV: index (%d) >= MaxViewports (%d)",
708bf215546Sopenharmony_ci                  index, ctx->Const.MaxViewports);
709bf215546Sopenharmony_ci      return;
710bf215546Sopenharmony_ci   }
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci   if (!verify_viewport_swizzle(swizzlex)) {
713bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
714bf215546Sopenharmony_ci                  "glViewportSwizzleNV(swizzlex=%x)", swizzlex);
715bf215546Sopenharmony_ci      return;
716bf215546Sopenharmony_ci   }
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci   if (!verify_viewport_swizzle(swizzley)) {
719bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
720bf215546Sopenharmony_ci                  "glViewportSwizzleNV(swizzley=%x)", swizzley);
721bf215546Sopenharmony_ci      return;
722bf215546Sopenharmony_ci   }
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   if (!verify_viewport_swizzle(swizzlez)) {
725bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
726bf215546Sopenharmony_ci                  "glViewportSwizzleNV(swizzlez=%x)", swizzlez);
727bf215546Sopenharmony_ci      return;
728bf215546Sopenharmony_ci   }
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci   if (!verify_viewport_swizzle(swizzlew)) {
731bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
732bf215546Sopenharmony_ci                  "glViewportSwizzleNV(swizzlew=%x)", swizzlew);
733bf215546Sopenharmony_ci      return;
734bf215546Sopenharmony_ci   }
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   set_viewport_swizzle(ctx, index, swizzlex, swizzley, swizzlez, swizzlew);
737bf215546Sopenharmony_ci}
738