1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file viewport.c 28848b8605Smrg * glViewport and glDepthRange functions. 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg 32848b8605Smrg#include "context.h" 33b8e80941Smrg#include "enums.h" 34848b8605Smrg#include "macros.h" 35848b8605Smrg#include "mtypes.h" 36848b8605Smrg#include "viewport.h" 37848b8605Smrg 38848b8605Smrgstatic void 39b8e80941Smrgclamp_viewport(struct gl_context *ctx, GLfloat *x, GLfloat *y, 40b8e80941Smrg GLfloat *width, GLfloat *height) 41848b8605Smrg{ 42848b8605Smrg /* clamp width and height to the implementation dependent range */ 43b8e80941Smrg *width = MIN2(*width, (GLfloat) ctx->Const.MaxViewportWidth); 44b8e80941Smrg *height = MIN2(*height, (GLfloat) ctx->Const.MaxViewportHeight); 45848b8605Smrg 46848b8605Smrg /* The GL_ARB_viewport_array spec says: 47848b8605Smrg * 48848b8605Smrg * "The location of the viewport's bottom-left corner, given by (x,y), 49848b8605Smrg * are clamped to be within the implementation-dependent viewport 50848b8605Smrg * bounds range. The viewport bounds range [min, max] tuple may be 51848b8605Smrg * determined by calling GetFloatv with the symbolic constant 52848b8605Smrg * VIEWPORT_BOUNDS_RANGE (see section 6.1)." 53848b8605Smrg */ 54b8e80941Smrg if (_mesa_has_ARB_viewport_array(ctx) || 55b8e80941Smrg _mesa_has_OES_viewport_array(ctx)) { 56b8e80941Smrg *x = CLAMP(*x, 57b8e80941Smrg ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max); 58b8e80941Smrg *y = CLAMP(*y, 59b8e80941Smrg ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max); 60848b8605Smrg } 61b8e80941Smrg} 62b8e80941Smrg 63b8e80941Smrgstatic void 64b8e80941Smrgset_viewport_no_notify(struct gl_context *ctx, unsigned idx, 65b8e80941Smrg GLfloat x, GLfloat y, 66b8e80941Smrg GLfloat width, GLfloat height) 67b8e80941Smrg{ 68b8e80941Smrg if (ctx->ViewportArray[idx].X == x && 69b8e80941Smrg ctx->ViewportArray[idx].Width == width && 70b8e80941Smrg ctx->ViewportArray[idx].Y == y && 71b8e80941Smrg ctx->ViewportArray[idx].Height == height) 72b8e80941Smrg return; 73b8e80941Smrg 74b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewViewport ? 0 : _NEW_VIEWPORT); 75b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewViewport; 76848b8605Smrg 77848b8605Smrg ctx->ViewportArray[idx].X = x; 78848b8605Smrg ctx->ViewportArray[idx].Width = width; 79848b8605Smrg ctx->ViewportArray[idx].Y = y; 80848b8605Smrg ctx->ViewportArray[idx].Height = height; 81848b8605Smrg} 82848b8605Smrg 83848b8605Smrgstruct gl_viewport_inputs { 84848b8605Smrg GLfloat X, Y; /**< position */ 85848b8605Smrg GLfloat Width, Height; /**< size */ 86848b8605Smrg}; 87848b8605Smrg 88848b8605Smrgstruct gl_depthrange_inputs { 89848b8605Smrg GLdouble Near, Far; /**< Depth buffer range */ 90848b8605Smrg}; 91848b8605Smrg 92b8e80941Smrgstatic void 93b8e80941Smrgviewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, 94b8e80941Smrg GLsizei height) 95b8e80941Smrg{ 96b8e80941Smrg struct gl_viewport_inputs input = { x, y, width, height }; 97b8e80941Smrg 98b8e80941Smrg /* Clamp the viewport to the implementation dependent values. */ 99b8e80941Smrg clamp_viewport(ctx, &input.X, &input.Y, &input.Width, &input.Height); 100b8e80941Smrg 101b8e80941Smrg /* The GL_ARB_viewport_array spec says: 102b8e80941Smrg * 103b8e80941Smrg * "Viewport sets the parameters for all viewports to the same values 104b8e80941Smrg * and is equivalent (assuming no errors are generated) to: 105b8e80941Smrg * 106b8e80941Smrg * for (uint i = 0; i < MAX_VIEWPORTS; i++) 107b8e80941Smrg * ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h);" 108b8e80941Smrg * 109b8e80941Smrg * Set all of the viewports supported by the implementation, but only 110b8e80941Smrg * signal the driver once at the end. 111b8e80941Smrg */ 112b8e80941Smrg for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) 113b8e80941Smrg set_viewport_no_notify(ctx, i, input.X, input.Y, input.Width, input.Height); 114b8e80941Smrg 115b8e80941Smrg if (ctx->Driver.Viewport) 116b8e80941Smrg ctx->Driver.Viewport(ctx); 117b8e80941Smrg} 118b8e80941Smrg 119848b8605Smrg/** 120848b8605Smrg * Set the viewport. 121848b8605Smrg * \sa Called via glViewport() or display list execution. 122848b8605Smrg * 123848b8605Smrg * Flushes the vertices and calls _mesa_set_viewport() with the given 124848b8605Smrg * parameters. 125848b8605Smrg */ 126b8e80941Smrgvoid GLAPIENTRY 127b8e80941Smrg_mesa_Viewport_no_error(GLint x, GLint y, GLsizei width, GLsizei height) 128b8e80941Smrg{ 129b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 130b8e80941Smrg viewport(ctx, x, y, width, height); 131b8e80941Smrg} 132b8e80941Smrg 133848b8605Smrgvoid GLAPIENTRY 134848b8605Smrg_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) 135848b8605Smrg{ 136848b8605Smrg GET_CURRENT_CONTEXT(ctx); 137848b8605Smrg 138848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 139848b8605Smrg _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height); 140848b8605Smrg 141848b8605Smrg if (width < 0 || height < 0) { 142848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 143848b8605Smrg "glViewport(%d, %d, %d, %d)", x, y, width, height); 144848b8605Smrg return; 145848b8605Smrg } 146848b8605Smrg 147b8e80941Smrg viewport(ctx, x, y, width, height); 148848b8605Smrg} 149848b8605Smrg 150848b8605Smrg 151848b8605Smrg/** 152b8e80941Smrg * Set new viewport parameters and update derived state. 153b8e80941Smrg * Usually called from _mesa_Viewport(). 154848b8605Smrg * 155848b8605Smrg * \param ctx GL context. 156848b8605Smrg * \param idx Index of the viewport to be updated. 157848b8605Smrg * \param x, y coordinates of the lower left corner of the viewport rectangle. 158848b8605Smrg * \param width width of the viewport rectangle. 159848b8605Smrg * \param height height of the viewport rectangle. 160848b8605Smrg */ 161848b8605Smrgvoid 162848b8605Smrg_mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y, 163848b8605Smrg GLfloat width, GLfloat height) 164848b8605Smrg{ 165b8e80941Smrg clamp_viewport(ctx, &x, &y, &width, &height); 166848b8605Smrg set_viewport_no_notify(ctx, idx, x, y, width, height); 167848b8605Smrg 168b8e80941Smrg if (ctx->Driver.Viewport) 169848b8605Smrg ctx->Driver.Viewport(ctx); 170b8e80941Smrg} 171b8e80941Smrg 172b8e80941Smrgstatic void 173b8e80941Smrgviewport_array(struct gl_context *ctx, GLuint first, GLsizei count, 174b8e80941Smrg struct gl_viewport_inputs *inputs) 175b8e80941Smrg{ 176b8e80941Smrg for (GLsizei i = 0; i < count; i++) { 177b8e80941Smrg clamp_viewport(ctx, &inputs[i].X, &inputs[i].Y, 178b8e80941Smrg &inputs[i].Width, &inputs[i].Height); 179b8e80941Smrg 180b8e80941Smrg set_viewport_no_notify(ctx, i + first, inputs[i].X, inputs[i].Y, 181b8e80941Smrg inputs[i].Width, inputs[i].Height); 182848b8605Smrg } 183b8e80941Smrg 184b8e80941Smrg if (ctx->Driver.Viewport) 185b8e80941Smrg ctx->Driver.Viewport(ctx); 186b8e80941Smrg} 187b8e80941Smrg 188b8e80941Smrgvoid GLAPIENTRY 189b8e80941Smrg_mesa_ViewportArrayv_no_error(GLuint first, GLsizei count, const GLfloat *v) 190b8e80941Smrg{ 191b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 192b8e80941Smrg 193b8e80941Smrg struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v; 194b8e80941Smrg viewport_array(ctx, first, count, p); 195848b8605Smrg} 196848b8605Smrg 197848b8605Smrgvoid GLAPIENTRY 198848b8605Smrg_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v) 199848b8605Smrg{ 200848b8605Smrg int i; 201b8e80941Smrg struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v; 202848b8605Smrg GET_CURRENT_CONTEXT(ctx); 203848b8605Smrg 204848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 205848b8605Smrg _mesa_debug(ctx, "glViewportArrayv %d %d\n", first, count); 206848b8605Smrg 207848b8605Smrg if ((first + count) > ctx->Const.MaxViewports) { 208848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 209848b8605Smrg "glViewportArrayv: first (%d) + count (%d) > MaxViewports " 210848b8605Smrg "(%d)", 211848b8605Smrg first, count, ctx->Const.MaxViewports); 212848b8605Smrg return; 213848b8605Smrg } 214848b8605Smrg 215848b8605Smrg /* Verify width & height */ 216848b8605Smrg for (i = 0; i < count; i++) { 217848b8605Smrg if (p[i].Width < 0 || p[i].Height < 0) { 218848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 219848b8605Smrg "glViewportArrayv: index (%d) width or height < 0 " 220848b8605Smrg "(%f, %f)", 221848b8605Smrg i + first, p[i].Width, p[i].Height); 222848b8605Smrg return; 223848b8605Smrg } 224848b8605Smrg } 225848b8605Smrg 226b8e80941Smrg viewport_array(ctx, first, count, p); 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrgstatic void 230b8e80941Smrgviewport_indexed_err(struct gl_context *ctx, GLuint index, GLfloat x, GLfloat y, 231b8e80941Smrg GLfloat w, GLfloat h, const char *function) 232848b8605Smrg{ 233848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 234848b8605Smrg _mesa_debug(ctx, "%s(%d, %f, %f, %f, %f)\n", 235848b8605Smrg function, index, x, y, w, h); 236848b8605Smrg 237848b8605Smrg if (index >= ctx->Const.MaxViewports) { 238848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 239848b8605Smrg "%s: index (%d) >= MaxViewports (%d)", 240848b8605Smrg function, index, ctx->Const.MaxViewports); 241848b8605Smrg return; 242848b8605Smrg } 243848b8605Smrg 244848b8605Smrg /* Verify width & height */ 245848b8605Smrg if (w < 0 || h < 0) { 246848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 247848b8605Smrg "%s: index (%d) width or height < 0 (%f, %f)", 248848b8605Smrg function, index, w, h); 249848b8605Smrg return; 250848b8605Smrg } 251848b8605Smrg 252848b8605Smrg _mesa_set_viewport(ctx, index, x, y, w, h); 253848b8605Smrg} 254848b8605Smrg 255b8e80941Smrgvoid GLAPIENTRY 256b8e80941Smrg_mesa_ViewportIndexedf_no_error(GLuint index, GLfloat x, GLfloat y, 257b8e80941Smrg GLfloat w, GLfloat h) 258b8e80941Smrg{ 259b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 260b8e80941Smrg _mesa_set_viewport(ctx, index, x, y, w, h); 261b8e80941Smrg} 262b8e80941Smrg 263848b8605Smrgvoid GLAPIENTRY 264848b8605Smrg_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y, 265848b8605Smrg GLfloat w, GLfloat h) 266848b8605Smrg{ 267b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 268b8e80941Smrg viewport_indexed_err(ctx, index, x, y, w, h, "glViewportIndexedf"); 269b8e80941Smrg} 270b8e80941Smrg 271b8e80941Smrgvoid GLAPIENTRY 272b8e80941Smrg_mesa_ViewportIndexedfv_no_error(GLuint index, const GLfloat *v) 273b8e80941Smrg{ 274b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 275b8e80941Smrg _mesa_set_viewport(ctx, index, v[0], v[1], v[2], v[3]); 276848b8605Smrg} 277848b8605Smrg 278848b8605Smrgvoid GLAPIENTRY 279848b8605Smrg_mesa_ViewportIndexedfv(GLuint index, const GLfloat *v) 280848b8605Smrg{ 281b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 282b8e80941Smrg viewport_indexed_err(ctx, index, v[0], v[1], v[2], v[3], 283b8e80941Smrg "glViewportIndexedfv"); 284848b8605Smrg} 285848b8605Smrg 286848b8605Smrgstatic void 287848b8605Smrgset_depth_range_no_notify(struct gl_context *ctx, unsigned idx, 288848b8605Smrg GLclampd nearval, GLclampd farval) 289848b8605Smrg{ 290848b8605Smrg if (ctx->ViewportArray[idx].Near == nearval && 291848b8605Smrg ctx->ViewportArray[idx].Far == farval) 292848b8605Smrg return; 293848b8605Smrg 294b8e80941Smrg /* The depth range is needed by program state constants. */ 295b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_VIEWPORT); 296b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewViewport; 297b8e80941Smrg 298848b8605Smrg ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0); 299848b8605Smrg ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0); 300848b8605Smrg} 301848b8605Smrg 302848b8605Smrgvoid 303848b8605Smrg_mesa_set_depth_range(struct gl_context *ctx, unsigned idx, 304848b8605Smrg GLclampd nearval, GLclampd farval) 305848b8605Smrg{ 306848b8605Smrg set_depth_range_no_notify(ctx, idx, nearval, farval); 307848b8605Smrg 308848b8605Smrg if (ctx->Driver.DepthRange) 309848b8605Smrg ctx->Driver.DepthRange(ctx); 310848b8605Smrg} 311848b8605Smrg 312848b8605Smrg/** 313848b8605Smrg * Called by glDepthRange 314848b8605Smrg * 315848b8605Smrg * \param nearval specifies the Z buffer value which should correspond to 316848b8605Smrg * the near clip plane 317848b8605Smrg * \param farval specifies the Z buffer value which should correspond to 318848b8605Smrg * the far clip plane 319848b8605Smrg */ 320848b8605Smrgvoid GLAPIENTRY 321848b8605Smrg_mesa_DepthRange(GLclampd nearval, GLclampd farval) 322848b8605Smrg{ 323848b8605Smrg unsigned i; 324848b8605Smrg GET_CURRENT_CONTEXT(ctx); 325848b8605Smrg 326848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 327848b8605Smrg _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval); 328848b8605Smrg 329848b8605Smrg /* The GL_ARB_viewport_array spec says: 330848b8605Smrg * 331848b8605Smrg * "DepthRange sets the depth range for all viewports to the same 332848b8605Smrg * values and is equivalent (assuming no errors are generated) to: 333848b8605Smrg * 334848b8605Smrg * for (uint i = 0; i < MAX_VIEWPORTS; i++) 335848b8605Smrg * DepthRangeIndexed(i, n, f);" 336848b8605Smrg * 337848b8605Smrg * Set the depth range for all of the viewports supported by the 338848b8605Smrg * implementation, but only signal the driver once at the end. 339848b8605Smrg */ 340848b8605Smrg for (i = 0; i < ctx->Const.MaxViewports; i++) 341848b8605Smrg set_depth_range_no_notify(ctx, i, nearval, farval); 342848b8605Smrg 343848b8605Smrg if (ctx->Driver.DepthRange) { 344848b8605Smrg ctx->Driver.DepthRange(ctx); 345848b8605Smrg } 346848b8605Smrg} 347848b8605Smrg 348848b8605Smrgvoid GLAPIENTRY 349848b8605Smrg_mesa_DepthRangef(GLclampf nearval, GLclampf farval) 350848b8605Smrg{ 351848b8605Smrg _mesa_DepthRange(nearval, farval); 352848b8605Smrg} 353848b8605Smrg 354848b8605Smrg/** 355848b8605Smrg * Update a range DepthRange values 356848b8605Smrg * 357848b8605Smrg * \param first starting array index 358848b8605Smrg * \param count count of DepthRange items to update 359848b8605Smrg * \param v pointer to memory containing 360848b8605Smrg * GLclampd near and far clip-plane values 361848b8605Smrg */ 362b8e80941Smrgstatic ALWAYS_INLINE void 363b8e80941Smrgdepth_range_arrayv(struct gl_context *ctx, GLuint first, GLsizei count, 364b8e80941Smrg const struct gl_depthrange_inputs *const inputs) 365b8e80941Smrg{ 366b8e80941Smrg for (GLsizei i = 0; i < count; i++) 367b8e80941Smrg set_depth_range_no_notify(ctx, i + first, inputs[i].Near, inputs[i].Far); 368b8e80941Smrg 369b8e80941Smrg if (ctx->Driver.DepthRange) 370b8e80941Smrg ctx->Driver.DepthRange(ctx); 371b8e80941Smrg} 372b8e80941Smrg 373b8e80941Smrgvoid GLAPIENTRY 374b8e80941Smrg_mesa_DepthRangeArrayv_no_error(GLuint first, GLsizei count, const GLclampd *v) 375b8e80941Smrg{ 376b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 377b8e80941Smrg 378b8e80941Smrg const struct gl_depthrange_inputs *const p = 379b8e80941Smrg (struct gl_depthrange_inputs *)v; 380b8e80941Smrg depth_range_arrayv(ctx, first, count, p); 381b8e80941Smrg} 382b8e80941Smrg 383848b8605Smrgvoid GLAPIENTRY 384848b8605Smrg_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd *v) 385848b8605Smrg{ 386848b8605Smrg const struct gl_depthrange_inputs *const p = 387848b8605Smrg (struct gl_depthrange_inputs *) v; 388848b8605Smrg GET_CURRENT_CONTEXT(ctx); 389848b8605Smrg 390848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 391848b8605Smrg _mesa_debug(ctx, "glDepthRangeArrayv %d %d\n", first, count); 392848b8605Smrg 393848b8605Smrg if ((first + count) > ctx->Const.MaxViewports) { 394848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 395848b8605Smrg "glDepthRangev: first (%d) + count (%d) >= MaxViewports (%d)", 396848b8605Smrg first, count, ctx->Const.MaxViewports); 397848b8605Smrg return; 398848b8605Smrg } 399848b8605Smrg 400b8e80941Smrg depth_range_arrayv(ctx, first, count, p); 401b8e80941Smrg} 402b8e80941Smrg 403b8e80941Smrgvoid GLAPIENTRY 404b8e80941Smrg_mesa_DepthRangeArrayfvOES(GLuint first, GLsizei count, const GLfloat *v) 405b8e80941Smrg{ 406b8e80941Smrg int i; 407b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 408b8e80941Smrg 409b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 410b8e80941Smrg _mesa_debug(ctx, "glDepthRangeArrayfv %d %d\n", first, count); 411b8e80941Smrg 412b8e80941Smrg if ((first + count) > ctx->Const.MaxViewports) { 413b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 414b8e80941Smrg "glDepthRangeArrayfv: first (%d) + count (%d) >= MaxViewports (%d)", 415b8e80941Smrg first, count, ctx->Const.MaxViewports); 416b8e80941Smrg return; 417b8e80941Smrg } 418b8e80941Smrg 419848b8605Smrg for (i = 0; i < count; i++) 420b8e80941Smrg set_depth_range_no_notify(ctx, i + first, v[i * 2], v[i * 2 + 1]); 421848b8605Smrg 422848b8605Smrg if (ctx->Driver.DepthRange) 423848b8605Smrg ctx->Driver.DepthRange(ctx); 424848b8605Smrg} 425848b8605Smrg 426848b8605Smrg/** 427848b8605Smrg * Update a single DepthRange 428848b8605Smrg * 429848b8605Smrg * \param index array index to update 430848b8605Smrg * \param nearval specifies the Z buffer value which should correspond to 431848b8605Smrg * the near clip plane 432848b8605Smrg * \param farval specifies the Z buffer value which should correspond to 433848b8605Smrg * the far clip plane 434848b8605Smrg */ 435b8e80941Smrgvoid GLAPIENTRY 436b8e80941Smrg_mesa_DepthRangeIndexed_no_error(GLuint index, GLclampd nearval, 437b8e80941Smrg GLclampd farval) 438b8e80941Smrg{ 439b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 440b8e80941Smrg _mesa_set_depth_range(ctx, index, nearval, farval); 441b8e80941Smrg} 442b8e80941Smrg 443b8e80941Smrg 444848b8605Smrgvoid GLAPIENTRY 445848b8605Smrg_mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval) 446848b8605Smrg{ 447848b8605Smrg GET_CURRENT_CONTEXT(ctx); 448848b8605Smrg 449848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 450848b8605Smrg _mesa_debug(ctx, "glDepthRangeIndexed(%d, %f, %f)\n", 451848b8605Smrg index, nearval, farval); 452848b8605Smrg 453848b8605Smrg if (index >= ctx->Const.MaxViewports) { 454848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 455848b8605Smrg "glDepthRangeIndexed: index (%d) >= MaxViewports (%d)", 456848b8605Smrg index, ctx->Const.MaxViewports); 457848b8605Smrg return; 458848b8605Smrg } 459848b8605Smrg 460848b8605Smrg _mesa_set_depth_range(ctx, index, nearval, farval); 461848b8605Smrg} 462848b8605Smrg 463b8e80941Smrgvoid GLAPIENTRY 464b8e80941Smrg_mesa_DepthRangeIndexedfOES(GLuint index, GLfloat nearval, GLfloat farval) 465b8e80941Smrg{ 466b8e80941Smrg _mesa_DepthRangeIndexed(index, nearval, farval); 467b8e80941Smrg} 468b8e80941Smrg 469848b8605Smrg/** 470848b8605Smrg * Initialize the context viewport attribute group. 471848b8605Smrg * \param ctx the GL context. 472848b8605Smrg */ 473848b8605Smrgvoid _mesa_init_viewport(struct gl_context *ctx) 474848b8605Smrg{ 475848b8605Smrg unsigned i; 476848b8605Smrg 477b8e80941Smrg ctx->Transform.ClipOrigin = GL_LOWER_LEFT; 478b8e80941Smrg ctx->Transform.ClipDepthMode = GL_NEGATIVE_ONE_TO_ONE; 479b8e80941Smrg 480848b8605Smrg /* Note: ctx->Const.MaxViewports may not have been set by the driver yet, 481848b8605Smrg * so just initialize all of them. 482848b8605Smrg */ 483848b8605Smrg for (i = 0; i < MAX_VIEWPORTS; i++) { 484848b8605Smrg /* Viewport group */ 485848b8605Smrg ctx->ViewportArray[i].X = 0; 486848b8605Smrg ctx->ViewportArray[i].Y = 0; 487848b8605Smrg ctx->ViewportArray[i].Width = 0; 488848b8605Smrg ctx->ViewportArray[i].Height = 0; 489848b8605Smrg ctx->ViewportArray[i].Near = 0.0; 490848b8605Smrg ctx->ViewportArray[i].Far = 1.0; 491b8e80941Smrg } 492b8e80941Smrg 493b8e80941Smrg ctx->SubpixelPrecisionBias[0] = 0; 494b8e80941Smrg ctx->SubpixelPrecisionBias[1] = 0; 495b8e80941Smrg} 496b8e80941Smrg 497b8e80941Smrg 498b8e80941Smrgstatic ALWAYS_INLINE void 499b8e80941Smrgclip_control(struct gl_context *ctx, GLenum origin, GLenum depth, bool no_error) 500b8e80941Smrg{ 501b8e80941Smrg if (ctx->Transform.ClipOrigin == origin && 502b8e80941Smrg ctx->Transform.ClipDepthMode == depth) 503b8e80941Smrg return; 504b8e80941Smrg 505b8e80941Smrg if (!no_error && 506b8e80941Smrg origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) { 507b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl"); 508b8e80941Smrg return; 509b8e80941Smrg } 510b8e80941Smrg 511b8e80941Smrg if (!no_error && 512b8e80941Smrg depth != GL_NEGATIVE_ONE_TO_ONE && depth != GL_ZERO_TO_ONE) { 513b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl"); 514b8e80941Smrg return; 515b8e80941Smrg } 516b8e80941Smrg 517b8e80941Smrg /* Affects transform state and the viewport transform */ 518b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewClipControl ? 0 : 519b8e80941Smrg _NEW_TRANSFORM | _NEW_VIEWPORT); 520b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewClipControl; 521b8e80941Smrg 522b8e80941Smrg if (ctx->Transform.ClipOrigin != origin) { 523b8e80941Smrg ctx->Transform.ClipOrigin = origin; 524848b8605Smrg 525b8e80941Smrg /* Affects the winding order of the front face. */ 526b8e80941Smrg if (ctx->DriverFlags.NewPolygonState) 527b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 528b8e80941Smrg else 529b8e80941Smrg ctx->NewState |= _NEW_POLYGON; 530b8e80941Smrg 531b8e80941Smrg if (ctx->Driver.FrontFace) 532b8e80941Smrg ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); 533b8e80941Smrg } 534b8e80941Smrg 535b8e80941Smrg if (ctx->Transform.ClipDepthMode != depth) { 536b8e80941Smrg ctx->Transform.ClipDepthMode = depth; 537b8e80941Smrg 538b8e80941Smrg if (ctx->Driver.DepthRange) 539b8e80941Smrg ctx->Driver.DepthRange(ctx); 540848b8605Smrg } 541848b8605Smrg} 542848b8605Smrg 543848b8605Smrg 544b8e80941Smrgvoid GLAPIENTRY 545b8e80941Smrg_mesa_ClipControl_no_error(GLenum origin, GLenum depth) 546b8e80941Smrg{ 547b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 548b8e80941Smrg clip_control(ctx, origin, depth, true); 549b8e80941Smrg} 550b8e80941Smrg 551b8e80941Smrg 552b8e80941Smrgvoid GLAPIENTRY 553b8e80941Smrg_mesa_ClipControl(GLenum origin, GLenum depth) 554b8e80941Smrg{ 555b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 556b8e80941Smrg 557b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 558b8e80941Smrg _mesa_debug(ctx, "glClipControl(%s, %s)\n", 559b8e80941Smrg _mesa_enum_to_string(origin), 560b8e80941Smrg _mesa_enum_to_string(depth)); 561b8e80941Smrg 562b8e80941Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 563b8e80941Smrg 564b8e80941Smrg if (!ctx->Extensions.ARB_clip_control) { 565b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glClipControl"); 566b8e80941Smrg return; 567b8e80941Smrg } 568b8e80941Smrg 569b8e80941Smrg clip_control(ctx, origin, depth, false); 570b8e80941Smrg} 571b8e80941Smrg 572b8e80941Smrg/** 573b8e80941Smrg * Computes the scaling and the translation part of the 574b8e80941Smrg * viewport transform matrix of the \param i-th viewport 575b8e80941Smrg * and writes that into \param scale and \param translate. 576848b8605Smrg */ 577b8e80941Smrgvoid 578b8e80941Smrg_mesa_get_viewport_xform(struct gl_context *ctx, unsigned i, 579b8e80941Smrg float scale[3], float translate[3]) 580848b8605Smrg{ 581b8e80941Smrg float x = ctx->ViewportArray[i].X; 582b8e80941Smrg float y = ctx->ViewportArray[i].Y; 583b8e80941Smrg float half_width = 0.5f * ctx->ViewportArray[i].Width; 584b8e80941Smrg float half_height = 0.5f * ctx->ViewportArray[i].Height; 585b8e80941Smrg double n = ctx->ViewportArray[i].Near; 586b8e80941Smrg double f = ctx->ViewportArray[i].Far; 587b8e80941Smrg 588b8e80941Smrg scale[0] = half_width; 589b8e80941Smrg translate[0] = half_width + x; 590b8e80941Smrg if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT) { 591b8e80941Smrg scale[1] = -half_height; 592b8e80941Smrg } else { 593b8e80941Smrg scale[1] = half_height; 594b8e80941Smrg } 595b8e80941Smrg translate[1] = half_height + y; 596b8e80941Smrg 597b8e80941Smrg if (ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE) { 598b8e80941Smrg scale[2] = 0.5 * (f - n); 599b8e80941Smrg translate[2] = 0.5 * (n + f); 600b8e80941Smrg } else { 601b8e80941Smrg scale[2] = f - n; 602b8e80941Smrg translate[2] = n; 603b8e80941Smrg } 604b8e80941Smrg} 605b8e80941Smrg 606b8e80941Smrg 607b8e80941Smrgstatic void 608b8e80941Smrgsubpixel_precision_bias(struct gl_context *ctx, GLuint xbits, GLuint ybits) 609b8e80941Smrg{ 610b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 611b8e80941Smrg _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); 612b8e80941Smrg 613b8e80941Smrg ctx->SubpixelPrecisionBias[0] = xbits; 614b8e80941Smrg ctx->SubpixelPrecisionBias[1] = ybits; 615848b8605Smrg 616b8e80941Smrg FLUSH_VERTICES(ctx, 0); 617b8e80941Smrg ctx->NewDriverState |= 618b8e80941Smrg ctx->DriverFlags.NewNvConservativeRasterizationParams; 619848b8605Smrg} 620848b8605Smrg 621b8e80941Smrgvoid GLAPIENTRY 622b8e80941Smrg_mesa_SubpixelPrecisionBiasNV_no_error(GLuint xbits, GLuint ybits) 623b8e80941Smrg{ 624b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 625b8e80941Smrg 626b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 627b8e80941Smrg _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); 628b8e80941Smrg 629b8e80941Smrg subpixel_precision_bias(ctx, xbits, ybits); 630b8e80941Smrg} 631b8e80941Smrg 632b8e80941Smrgvoid GLAPIENTRY 633b8e80941Smrg_mesa_SubpixelPrecisionBiasNV(GLuint xbits, GLuint ybits) 634b8e80941Smrg{ 635b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 636b8e80941Smrg 637b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 638b8e80941Smrg _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); 639b8e80941Smrg 640b8e80941Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 641b8e80941Smrg 642b8e80941Smrg if (!ctx->Extensions.NV_conservative_raster) { 643b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 644b8e80941Smrg "glSubpixelPrecisionBiasNV not supported"); 645b8e80941Smrg return; 646b8e80941Smrg } 647b8e80941Smrg 648b8e80941Smrg if (xbits > ctx->Const.MaxSubpixelPrecisionBiasBits) { 649b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV"); 650b8e80941Smrg return; 651b8e80941Smrg } 652b8e80941Smrg 653b8e80941Smrg if (ybits > ctx->Const.MaxSubpixelPrecisionBiasBits) { 654b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV"); 655b8e80941Smrg return; 656b8e80941Smrg } 657b8e80941Smrg 658b8e80941Smrg subpixel_precision_bias(ctx, xbits, ybits); 659b8e80941Smrg} 660