X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fviewport.c;h=d8b80aa469f68d4a55dc0f187add48156b30e37a;hb=11929895332213363628d632f7f9f6d79b5124d1;hp=f59723fad9571594c4f6551a7e02a16459ada0a3;hpb=0f01aa803332760079bde36218a3e884f2613db6;p=mesa.git diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c index f59723fad95..d8b80aa469f 100644 --- a/src/mesa/main/viewport.c +++ b/src/mesa/main/viewport.c @@ -36,13 +36,12 @@ #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: * @@ -52,24 +51,33 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx, * determined by calling GetFloatv with the symbolic constant * VIEWPORT_BOUNDS_RANGE (see section 6.1)." */ - if (ctx->Extensions.ARB_viewport_array) { - x = CLAMP(x, - ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max); - y = CLAMP(y, - ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max); + if (_mesa_has_ARB_viewport_array(ctx) || + _mesa_has_OES_viewport_array(ctx)) { + *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 { @@ -81,6 +89,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. @@ -88,12 +123,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); @@ -104,26 +144,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); } @@ -141,21 +162,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) @@ -180,21 +223,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); @@ -217,17 +252,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 @@ -238,9 +291,12 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx, ctx->ViewportArray[idx].Far == farval) return; - ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0); - ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0); - ctx->NewState |= _NEW_VIEWPORT; + /* The depth range is needed by program state constants. */ + FLUSH_VERTICES(ctx, _NEW_VIEWPORT); + ctx->NewDriverState |= ctx->DriverFlags.NewViewport; + + ctx->ViewportArray[idx].Near = SATURATE(nearval); + ctx->ViewportArray[idx].Far = SATURATE(farval); } void @@ -267,8 +323,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); @@ -305,10 +359,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); @@ -323,11 +397,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 @@ -362,6 +432,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) { @@ -409,49 +488,49 @@ void _mesa_init_viewport(struct gl_context *ctx) ctx->ViewportArray[i].Height = 0; ctx->ViewportArray[i].Near = 0.0; ctx->ViewportArray[i].Far = 1.0; + ctx->ViewportArray[i].SwizzleX = GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV; + ctx->ViewportArray[i].SwizzleY = GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV; + ctx->ViewportArray[i].SwizzleZ = GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV; + ctx->ViewportArray[i].SwizzleW = GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV; } + + ctx->SubpixelPrecisionBias[0] = 0; + ctx->SubpixelPrecisionBias[1] = 0; } -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); @@ -465,6 +544,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 @@ -498,3 +606,152 @@ _mesa_get_viewport_xform(struct gl_context *ctx, unsigned i, translate[2] = n; } } + + +static void +subpixel_precision_bias(struct gl_context *ctx, GLuint xbits, GLuint ybits) +{ + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); + + FLUSH_VERTICES(ctx, 0); + + ctx->SubpixelPrecisionBias[0] = xbits; + ctx->SubpixelPrecisionBias[1] = ybits; + + ctx->NewDriverState |= + ctx->DriverFlags.NewNvConservativeRasterizationParams; +} + +void GLAPIENTRY +_mesa_SubpixelPrecisionBiasNV_no_error(GLuint xbits, GLuint ybits) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); + + subpixel_precision_bias(ctx, xbits, ybits); +} + +void GLAPIENTRY +_mesa_SubpixelPrecisionBiasNV(GLuint xbits, GLuint ybits) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glSubpixelPrecisionBiasNV(%u, %u)\n", xbits, ybits); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.NV_conservative_raster) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glSubpixelPrecisionBiasNV not supported"); + return; + } + + if (xbits > ctx->Const.MaxSubpixelPrecisionBiasBits) { + _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV"); + return; + } + + if (ybits > ctx->Const.MaxSubpixelPrecisionBiasBits) { + _mesa_error(ctx, GL_INVALID_VALUE, "glSubpixelPrecisionBiasNV"); + return; + } + + subpixel_precision_bias(ctx, xbits, ybits); +} + +static void +set_viewport_swizzle(struct gl_context *ctx, GLuint index, + GLenum swizzlex, GLenum swizzley, + GLenum swizzlez, GLenum swizzlew) +{ + struct gl_viewport_attrib *viewport = &ctx->ViewportArray[index]; + if (viewport->SwizzleX == swizzlex && + viewport->SwizzleY == swizzley && + viewport->SwizzleZ == swizzlez && + viewport->SwizzleW == swizzlew) + return; + + FLUSH_VERTICES(ctx, _NEW_VIEWPORT); + ctx->NewDriverState |= ctx->DriverFlags.NewViewport; + + viewport->SwizzleX = swizzlex; + viewport->SwizzleY = swizzley; + viewport->SwizzleZ = swizzlez; + viewport->SwizzleW = swizzlew; +} + +void GLAPIENTRY +_mesa_ViewportSwizzleNV_no_error(GLuint index, + GLenum swizzlex, GLenum swizzley, + GLenum swizzlez, GLenum swizzlew) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewportSwizzleNV(%x, %x, %x, %x)\n", + swizzlex, swizzley, swizzlez, swizzlew); + + set_viewport_swizzle(ctx, index, swizzlex, swizzley, swizzlez, swizzlew); +} + +static bool +verify_viewport_swizzle(GLenum swizzle) +{ + return swizzle >= GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV && + swizzle <= GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV; +} + +void GLAPIENTRY +_mesa_ViewportSwizzleNV(GLuint index, + GLenum swizzlex, GLenum swizzley, + GLenum swizzlez, GLenum swizzlew) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewportSwizzleNV(%x, %x, %x, %x)\n", + swizzlex, swizzley, swizzlez, swizzlew); + + if (!ctx->Extensions.NV_viewport_swizzle) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glViewportSwizzleNV not supported"); + return; + } + + if (index >= ctx->Const.MaxViewports) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glViewportSwizzleNV: index (%d) >= MaxViewports (%d)", + index, ctx->Const.MaxViewports); + return; + } + + if (!verify_viewport_swizzle(swizzlex)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glViewportSwizzleNV(swizzlex=%x)", swizzlex); + return; + } + + if (!verify_viewport_swizzle(swizzley)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glViewportSwizzleNV(swizzley=%x)", swizzley); + return; + } + + if (!verify_viewport_swizzle(swizzlez)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glViewportSwizzleNV(swizzlez=%x)", swizzlez); + return; + } + + if (!verify_viewport_swizzle(swizzlew)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glViewportSwizzleNV(swizzlew=%x)", swizzlew); + return; + } + + set_viewport_swizzle(ctx, index, swizzlex, swizzley, swizzlez, swizzlew); +}