Signed-off-by: Courtney Goeltzenleuchter <court...@lunarg.com> --- src/mesa/main/context.c | 2 +- src/mesa/main/scissor.c | 2 +- src/mesa/main/viewport.c | 316 +++++++++++++++++++++++++++++++++++++++-------- src/mesa/main/viewport.h | 22 +++- 4 files changed, 287 insertions(+), 55 deletions(-)
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 2baf4ef..6020883 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1436,12 +1436,12 @@ _mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height) * potential infinite recursion. */ ctx->ViewportInitialized = GL_TRUE; - _mesa_set_viewport(ctx, 0, 0, width, height); /* ARB_viewport_array specifies that glScissor is equivalent to * calling glViewportArray with an array containing a single * viewport once for each supported viewport. */ for (i = 0; i < ctx->Const.MaxViewports; i++) { + _mesa_set_viewporti(ctx, i, 0, 0, width, height); _mesa_set_scissori(ctx, i, 0, 0, width, height); } } diff --git a/src/mesa/main/scissor.c b/src/mesa/main/scissor.c index 580558e..20731f7 100644 --- a/src/mesa/main/scissor.c +++ b/src/mesa/main/scissor.c @@ -109,7 +109,7 @@ _mesa_ScissorArrayv(GLuint first, GLsizei count, const GLint * v) struct gl_scissor_rect *p = (struct gl_scissor_rect *) v; GET_CURRENT_CONTEXT(ctx); - if ((first + count) >= ctx->Const.MaxViewports) { + if ((first + count) > ctx->Const.MaxViewports) { _mesa_error(ctx, GL_INVALID_VALUE, "glScissorArrayv: first (%d) + count (%d) >= MaxViewports (%d)", first, count, ctx->Const.MaxViewports); diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c index 08efd05..e191923 100644 --- a/src/mesa/main/viewport.c +++ b/src/mesa/main/viewport.c @@ -34,6 +34,16 @@ #include "mtypes.h" #include "viewport.h" +struct gl_viewport_inputs +{ + GLfloat X, Y; /**< position */ + GLfloat Width, Height; /**< size */ +}; + +struct gl_depthrange_inputs +{ + GLdouble Near, Far; /**< Depth buffer range */ +}; /** * Set the viewport. @@ -45,42 +55,151 @@ void GLAPIENTRY _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) { + GLuint i; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); - _mesa_set_viewport(ctx, x, y, width, height); -} + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height); + + if (width < 0 || height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewport(%d, %d, %d, %d)", x, y, width, height); + return; + } + + /* ARB_viewport_array specifies that glScissor is equivalent to + * calling glViewportArray with an array containing a single + * viewport once for each supported viewport. + */ + for (i = 0; i < ctx->Const.MaxViewports; i++) { + _mesa_set_viewporti(ctx, i, x, y, width, height); + } +} /** * Set new viewport parameters and update derived state (the _WindowMap * matrix). Usually called from _mesa_Viewport(). - * + * * \param ctx GL context. * \param x, y coordinates of the lower left corner of the viewport rectangle. * \param width width of the viewport rectangle. * \param height height of the viewport rectangle. */ void -_mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, - GLsizei width, GLsizei height) +_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v) { + GLuint i; + struct gl_viewport_inputs *p = (struct gl_viewport_inputs *) v; + GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height); + _mesa_debug(ctx, "glViewportArrayv %d %d\n", first, count); - if (width < 0 || height < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glViewport(%d, %d, %d, %d)", x, y, width, height); + if ((first + count) > ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportArrayv: first (%d) + count (%d) > MaxViewports (%d)", + first, count, ctx->Const.MaxViewports); + return; + } + + /* Verify width & height */ + for (i = 0; i < count; i++) { + if (p[i].Width < 0 || p[i].Height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportArrayv: index (%d) width or height < 0 (%f, %f)", + i + first, p[i].Width, p[i].Height); + } + } + + for (i = 0; i < count; i++) + _mesa_set_viewporti(ctx, i + first, p[i].X, p[i].Y, p[i].Width, p[i].Height); +} + +void GLAPIENTRY +_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y, + GLfloat w, GLfloat h) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewportIndexedf(%d, %f, %f, %f, %f)\n", + index, x, y, w, h); + + if (index >= ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportIndexedf: index (%d) >= MaxViewports (%d)", + index, ctx->Const.MaxViewports); + return; + } + + /* Verify width & height */ + if (w < 0 || h < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportArrayv: index (%d) width or height < 0 (%f, %f)", + index, w, h); + } + + _mesa_set_viewporti(ctx, index, x, y, w, h); +} + +void GLAPIENTRY +_mesa_ViewportIndexedfv(GLuint index, const GLfloat * v) +{ + struct gl_viewport_inputs *p = (struct gl_viewport_inputs *) v; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewportIndexedv(%d, %f, %f, %f, %f)\n", + index, p->X, p->Y, p->Width, p->Height); + + if (index >= ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportIndexedf: index (%d) >= MaxViewports (%d)", + index, ctx->Const.MaxViewports); return; } + /* Verify width & height */ + if (p->Width < 0 || p->Height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportArrayv: index (%d) width or height < 0 (%f, %f)", + index, p->Width, p->Height); + } + + _mesa_set_viewporti(ctx, index, p->X, p->Y, p->Width, p->Height); +} + +/** + * Set new viewport parameters and update derived state (the _WindowMap + * matrix). Usually called from _mesa_Viewport(). + * + * \param ctx GL context. + * \param index index of viewport to update + * \param x, y coordinates of the lower left corner of the viewport rectangle. + * \param width width of the viewport rectangle. + * \param height height of the viewport rectangle. + */ +void +_mesa_set_viewporti(struct gl_context *ctx, GLuint index, + GLint x, GLint y, + GLsizei width, GLsizei height) +{ /* clamp width and height to the implementation dependent range */ - width = MIN2(width, (GLsizei) ctx->Const.MaxViewportWidth); + width = MIN2(width, (GLsizei) ctx->Const.MaxViewportWidth); height = MIN2(height, (GLsizei) ctx->Const.MaxViewportHeight); + + /* The location of the viewport's bottom-left corner, given by (x,y), are + * clamped to be within the implementation-dependent viewport bounds range. + */ + x = CLAMP(x, (GLint)ctx->Const.ViewportBounds.Min, (GLint)ctx->Const.ViewportBounds.Max); + y = CLAMP(y, (GLint)ctx->Const.ViewportBounds.Min, (GLint)ctx->Const.ViewportBounds.Max); + + ctx->ViewportArray[index].X = (GLfloat) x; + ctx->ViewportArray[index].Width = (GLfloat) width; + ctx->ViewportArray[index].Y = (GLfloat) y; + ctx->ViewportArray[index].Height = (GLfloat) height; - ctx->ViewportArray[0].X = x; - ctx->ViewportArray[0].Width = width; - ctx->ViewportArray[0].Y = y; - ctx->ViewportArray[0].Height = height; ctx->NewState |= _NEW_VIEWPORT; #if 1 @@ -88,10 +207,10 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, * the WindowMap matrix being up to date in the driver's Viewport * and DepthRange functions. */ - _math_matrix_viewport(&ctx->ViewportArray[0]._WindowMap, - ctx->ViewportArray[0].X, ctx->ViewportArray[0].Y, - ctx->ViewportArray[0].Width, ctx->ViewportArray[0].Height, - ctx->ViewportArray[0].Near, ctx->ViewportArray[0].Far, + _math_matrix_viewport(&ctx->ViewportArray[index]._WindowMap, + ctx->ViewportArray[index].X, ctx->ViewportArray[index].Y, + ctx->ViewportArray[index].Width, ctx->ViewportArray[index].Height, + ctx->ViewportArray[index].Near, ctx->ViewportArray[index].Far, ctx->DrawBuffer->_DepthMaxF); #endif @@ -99,10 +218,49 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, /* Many drivers will use this call to check for window size changes * and reallocate the z/stencil/accum/etc buffers if needed. */ - ctx->Driver.Viewport(ctx, 0, x, y, width, height); + ctx->Driver.Viewport(ctx, index, + ctx->ViewportArray[index].X, ctx->ViewportArray[index].Y, + ctx->ViewportArray[index].Width, ctx->ViewportArray[index].Height); } } +/** + * Part of ARB_viewport_array extension + * Update a single DepthRange + * + * \param index array index to update + * \param nearval specifies the Z buffer value which should correspond to + * the near clip plane + * \param farval specifies the Z buffer value which should correspond to + * the far clip plane + */ +void +_mesa_set_depthrangei(struct gl_context *ctx, GLuint index, + GLclampd nearval, GLclampd farval) +{ + FLUSH_VERTICES(ctx, 0); + + ctx->ViewportArray[index].Near = (GLdouble) CLAMP(nearval, 0.0, 1.0); + ctx->ViewportArray[index].Far = (GLdouble) CLAMP(farval, 0.0, 1.0); + + ctx->NewState |= _NEW_VIEWPORT; + +#if 1 + /* XXX remove this someday. Currently the DRI drivers rely on + * the WindowMap matrix being up to date in the driver's Viewport + * and DepthRange functions. + */ + _math_matrix_viewport(&ctx->ViewportArray[index]._WindowMap, + ctx->ViewportArray[index].X, ctx->ViewportArray[index].Y, + ctx->ViewportArray[index].Width, ctx->ViewportArray[index].Height, + ctx->ViewportArray[index].Near, ctx->ViewportArray[index].Far, + ctx->DrawBuffer->_DepthMaxF); +#endif + + if (ctx->Driver.DepthRange) { + ctx->Driver.DepthRange(ctx, index, nearval, farval); + } +} /** * Called by glDepthRange @@ -115,35 +273,22 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, void GLAPIENTRY _mesa_DepthRange(GLclampd nearval, GLclampd farval) { + GLint i; GET_CURRENT_CONTEXT(ctx); - FLUSH_VERTICES(ctx, 0); - - if (MESA_VERBOSE&VERBOSE_API) + if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval); if (ctx->ViewportArray[0].Near == nearval && ctx->ViewportArray[0].Far == farval) return; - ctx->ViewportArray[0].Near = (GLfloat) CLAMP(nearval, 0.0, 1.0); - ctx->ViewportArray[0].Far = (GLfloat) CLAMP(farval, 0.0, 1.0); - ctx->NewState |= _NEW_VIEWPORT; - -#if 1 - /* XXX remove this someday. Currently the DRI drivers rely on - * the WindowMap matrix being up to date in the driver's Viewport - * and DepthRange functions. + /* glDepthRange is equivalent to calling glViewportArray with an + * array containing a single viewport once for each supported + * viewport. It therefore defines all viewports in a single call. */ - _math_matrix_viewport(&ctx->ViewportArray[0]._WindowMap, - ctx->ViewportArray[0].X, ctx->ViewportArray[0].Y, - ctx->ViewportArray[0].Width, ctx->ViewportArray[0].Height, - ctx->ViewportArray[0].Near, ctx->ViewportArray[0].Far, - ctx->DrawBuffer->_DepthMaxF); -#endif - - if (ctx->Driver.DepthRange) { - ctx->Driver.DepthRange(ctx, 0, nearval, farval); + for (i = 0; i < ctx->Const.MaxViewports; i++) { + _mesa_set_depthrangei(ctx, i, nearval, farval); } } @@ -153,27 +298,91 @@ _mesa_DepthRangef(GLclampf nearval, GLclampf farval) _mesa_DepthRange(nearval, farval); } +/** + * Part of ARB_viewport_array extension + * Update a range DepthRange values + * + * \param first starting array index + * \param count count of DepthRange items to update + * \param v pointer to memory containing + * GLclampd near and far clip-plane values + */ +void GLAPIENTRY +_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd * v) +{ + GLuint i; + struct gl_depthrange_inputs *p = (struct gl_depthrange_inputs *) v; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDepthRangeArrayv %d %d\n", first, count); + + if ((first + count) > ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDepthRangev: first (%d) + count (%d) >= MaxViewports (%d)", + first, count, ctx->Const.MaxViewports); + return; + } + + for (i = 0; i < count; i++) { + _mesa_set_depthrangei(ctx, i + first, + (GLdouble) CLAMP(p[i].Near, 0.0, 1.0), + (GLdouble) CLAMP(p[i].Far, 0.0, 1.0)); + } +} + +/** + * Part of ARB_viewport_array extension + * Update a single DepthRange + * + * \param index array index to update + * \param nearval specifies the Z buffer value which should correspond to + * the near clip plane + * \param farval specifies the Z buffer value which should correspond to + * the far clip plane + */ +void GLAPIENTRY +_mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDepthRangeIndexed(%d, %f, %f)\n", index, nearval, farval); + + if (index >= ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDepthRangeIndexed: index (%d) >= MaxViewports (%d)", + index, ctx->Const.MaxViewports); + return; + } + + _mesa_set_depthrangei(ctx, index, nearval, farval); +} + /** * Initialize the context viewport attribute group. * \param ctx the GL context. */ void _mesa_init_viewport(struct gl_context *ctx) { + GLint i; GLfloat depthMax = 65535.0F; /* sorf of arbitrary */ /* Viewport group */ - ctx->ViewportArray[0].X = 0; - ctx->ViewportArray[0].Y = 0; - ctx->ViewportArray[0].Width = 0; - ctx->ViewportArray[0].Height = 0; - ctx->ViewportArray[0].Near = 0.0; - ctx->ViewportArray[0].Far = 1.0; - _math_matrix_ctr(&ctx->ViewportArray[0]._WindowMap); - - _math_matrix_viewport(&ctx->ViewportArray[0]._WindowMap, 0, 0, 0, 0, - 0.0F, 1.0F, depthMax); -} + for (i = 0; i < MAX_VIEWPORTS; i++) { + ctx->ViewportArray[i].X = 0.0F; + ctx->ViewportArray[i].Width = 0.0F; + ctx->ViewportArray[i].Y = 0.0F; + ctx->ViewportArray[i].Height = 0.0F; + ctx->ViewportArray[i].Near = 0.0F; + ctx->ViewportArray[i].Far = 1.0F; + _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap); + + _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, 0, 0, 0, 0, + 0.0F, 1.0F, depthMax); + } +} /** * Free the context viewport attribute group data. @@ -181,6 +390,11 @@ void _mesa_init_viewport(struct gl_context *ctx) */ void _mesa_free_viewport_data(struct gl_context *ctx) { - _math_matrix_dtr(&ctx->ViewportArray[0]._WindowMap); + GLint i; + + for (i = 0; i < ctx->Const.MaxViewports; i++) { + _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap); + } + } diff --git a/src/mesa/main/viewport.h b/src/mesa/main/viewport.h index ffa3a72..8f99e69 100644 --- a/src/mesa/main/viewport.h +++ b/src/mesa/main/viewport.h @@ -34,11 +34,24 @@ struct gl_context; extern void GLAPIENTRY _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height); +extern void GLAPIENTRY +_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat * v); + +extern void GLAPIENTRY +_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); + +extern void GLAPIENTRY +_mesa_ViewportIndexedfv(GLuint index, const GLfloat * v); + extern void -_mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, - GLsizei width, GLsizei height); +_mesa_set_viewporti(struct gl_context *ctx, GLuint index, + GLint x, GLint y, + GLsizei width, GLsizei height); +extern void +_mesa_set_depthrangei(struct gl_context *ctx, GLuint index, + GLclampd nearval, GLclampd farval); extern void GLAPIENTRY _mesa_DepthRange(GLclampd nearval, GLclampd farval); @@ -46,6 +59,11 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval); extern void GLAPIENTRY _mesa_DepthRangef(GLclampf nearval, GLclampf farval); +extern void GLAPIENTRY +_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd * v); + +extern void GLAPIENTRY +_mesa_DepthRangeIndexed(GLuint index, GLclampd n, GLclampd f); extern void _mesa_init_viewport(struct gl_context *ctx); -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev