[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