[Mesa-dev] [PATCH 13/18] mesa: Add ARB_viewport_array viewport entry points

Courtney Goeltzenleuchter courtney at lunarg.com
Wed Nov 20 14:59:29 PST 2013


Signed-off-by: Courtney Goeltzenleuchter <courtney at 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



More information about the mesa-dev mailing list