X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fclear.c;h=6beff9ed842bc7e38a8cd93429c92298b8184c1f;hb=e727f8c8b814b9c36d4a8b52829c2bf7281765be;hp=7eff07b65b0cf5f98189ad1213c0009132177657;hpb=e725dc0a74f594a4ff67579310e26651ecc5679d;p=mesa.git diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c index 7eff07b65b0..6beff9ed842 100644 --- a/src/mesa/main/clear.c +++ b/src/mesa/main/clear.c @@ -34,6 +34,8 @@ #include "clear.h" #include "context.h" #include "enums.h" +#include "fbobject.h" +#include "get.h" #include "macros.h" #include "mtypes.h" #include "state.h" @@ -58,10 +60,6 @@ _mesa_ClearIndex( GLfloat c ) * \param alpha alpha component. * * \sa glClearColor(). - * - * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a - * change, flushes the vertices and notifies the driver via the - * dd_function_table::ClearColor callback. */ void GLAPIENTRY _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) @@ -117,16 +115,17 @@ color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx) { struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx]; GLuint c; - GLubyte colorMask = 0; if (rb) { for (c = 0; c < 4; c++) { - if (_mesa_format_has_color_component(rb->Format, c)) - colorMask |= ctx->Color.ColorMask[idx][c]; + if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) && + _mesa_format_has_color_component(rb->Format, c)) { + return true; + } } } - return colorMask != 0; + return false; } @@ -141,40 +140,36 @@ color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx) * GL_RENDER then requests the driver to clear the buffers, via the * dd_function_table::Clear callback. */ -void GLAPIENTRY -_mesa_Clear( GLbitfield mask ) +static ALWAYS_INLINE void +clear(struct gl_context *ctx, GLbitfield mask, bool no_error) { - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); - FLUSH_CURRENT(ctx, 0); - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glClear 0x%x\n", mask); - - if (mask & ~(GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT | - GL_STENCIL_BUFFER_BIT | - GL_ACCUM_BUFFER_BIT)) { - /* invalid bit set */ - _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); - return; - } + if (!no_error) { + if (mask & ~(GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_ACCUM_BUFFER_BIT)) { + _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); + return; + } - /* Accumulation buffers were removed in core contexts, and they never - * existed in OpenGL ES. - */ - if ((mask & GL_ACCUM_BUFFER_BIT) != 0 - && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { - _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); - return; + /* Accumulation buffers were removed in core contexts, and they never + * existed in OpenGL ES. + */ + if ((mask & GL_ACCUM_BUFFER_BIT) != 0 + && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { + _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); + return; + } } if (ctx->NewState) { _mesa_update_state( ctx ); /* update _Xmin, etc */ } - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glClear(incomplete framebuffer)"); return; @@ -199,9 +194,9 @@ _mesa_Clear( GLbitfield mask ) if (mask & GL_COLOR_BUFFER_BIT) { GLuint i; for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; + gl_buffer_index buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; - if (buf >= 0 && color_buffer_writes_enabled(ctx, i)) { + if (buf != BUFFER_NONE && color_buffer_writes_enabled(ctx, i)) { bufferMask |= 1 << buf; } } @@ -222,14 +217,34 @@ _mesa_Clear( GLbitfield mask ) bufferMask |= BUFFER_BIT_ACCUM; } - ASSERT(ctx->Driver.Clear); + assert(ctx->Driver.Clear); ctx->Driver.Clear(ctx, bufferMask); } } +void GLAPIENTRY +_mesa_Clear_no_error(GLbitfield mask) +{ + GET_CURRENT_CONTEXT(ctx); + clear(ctx, mask, true); +} + + +void GLAPIENTRY +_mesa_Clear(GLbitfield mask) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glClear 0x%x\n", mask); + + clear(ctx, mask, false); +} + + /** Returned by make_color_buffer_mask() for errors */ -#define INVALID_MASK ~0x0 +#define INVALID_MASK ~0x0U /** @@ -269,6 +284,14 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) mask |= BUFFER_BIT_FRONT_RIGHT; break; case GL_BACK: + /* For GLES contexts with a single buffered configuration, we actually + * only have a front renderbuffer, so any clear calls to GL_BACK should + * affect that buffer. See draw_buffer_enum_to_bitmask for details. + */ + if (_mesa_is_gles(ctx)) + if (!ctx->DrawBuffer->Visual.doubleBufferMode) + if (att[BUFFER_FRONT_LEFT].Renderbuffer) + mask |= BUFFER_BIT_FRONT_LEFT; if (att[BUFFER_BACK_LEFT].Renderbuffer) mask |= BUFFER_BIT_BACK_LEFT; if (att[BUFFER_BACK_RIGHT].Renderbuffer) @@ -298,9 +321,10 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) break; default: { - GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; + gl_buffer_index buf = + ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; - if (buf >= 0 && att[buf].Renderbuffer) { + if (buf != BUFFER_NONE && att[buf].Renderbuffer) { mask |= 1 << buf; } } @@ -315,12 +339,11 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) * New in GL 3.0 * Clear signed integer color buffer or stencil buffer (not depth). */ -void GLAPIENTRY -_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) +static ALWAYS_INLINE void +clear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + const GLint *value, bool no_error) { - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); - FLUSH_CURRENT(ctx, 0); if (ctx->NewState) { @@ -336,7 +359,7 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." */ - if (drawbuffer != 0) { + if (!no_error && drawbuffer != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", drawbuffer); return; @@ -357,7 +380,7 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) case GL_COLOR: { const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); - if (mask == INVALID_MASK) { + if (!no_error && mask == INVALID_MASK) { _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", drawbuffer); return; @@ -376,42 +399,64 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) } } break; - case GL_DEPTH: - /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: - * - * "The result of ClearBuffer is undefined if no conversion between - * the type of the specified value and the type of the buffer being - * cleared is defined (for example, if ClearBufferiv is called for a - * fixed- or floating-point buffer, or if ClearBufferfv is called - * for a signed or unsigned integer buffer). This is not an error." - * - * In this case we take "undefined" and "not an error" to mean "ignore." - * Note that we still need to generate an error for the invalid - * drawbuffer case (see the GL_STENCIL case above). - */ - if (drawbuffer != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", - drawbuffer); - return; - } - return; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + if (!no_error) { + /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' + * of the OpenGL 4.5 spec states: + * + * "An INVALID_ENUM error is generated by ClearBufferiv and + * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." + */ + _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", + _mesa_enum_to_string(buffer)); + } return; } } +void GLAPIENTRY +_mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferiv(ctx, buffer, drawbuffer, value, true); +} + + +void GLAPIENTRY +_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferiv(ctx, buffer, drawbuffer, value, false); +} + + /** - * New in GL 3.0 - * Clear unsigned integer color buffer (not depth, not stencil). + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. */ void GLAPIENTRY -_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) +_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLint *value) { - GET_CURRENT_CONTEXT(ctx); + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + +/** + * New in GL 3.0 + * Clear unsigned integer color buffer (not depth, not stencil). + */ +static ALWAYS_INLINE void +clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + const GLuint *value, bool no_error) +{ FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); @@ -423,7 +468,7 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) case GL_COLOR: { const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); - if (mask == INVALID_MASK) { + if (!no_error && mask == INVALID_MASK) { _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", drawbuffer); return; @@ -442,48 +487,65 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) } } break; - case GL_DEPTH: - case GL_STENCIL: - /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: - * - * "The result of ClearBuffer is undefined if no conversion between - * the type of the specified value and the type of the buffer being - * cleared is defined (for example, if ClearBufferiv is called for a - * fixed- or floating-point buffer, or if ClearBufferfv is called - * for a signed or unsigned integer buffer). This is not an error." - * - * In this case we take "undefined" and "not an error" to mean "ignore." - * Even though we could do something sensible for GL_STENCIL, page 263 - * (page 279 of the PDF) says: - * - * "Only ClearBufferiv should be used to clear stencil buffers." - * - * Note that we still need to generate an error for the invalid - * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv). - */ - if (drawbuffer != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", - drawbuffer); - return; - } - return; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + if (!no_error) { + /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' + * of the OpenGL 4.5 spec states: + * + * "An INVALID_ENUM error is generated by ClearBufferuiv and + * ClearNamedFramebufferuiv if buffer is not COLOR." + */ + _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", + _mesa_enum_to_string(buffer)); + } return; } } +void GLAPIENTRY +_mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferuiv(ctx, buffer, drawbuffer, value, true); +} + + +void GLAPIENTRY +_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferuiv(ctx, buffer, drawbuffer, value, false); +} + + /** - * New in GL 3.0 - * Clear fixed-pt or float color buffer or depth buffer (not stencil). + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. */ void GLAPIENTRY -_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) +_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint *value) { - GET_CURRENT_CONTEXT(ctx); + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferuiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + +/** + * New in GL 3.0 + * Clear fixed-pt or float color buffer or depth buffer (not stencil). + */ +static ALWAYS_INLINE void +clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + const GLfloat *value, bool no_error) +{ FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); @@ -500,7 +562,7 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." */ - if (drawbuffer != 0) { + if (!no_error && drawbuffer != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", drawbuffer); return; @@ -522,7 +584,7 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) case GL_COLOR: { const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); - if (mask == INVALID_MASK) { + if (!no_error && mask == INVALID_MASK) { _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", drawbuffer); return; @@ -541,64 +603,89 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) } } break; - case GL_STENCIL: - /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: - * - * "The result of ClearBuffer is undefined if no conversion between - * the type of the specified value and the type of the buffer being - * cleared is defined (for example, if ClearBufferiv is called for a - * fixed- or floating-point buffer, or if ClearBufferfv is called - * for a signed or unsigned integer buffer). This is not an error." - * - * In this case we take "undefined" and "not an error" to mean "ignore." - * Note that we still need to generate an error for the invalid - * drawbuffer case (see the GL_DEPTH case above). - */ - if (drawbuffer != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", - drawbuffer); - return; - } - return; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); + if (!no_error) { + /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' + * of the OpenGL 4.5 spec states: + * + * "An INVALID_ENUM error is generated by ClearBufferfv and + * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH." + */ + _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", + _mesa_enum_to_string(buffer)); + } return; } } +void GLAPIENTRY +_mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferfv(ctx, buffer, drawbuffer, value, true); +} + + +void GLAPIENTRY +_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferfv(ctx, buffer, drawbuffer, value, false); +} + + +/** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLfloat *value) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + /** * New in GL 3.0 * Clear depth/stencil buffer only. */ -void GLAPIENTRY -_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, - GLfloat depth, GLint stencil) +static ALWAYS_INLINE void +clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil, bool no_error) { - GET_CURRENT_CONTEXT(ctx); GLbitfield mask = 0; FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); - if (buffer != GL_DEPTH_STENCIL) { - _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", - _mesa_lookup_enum_by_nr(buffer)); - return; - } + if (!no_error) { + if (buffer != GL_DEPTH_STENCIL) { + _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", + _mesa_enum_to_string(buffer)); + return; + } - /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: - * - * "ClearBuffer generates an INVALID VALUE error if buffer is - * COLOR and drawbuffer is less than zero, or greater than the - * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, - * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." - */ - if (drawbuffer != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", - drawbuffer); - return; + /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: + * + * "ClearBuffer generates an INVALID VALUE error if buffer is + * COLOR and drawbuffer is less than zero, or greater than the + * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, + * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." + */ + if (drawbuffer != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", + drawbuffer); + return; + } } if (ctx->RasterDiscard) @@ -630,3 +717,39 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, ctx->Stencil.Clear = clearStencilSave; } } + + +void GLAPIENTRY +_mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true); +} + + +void GLAPIENTRY +_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil) +{ + GET_CURRENT_CONTEXT(ctx); + clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false); +} + + +/** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, GLfloat depth, GLint stencil) +{ + GLint oldfb; + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +}