mesa: add support for memory object creation/import/delete
[mesa.git] / src / mesa / main / viewport.c
index bd580446f7620d174530493e211721c739f2d616..fc384909e6363f24f59f3a772e57668f53bda4bc 100644 (file)
 #include "viewport.h"
 
 static void
-set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
-                       GLfloat x, GLfloat y,
-                       GLfloat width, GLfloat height)
+clamp_viewport(struct gl_context *ctx, GLfloat *x, GLfloat *y,
+               GLfloat *width, GLfloat *height)
 {
    /* clamp width and height to the implementation dependent range */
-   width  = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth);
-   height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight);
+   *width  = MIN2(*width, (GLfloat) ctx->Const.MaxViewportWidth);
+   *height = MIN2(*height, (GLfloat) ctx->Const.MaxViewportHeight);
 
    /* The GL_ARB_viewport_array spec says:
     *
@@ -55,23 +54,31 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
    if (ctx->Extensions.ARB_viewport_array ||
        (ctx->Extensions.OES_viewport_array &&
         _mesa_is_gles31(ctx))) {
-      x = CLAMP(x,
-                ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
-      y = CLAMP(y,
-                ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
+      *x = CLAMP(*x,
+                 ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
+      *y = CLAMP(*y,
+                 ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
    }
+}
 
+static void
+set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
+                       GLfloat x, GLfloat y,
+                       GLfloat width, GLfloat height)
+{
    if (ctx->ViewportArray[idx].X == x &&
        ctx->ViewportArray[idx].Width == width &&
        ctx->ViewportArray[idx].Y == y &&
        ctx->ViewportArray[idx].Height == height)
       return;
 
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewViewport ? 0 : _NEW_VIEWPORT);
+   ctx->NewDriverState |= ctx->DriverFlags.NewViewport;
+
    ctx->ViewportArray[idx].X = x;
    ctx->ViewportArray[idx].Width = width;
    ctx->ViewportArray[idx].Y = y;
    ctx->ViewportArray[idx].Height = height;
-   ctx->NewState |= _NEW_VIEWPORT;
 }
 
 struct gl_viewport_inputs {
@@ -83,6 +90,33 @@ struct gl_depthrange_inputs {
    GLdouble Near, Far;          /**< Depth buffer range */
 };
 
+static void
+viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width,
+         GLsizei height)
+{
+   struct gl_viewport_inputs input = { x, y, width, height };
+
+   /* Clamp the viewport to the implementation dependent values. */
+   clamp_viewport(ctx, &input.X, &input.Y, &input.Width, &input.Height);
+
+   /* The GL_ARB_viewport_array spec says:
+    *
+    *     "Viewport sets the parameters for all viewports to the same values
+    *     and is equivalent (assuming no errors are generated) to:
+    *
+    *     for (uint i = 0; i < MAX_VIEWPORTS; i++)
+    *         ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h);"
+    *
+    * Set all of the viewports supported by the implementation, but only
+    * signal the driver once at the end.
+    */
+   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++)
+      set_viewport_no_notify(ctx, i, input.X, input.Y, input.Width, input.Height);
+
+   if (ctx->Driver.Viewport)
+      ctx->Driver.Viewport(ctx);
+}
+
 /**
  * Set the viewport.
  * \sa Called via glViewport() or display list execution.
@@ -90,12 +124,17 @@ struct gl_depthrange_inputs {
  * Flushes the vertices and calls _mesa_set_viewport() with the given
  * parameters.
  */
+void GLAPIENTRY
+_mesa_Viewport_no_error(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   viewport(ctx, x, y, width, height);
+}
+
 void GLAPIENTRY
 _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
 {
-   unsigned i;
    GET_CURRENT_CONTEXT(ctx);
-   FLUSH_VERTICES(ctx, 0);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
@@ -106,26 +145,7 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
       return;
    }
 
-   /* The GL_ARB_viewport_array spec says:
-    *
-    *     "Viewport sets the parameters for all viewports to the same values
-    *     and is equivalent (assuming no errors are generated) to:
-    *
-    *     for (uint i = 0; i < MAX_VIEWPORTS; i++)
-    *         ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h);"
-    *
-    * Set all of the viewports supported by the implementation, but only
-    * signal the driver once at the end.
-    */
-   for (i = 0; i < ctx->Const.MaxViewports; i++)
-      set_viewport_no_notify(ctx, i, x, y, width, height);
-
-   if (ctx->Driver.Viewport) {
-      /* 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);
-   }
+   viewport(ctx, x, y, width, height);
 }
 
 
@@ -143,21 +163,43 @@ void
 _mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y,
                     GLfloat width, GLfloat height)
 {
+   clamp_viewport(ctx, &x, &y, &width, &height);
    set_viewport_no_notify(ctx, idx, x, y, width, height);
 
-   if (ctx->Driver.Viewport) {
-      /* Many drivers will use this call to check for window size changes
-       * and reallocate the z/stencil/accum/etc buffers if needed.
-       */
+   if (ctx->Driver.Viewport)
       ctx->Driver.Viewport(ctx);
+}
+
+static void
+viewport_array(struct gl_context *ctx, GLuint first, GLsizei count,
+               struct gl_viewport_inputs *inputs)
+{
+   for (GLsizei i = 0; i < count; i++) {
+      clamp_viewport(ctx, &inputs[i].X, &inputs[i].Y,
+                     &inputs[i].Width, &inputs[i].Height);
+
+      set_viewport_no_notify(ctx, i + first, inputs[i].X, inputs[i].Y,
+                             inputs[i].Width, inputs[i].Height);
    }
+
+   if (ctx->Driver.Viewport)
+      ctx->Driver.Viewport(ctx);
+}
+
+void GLAPIENTRY
+_mesa_ViewportArrayv_no_error(GLuint first, GLsizei count, const GLfloat *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v;
+   viewport_array(ctx, first, count, p);
 }
 
 void GLAPIENTRY
 _mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v)
 {
    int i;
-   const struct gl_viewport_inputs *const p = (struct gl_viewport_inputs *) v;
+   struct gl_viewport_inputs *p = (struct gl_viewport_inputs *)v;
    GET_CURRENT_CONTEXT(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
@@ -182,21 +224,13 @@ _mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v)
       }
    }
 
-   for (i = 0; i < count; i++)
-      set_viewport_no_notify(ctx, i + first,
-                             p[i].X, p[i].Y,
-                             p[i].Width, p[i].Height);
-
-   if (ctx->Driver.Viewport)
-      ctx->Driver.Viewport(ctx);
+   viewport_array(ctx, first, count, p);
 }
 
 static void
-ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
-                 GLfloat w, GLfloat h, const char *function)
+viewport_indexed_err(struct gl_context *ctx, GLuint index, GLfloat x, GLfloat y,
+                     GLfloat w, GLfloat h, const char *function)
 {
-   GET_CURRENT_CONTEXT(ctx);
-
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "%s(%d, %f, %f, %f, %f)\n",
                   function, index, x, y, w, h);
@@ -219,17 +253,35 @@ ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
    _mesa_set_viewport(ctx, index, x, y, w, h);
 }
 
+void GLAPIENTRY
+_mesa_ViewportIndexedf_no_error(GLuint index, GLfloat x, GLfloat y,
+                                GLfloat w, GLfloat h)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_set_viewport(ctx, index, x, y, w, h);
+}
+
 void GLAPIENTRY
 _mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
                        GLfloat w, GLfloat h)
 {
-   ViewportIndexedf(index, x, y, w, h, "glViewportIndexedf");
+   GET_CURRENT_CONTEXT(ctx);
+   viewport_indexed_err(ctx, index, x, y, w, h, "glViewportIndexedf");
+}
+
+void GLAPIENTRY
+_mesa_ViewportIndexedfv_no_error(GLuint index, const GLfloat *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_set_viewport(ctx, index, v[0], v[1], v[2], v[3]);
 }
 
 void GLAPIENTRY
 _mesa_ViewportIndexedfv(GLuint index, const GLfloat *v)
 {
-   ViewportIndexedf(index, v[0], v[1], v[2], v[3], "glViewportIndexedfv");
+   GET_CURRENT_CONTEXT(ctx);
+   viewport_indexed_err(ctx, index, v[0], v[1], v[2], v[3],
+                        "glViewportIndexedfv");
 }
 
 static void
@@ -240,9 +292,12 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
        ctx->ViewportArray[idx].Far == farval)
       return;
 
+   /* The depth range is needed by program state constants. */
+   FLUSH_VERTICES(ctx, _NEW_VIEWPORT);
+   ctx->NewDriverState |= ctx->DriverFlags.NewViewport;
+
    ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0);
    ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0);
-   ctx->NewState |= _NEW_VIEWPORT;
 }
 
 void
@@ -269,8 +324,6 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval)
    unsigned i;
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    if (MESA_VERBOSE&VERBOSE_API)
       _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
 
@@ -307,10 +360,30 @@ _mesa_DepthRangef(GLclampf nearval, GLclampf farval)
  * \param v       pointer to memory containing
  *                GLclampd near and far clip-plane values
  */
+static ALWAYS_INLINE void
+depth_range_arrayv(struct gl_context *ctx, GLuint first, GLsizei count,
+                   const struct gl_depthrange_inputs *const inputs)
+{
+   for (GLsizei i = 0; i < count; i++)
+      set_depth_range_no_notify(ctx, i + first, inputs[i].Near, inputs[i].Far);
+
+   if (ctx->Driver.DepthRange)
+      ctx->Driver.DepthRange(ctx);
+}
+
+void GLAPIENTRY
+_mesa_DepthRangeArrayv_no_error(GLuint first, GLsizei count, const GLclampd *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   const struct gl_depthrange_inputs *const p =
+      (struct gl_depthrange_inputs *)v;
+   depth_range_arrayv(ctx, first, count, p);
+}
+
 void GLAPIENTRY
 _mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd *v)
 {
-   int i;
    const struct gl_depthrange_inputs *const p =
       (struct gl_depthrange_inputs *) v;
    GET_CURRENT_CONTEXT(ctx);
@@ -325,11 +398,7 @@ _mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd *v)
       return;
    }
 
-   for (i = 0; i < count; i++)
-      set_depth_range_no_notify(ctx, i + first, p[i].Near, p[i].Far);
-
-   if (ctx->Driver.DepthRange)
-      ctx->Driver.DepthRange(ctx);
+   depth_range_arrayv(ctx, first, count, p);
 }
 
 void GLAPIENTRY
@@ -364,6 +433,15 @@ _mesa_DepthRangeArrayfvOES(GLuint first, GLsizei count, const GLfloat *v)
  * \param farval   specifies the Z buffer value which should correspond to
  *                 the far clip plane
  */
+void GLAPIENTRY
+_mesa_DepthRangeIndexed_no_error(GLuint index, GLclampd nearval,
+                                 GLclampd farval)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_set_depth_range(ctx, index, nearval, farval);
+}
+
+
 void GLAPIENTRY
 _mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval)
 {
@@ -415,45 +493,38 @@ void _mesa_init_viewport(struct gl_context *ctx)
 }
 
 
-extern void GLAPIENTRY
-_mesa_ClipControl(GLenum origin, GLenum depth)
+static ALWAYS_INLINE void
+clip_control(struct gl_context *ctx, GLenum origin, GLenum depth, bool no_error)
 {
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (MESA_VERBOSE&VERBOSE_API)
-      _mesa_debug(ctx, "glClipControl(%s, %s)\n",
-                 _mesa_enum_to_string(origin),
-                  _mesa_enum_to_string(depth));
-
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!ctx->Extensions.ARB_clip_control) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glClipControl");
+   if (ctx->Transform.ClipOrigin == origin &&
+       ctx->Transform.ClipDepthMode == depth)
       return;
-   }
 
-   if (origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) {
+   if (!no_error &&
+       origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl");
       return;
    }
 
-   if (depth != GL_NEGATIVE_ONE_TO_ONE && depth != GL_ZERO_TO_ONE) {
+   if (!no_error &&
+       depth != GL_NEGATIVE_ONE_TO_ONE && depth != GL_ZERO_TO_ONE) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glClipControl");
       return;
    }
 
-   if (ctx->Transform.ClipOrigin == origin &&
-       ctx->Transform.ClipDepthMode == depth)
-      return;
-
    /* Affects transform state and the viewport transform */
-   FLUSH_VERTICES(ctx, _NEW_TRANSFORM | _NEW_VIEWPORT);
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewClipControl ? 0 :
+                  _NEW_TRANSFORM | _NEW_VIEWPORT);
+   ctx->NewDriverState |= ctx->DriverFlags.NewClipControl;
 
    if (ctx->Transform.ClipOrigin != origin) {
       ctx->Transform.ClipOrigin = origin;
 
       /* Affects the winding order of the front face. */
-      ctx->NewState |= _NEW_POLYGON;
+      if (ctx->DriverFlags.NewPolygonState)
+         ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState;
+      else
+         ctx->NewState |= _NEW_POLYGON;
 
       if (ctx->Driver.FrontFace)
          ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
@@ -467,6 +538,35 @@ _mesa_ClipControl(GLenum origin, GLenum depth)
    }
 }
 
+
+void GLAPIENTRY
+_mesa_ClipControl_no_error(GLenum origin, GLenum depth)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   clip_control(ctx, origin, depth, true);
+}
+
+
+void GLAPIENTRY
+_mesa_ClipControl(GLenum origin, GLenum depth)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glClipControl(%s, %s)\n",
+                 _mesa_enum_to_string(origin),
+                  _mesa_enum_to_string(depth));
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (!ctx->Extensions.ARB_clip_control) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glClipControl");
+      return;
+   }
+
+   clip_control(ctx, origin, depth, false);
+}
+
 /**
  * Computes the scaling and the translation part of the
  * viewport transform matrix of the \param i-th viewport