X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fclear.c;h=6beff9ed842bc7e38a8cd93429c92298b8184c1f;hb=36b3e7ea90ee275451184b287577f4b88962df81;hp=426caea470903dddce970400216862c12fd52d28;hpb=a62edcce4eb4c800d972817a20ee874bf2a2c3ef;p=mesa.git diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c index 426caea4709..6beff9ed842 100644 --- a/src/mesa/main/clear.c +++ b/src/mesa/main/clear.c @@ -115,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; } @@ -139,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; @@ -197,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; } } @@ -226,6 +223,26 @@ _mesa_Clear( GLbitfield mask ) } +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 ~0x0U @@ -267,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) @@ -296,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; } } @@ -313,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) { @@ -334,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; @@ -355,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; @@ -374,33 +399,38 @@ _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); +} + + /** * The ClearBuffer framework is so complicated and so riddled with the * assumption that the framebuffer is bound that, for now, we will just fake @@ -423,11 +453,10 @@ _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, * New in GL 3.0 * Clear unsigned integer color buffer (not depth, not stencil). */ -void GLAPIENTRY -_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) +static ALWAYS_INLINE void +clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + const GLuint *value, bool no_error) { - GET_CURRENT_CONTEXT(ctx); - FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); @@ -439,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; @@ -458,39 +487,39 @@ _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); +} + + /** * The ClearBuffer framework is so complicated and so riddled with the * assumption that the framebuffer is bound that, for now, we will just fake @@ -513,11 +542,10 @@ _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, * New in GL 3.0 * Clear fixed-pt or float color buffer or depth buffer (not stencil). */ -void GLAPIENTRY -_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) +static ALWAYS_INLINE void +clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, + const GLfloat *value, bool no_error) { - GET_CURRENT_CONTEXT(ctx); - FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); @@ -534,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; @@ -556,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; @@ -575,33 +603,39 @@ _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 @@ -624,33 +658,34 @@ _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, * 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) @@ -684,6 +719,24 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, } +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 @@ -691,12 +744,12 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, */ void GLAPIENTRY _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, - GLfloat depth, GLint stencil) + GLint drawbuffer, GLfloat depth, GLint stencil) { GLint oldfb; _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); - _mesa_ClearBufferfi(buffer, 0, depth, stencil); + _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); }