clear.c revision 01e04c3f
1c1f859d4Smrg/* 2c1f859d4Smrg * Mesa 3-D graphics library 3c1f859d4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5c1f859d4Smrg * 6c1f859d4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7c1f859d4Smrg * copy of this software and associated documentation files (the "Software"), 8c1f859d4Smrg * to deal in the Software without restriction, including without limitation 9c1f859d4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10c1f859d4Smrg * and/or sell copies of the Software, and to permit persons to whom the 11c1f859d4Smrg * Software is furnished to do so, subject to the following conditions: 12c1f859d4Smrg * 13c1f859d4Smrg * The above copyright notice and this permission notice shall be included 14c1f859d4Smrg * in all copies or substantial portions of the Software. 15c1f859d4Smrg * 16c1f859d4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17c1f859d4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18c1f859d4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 23c1f859d4Smrg */ 24c1f859d4Smrg 25c1f859d4Smrg 26c1f859d4Smrg/** 27c1f859d4Smrg * \file clear.c 28c1f859d4Smrg * glClearColor, glClearIndex, glClear() functions. 29c1f859d4Smrg */ 30c1f859d4Smrg 31c1f859d4Smrg 32c1f859d4Smrg 33c1f859d4Smrg#include "glheader.h" 34c1f859d4Smrg#include "clear.h" 35c1f859d4Smrg#include "context.h" 36cdc920a0Smrg#include "enums.h" 3701e04c3fSmrg#include "fbobject.h" 3801e04c3fSmrg#include "get.h" 393464ebd5Sriastradh#include "macros.h" 403464ebd5Sriastradh#include "mtypes.h" 41c1f859d4Smrg#include "state.h" 42c1f859d4Smrg 43c1f859d4Smrg 44c1f859d4Smrg 45c1f859d4Smrgvoid GLAPIENTRY 46c1f859d4Smrg_mesa_ClearIndex( GLfloat c ) 47c1f859d4Smrg{ 48c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 49c1f859d4Smrg 50c1f859d4Smrg ctx->Color.ClearIndex = (GLuint) c; 51c1f859d4Smrg} 52c1f859d4Smrg 53c1f859d4Smrg 54c1f859d4Smrg/** 55c1f859d4Smrg * Specify the clear values for the color buffers. 56c1f859d4Smrg * 57c1f859d4Smrg * \param red red color component. 58c1f859d4Smrg * \param green green color component. 59c1f859d4Smrg * \param blue blue color component. 60c1f859d4Smrg * \param alpha alpha component. 61c1f859d4Smrg * 62c1f859d4Smrg * \sa glClearColor(). 63c1f859d4Smrg */ 64c1f859d4Smrgvoid GLAPIENTRY 65c1f859d4Smrg_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 66c1f859d4Smrg{ 67c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 683464ebd5Sriastradh 69af69d88dSmrg ctx->Color.ClearColor.f[0] = red; 70af69d88dSmrg ctx->Color.ClearColor.f[1] = green; 71af69d88dSmrg ctx->Color.ClearColor.f[2] = blue; 72af69d88dSmrg ctx->Color.ClearColor.f[3] = alpha; 73c1f859d4Smrg} 74c1f859d4Smrg 75c1f859d4Smrg 763464ebd5Sriastradh/** 773464ebd5Sriastradh * GL_EXT_texture_integer 783464ebd5Sriastradh */ 793464ebd5Sriastradhvoid GLAPIENTRY 803464ebd5Sriastradh_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a) 813464ebd5Sriastradh{ 823464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 833464ebd5Sriastradh 84af69d88dSmrg ctx->Color.ClearColor.i[0] = r; 85af69d88dSmrg ctx->Color.ClearColor.i[1] = g; 86af69d88dSmrg ctx->Color.ClearColor.i[2] = b; 87af69d88dSmrg ctx->Color.ClearColor.i[3] = a; 883464ebd5Sriastradh} 893464ebd5Sriastradh 903464ebd5Sriastradh 913464ebd5Sriastradh/** 923464ebd5Sriastradh * GL_EXT_texture_integer 933464ebd5Sriastradh */ 943464ebd5Sriastradhvoid GLAPIENTRY 953464ebd5Sriastradh_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a) 963464ebd5Sriastradh{ 973464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 983464ebd5Sriastradh 99af69d88dSmrg ctx->Color.ClearColor.ui[0] = r; 100af69d88dSmrg ctx->Color.ClearColor.ui[1] = g; 101af69d88dSmrg ctx->Color.ClearColor.ui[2] = b; 102af69d88dSmrg ctx->Color.ClearColor.ui[3] = a; 103af69d88dSmrg} 1043464ebd5Sriastradh 1053464ebd5Sriastradh 106af69d88dSmrg/** 107af69d88dSmrg * Returns true if color writes are enabled for the given color attachment. 108af69d88dSmrg * 109af69d88dSmrg * Beyond checking ColorMask, this uses _mesa_format_has_color_component to 110af69d88dSmrg * ignore components that don't actually exist in the format (such as X in 111af69d88dSmrg * XRGB). 112af69d88dSmrg */ 113af69d88dSmrgstatic bool 114af69d88dSmrgcolor_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx) 115af69d88dSmrg{ 116af69d88dSmrg struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx]; 117af69d88dSmrg GLuint c; 118af69d88dSmrg 119af69d88dSmrg if (rb) { 120af69d88dSmrg for (c = 0; c < 4; c++) { 12101e04c3fSmrg if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) && 12201e04c3fSmrg _mesa_format_has_color_component(rb->Format, c)) { 12301e04c3fSmrg return true; 12401e04c3fSmrg } 125af69d88dSmrg } 1263464ebd5Sriastradh } 127af69d88dSmrg 12801e04c3fSmrg return false; 1293464ebd5Sriastradh} 1303464ebd5Sriastradh 1313464ebd5Sriastradh 132c1f859d4Smrg/** 133c1f859d4Smrg * Clear buffers. 13401e04c3fSmrg * 135c1f859d4Smrg * \param mask bit-mask indicating the buffers to be cleared. 136c1f859d4Smrg * 13701e04c3fSmrg * Flushes the vertices and verifies the parameter. 13801e04c3fSmrg * If __struct gl_contextRec::NewState is set then calls _mesa_update_state() 13901e04c3fSmrg * to update gl_frame_buffer::_Xmin, etc. If the rasterization mode is set to 14001e04c3fSmrg * GL_RENDER then requests the driver to clear the buffers, via the 14101e04c3fSmrg * dd_function_table::Clear callback. 14201e04c3fSmrg */ 14301e04c3fSmrgstatic ALWAYS_INLINE void 14401e04c3fSmrgclear(struct gl_context *ctx, GLbitfield mask, bool no_error) 145c1f859d4Smrg{ 146af69d88dSmrg FLUSH_VERTICES(ctx, 0); 147c1f859d4Smrg FLUSH_CURRENT(ctx, 0); 148c1f859d4Smrg 14901e04c3fSmrg if (!no_error) { 15001e04c3fSmrg if (mask & ~(GL_COLOR_BUFFER_BIT | 15101e04c3fSmrg GL_DEPTH_BUFFER_BIT | 15201e04c3fSmrg GL_STENCIL_BUFFER_BIT | 15301e04c3fSmrg GL_ACCUM_BUFFER_BIT)) { 15401e04c3fSmrg _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); 15501e04c3fSmrg return; 15601e04c3fSmrg } 157c1f859d4Smrg 15801e04c3fSmrg /* Accumulation buffers were removed in core contexts, and they never 15901e04c3fSmrg * existed in OpenGL ES. 16001e04c3fSmrg */ 16101e04c3fSmrg if ((mask & GL_ACCUM_BUFFER_BIT) != 0 16201e04c3fSmrg && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { 16301e04c3fSmrg _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); 16401e04c3fSmrg return; 16501e04c3fSmrg } 166af69d88dSmrg } 167af69d88dSmrg 168c1f859d4Smrg if (ctx->NewState) { 169c1f859d4Smrg _mesa_update_state( ctx ); /* update _Xmin, etc */ 170c1f859d4Smrg } 171c1f859d4Smrg 17201e04c3fSmrg if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 173c1f859d4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 174c1f859d4Smrg "glClear(incomplete framebuffer)"); 175c1f859d4Smrg return; 176c1f859d4Smrg } 177c1f859d4Smrg 178af69d88dSmrg if (ctx->RasterDiscard) 179c1f859d4Smrg return; 180c1f859d4Smrg 181c1f859d4Smrg if (ctx->RenderMode == GL_RENDER) { 182c1f859d4Smrg GLbitfield bufferMask; 183c1f859d4Smrg 184c1f859d4Smrg /* don't clear depth buffer if depth writing disabled */ 185c1f859d4Smrg if (!ctx->Depth.Mask) 186c1f859d4Smrg mask &= ~GL_DEPTH_BUFFER_BIT; 187c1f859d4Smrg 188c1f859d4Smrg /* Build the bitmask to send to device driver's Clear function. 189c1f859d4Smrg * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 190c1f859d4Smrg * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 191c1f859d4Smrg * BUFFER_BIT_COLORn flags. 192c1f859d4Smrg */ 193c1f859d4Smrg bufferMask = 0; 194c1f859d4Smrg if (mask & GL_COLOR_BUFFER_BIT) { 195c1f859d4Smrg GLuint i; 196c1f859d4Smrg for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 19701e04c3fSmrg gl_buffer_index buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; 198af69d88dSmrg 19901e04c3fSmrg if (buf != BUFFER_NONE && color_buffer_writes_enabled(ctx, i)) { 200af69d88dSmrg bufferMask |= 1 << buf; 201af69d88dSmrg } 202c1f859d4Smrg } 203c1f859d4Smrg } 204c1f859d4Smrg 205c1f859d4Smrg if ((mask & GL_DEPTH_BUFFER_BIT) 206c1f859d4Smrg && ctx->DrawBuffer->Visual.haveDepthBuffer) { 207c1f859d4Smrg bufferMask |= BUFFER_BIT_DEPTH; 208c1f859d4Smrg } 209c1f859d4Smrg 210c1f859d4Smrg if ((mask & GL_STENCIL_BUFFER_BIT) 211c1f859d4Smrg && ctx->DrawBuffer->Visual.haveStencilBuffer) { 212c1f859d4Smrg bufferMask |= BUFFER_BIT_STENCIL; 213c1f859d4Smrg } 214c1f859d4Smrg 215c1f859d4Smrg if ((mask & GL_ACCUM_BUFFER_BIT) 216c1f859d4Smrg && ctx->DrawBuffer->Visual.haveAccumBuffer) { 217c1f859d4Smrg bufferMask |= BUFFER_BIT_ACCUM; 218c1f859d4Smrg } 219c1f859d4Smrg 22001e04c3fSmrg assert(ctx->Driver.Clear); 221c1f859d4Smrg ctx->Driver.Clear(ctx, bufferMask); 222c1f859d4Smrg } 223c1f859d4Smrg} 224cdc920a0Smrg 225cdc920a0Smrg 22601e04c3fSmrgvoid GLAPIENTRY 22701e04c3fSmrg_mesa_Clear_no_error(GLbitfield mask) 22801e04c3fSmrg{ 22901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 23001e04c3fSmrg clear(ctx, mask, true); 23101e04c3fSmrg} 23201e04c3fSmrg 23301e04c3fSmrg 23401e04c3fSmrgvoid GLAPIENTRY 23501e04c3fSmrg_mesa_Clear(GLbitfield mask) 23601e04c3fSmrg{ 23701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 23801e04c3fSmrg 23901e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 24001e04c3fSmrg _mesa_debug(ctx, "glClear 0x%x\n", mask); 24101e04c3fSmrg 24201e04c3fSmrg clear(ctx, mask, false); 24301e04c3fSmrg} 24401e04c3fSmrg 24501e04c3fSmrg 246cdc920a0Smrg/** Returned by make_color_buffer_mask() for errors */ 24701e04c3fSmrg#define INVALID_MASK ~0x0U 248cdc920a0Smrg 249cdc920a0Smrg 250cdc920a0Smrg/** 251cdc920a0Smrg * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of 252cdc920a0Smrg * BUFFER_BIT_x values. 253cdc920a0Smrg * Return INVALID_MASK if the drawbuffer value is invalid. 254cdc920a0Smrg */ 255cdc920a0Smrgstatic GLbitfield 2563464ebd5Sriastradhmake_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) 257cdc920a0Smrg{ 258cdc920a0Smrg const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; 259cdc920a0Smrg GLbitfield mask = 0x0; 260cdc920a0Smrg 261af69d88dSmrg /* From the GL 4.0 specification: 262af69d88dSmrg * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is 263af69d88dSmrg * specified by passing i as the parameter drawbuffer, and value 264af69d88dSmrg * points to a four-element vector specifying the R, G, B, and A 265af69d88dSmrg * color to clear that draw buffer to. If the draw buffer is one 266af69d88dSmrg * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying 267af69d88dSmrg * multiple buffers, each selected buffer is cleared to the same 268af69d88dSmrg * value. 269af69d88dSmrg * 270af69d88dSmrg * Note that "drawbuffer" and "draw buffer" have different meaning. 271af69d88dSmrg * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's 272af69d88dSmrg * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK, 273af69d88dSmrg * etc. 274af69d88dSmrg */ 275af69d88dSmrg if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 276af69d88dSmrg return INVALID_MASK; 277af69d88dSmrg } 278af69d88dSmrg 279af69d88dSmrg switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) { 280cdc920a0Smrg case GL_FRONT: 281cdc920a0Smrg if (att[BUFFER_FRONT_LEFT].Renderbuffer) 282cdc920a0Smrg mask |= BUFFER_BIT_FRONT_LEFT; 283cdc920a0Smrg if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 284cdc920a0Smrg mask |= BUFFER_BIT_FRONT_RIGHT; 285cdc920a0Smrg break; 286cdc920a0Smrg case GL_BACK: 28701e04c3fSmrg /* For GLES contexts with a single buffered configuration, we actually 28801e04c3fSmrg * only have a front renderbuffer, so any clear calls to GL_BACK should 28901e04c3fSmrg * affect that buffer. See draw_buffer_enum_to_bitmask for details. 29001e04c3fSmrg */ 29101e04c3fSmrg if (_mesa_is_gles(ctx)) 29201e04c3fSmrg if (!ctx->DrawBuffer->Visual.doubleBufferMode) 29301e04c3fSmrg if (att[BUFFER_FRONT_LEFT].Renderbuffer) 29401e04c3fSmrg mask |= BUFFER_BIT_FRONT_LEFT; 295cdc920a0Smrg if (att[BUFFER_BACK_LEFT].Renderbuffer) 296cdc920a0Smrg mask |= BUFFER_BIT_BACK_LEFT; 297cdc920a0Smrg if (att[BUFFER_BACK_RIGHT].Renderbuffer) 298cdc920a0Smrg mask |= BUFFER_BIT_BACK_RIGHT; 299cdc920a0Smrg break; 300cdc920a0Smrg case GL_LEFT: 301cdc920a0Smrg if (att[BUFFER_FRONT_LEFT].Renderbuffer) 302cdc920a0Smrg mask |= BUFFER_BIT_FRONT_LEFT; 303cdc920a0Smrg if (att[BUFFER_BACK_LEFT].Renderbuffer) 304cdc920a0Smrg mask |= BUFFER_BIT_BACK_LEFT; 305cdc920a0Smrg break; 306cdc920a0Smrg case GL_RIGHT: 307cdc920a0Smrg if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 308cdc920a0Smrg mask |= BUFFER_BIT_FRONT_RIGHT; 309cdc920a0Smrg if (att[BUFFER_BACK_RIGHT].Renderbuffer) 310cdc920a0Smrg mask |= BUFFER_BIT_BACK_RIGHT; 311cdc920a0Smrg break; 312cdc920a0Smrg case GL_FRONT_AND_BACK: 313cdc920a0Smrg if (att[BUFFER_FRONT_LEFT].Renderbuffer) 314cdc920a0Smrg mask |= BUFFER_BIT_FRONT_LEFT; 315cdc920a0Smrg if (att[BUFFER_BACK_LEFT].Renderbuffer) 316cdc920a0Smrg mask |= BUFFER_BIT_BACK_LEFT; 317cdc920a0Smrg if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 318cdc920a0Smrg mask |= BUFFER_BIT_FRONT_RIGHT; 319cdc920a0Smrg if (att[BUFFER_BACK_RIGHT].Renderbuffer) 320cdc920a0Smrg mask |= BUFFER_BIT_BACK_RIGHT; 321cdc920a0Smrg break; 322cdc920a0Smrg default: 323af69d88dSmrg { 32401e04c3fSmrg gl_buffer_index buf = 32501e04c3fSmrg ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; 326af69d88dSmrg 32701e04c3fSmrg if (buf != BUFFER_NONE && att[buf].Renderbuffer) { 328af69d88dSmrg mask |= 1 << buf; 329af69d88dSmrg } 330cdc920a0Smrg } 331cdc920a0Smrg } 332cdc920a0Smrg 333cdc920a0Smrg return mask; 334cdc920a0Smrg} 335cdc920a0Smrg 336cdc920a0Smrg 337cdc920a0Smrg 338cdc920a0Smrg/** 339cdc920a0Smrg * New in GL 3.0 340cdc920a0Smrg * Clear signed integer color buffer or stencil buffer (not depth). 341cdc920a0Smrg */ 34201e04c3fSmrgstatic ALWAYS_INLINE void 34301e04c3fSmrgclear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 34401e04c3fSmrg const GLint *value, bool no_error) 345cdc920a0Smrg{ 346af69d88dSmrg FLUSH_VERTICES(ctx, 0); 347cdc920a0Smrg FLUSH_CURRENT(ctx, 0); 348cdc920a0Smrg 349cdc920a0Smrg if (ctx->NewState) { 350cdc920a0Smrg _mesa_update_state( ctx ); 351cdc920a0Smrg } 352cdc920a0Smrg 353cdc920a0Smrg switch (buffer) { 354cdc920a0Smrg case GL_STENCIL: 355af69d88dSmrg /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 356af69d88dSmrg * 357af69d88dSmrg * "ClearBuffer generates an INVALID VALUE error if buffer is 358af69d88dSmrg * COLOR and drawbuffer is less than zero, or greater than the 359af69d88dSmrg * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 360af69d88dSmrg * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 361af69d88dSmrg */ 36201e04c3fSmrg if (!no_error && drawbuffer != 0) { 363cdc920a0Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 364cdc920a0Smrg drawbuffer); 365cdc920a0Smrg return; 366cdc920a0Smrg } 36701e04c3fSmrg else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer 36801e04c3fSmrg && !ctx->RasterDiscard) { 369cdc920a0Smrg /* Save current stencil clear value, set to 'value', do the 370cdc920a0Smrg * stencil clear and restore the clear value. 371cdc920a0Smrg * XXX in the future we may have a new ctx->Driver.ClearBuffer() 372cdc920a0Smrg * hook instead. 373cdc920a0Smrg */ 374cdc920a0Smrg const GLuint clearSave = ctx->Stencil.Clear; 375cdc920a0Smrg ctx->Stencil.Clear = *value; 376cdc920a0Smrg ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL); 377cdc920a0Smrg ctx->Stencil.Clear = clearSave; 378cdc920a0Smrg } 379cdc920a0Smrg break; 380cdc920a0Smrg case GL_COLOR: 381cdc920a0Smrg { 382cdc920a0Smrg const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 38301e04c3fSmrg if (!no_error && mask == INVALID_MASK) { 384cdc920a0Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 385cdc920a0Smrg drawbuffer); 386cdc920a0Smrg return; 387cdc920a0Smrg } 388af69d88dSmrg else if (mask && !ctx->RasterDiscard) { 389af69d88dSmrg union gl_color_union clearSave; 390af69d88dSmrg 391cdc920a0Smrg /* save color */ 392af69d88dSmrg clearSave = ctx->Color.ClearColor; 393cdc920a0Smrg /* set color */ 394af69d88dSmrg COPY_4V(ctx->Color.ClearColor.i, value); 395cdc920a0Smrg /* clear buffer(s) */ 396cdc920a0Smrg ctx->Driver.Clear(ctx, mask); 397cdc920a0Smrg /* restore color */ 398af69d88dSmrg ctx->Color.ClearColor = clearSave; 399cdc920a0Smrg } 400cdc920a0Smrg } 401cdc920a0Smrg break; 402cdc920a0Smrg default: 40301e04c3fSmrg if (!no_error) { 40401e04c3fSmrg /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 40501e04c3fSmrg * of the OpenGL 4.5 spec states: 40601e04c3fSmrg * 40701e04c3fSmrg * "An INVALID_ENUM error is generated by ClearBufferiv and 40801e04c3fSmrg * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." 40901e04c3fSmrg */ 41001e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 41101e04c3fSmrg _mesa_enum_to_string(buffer)); 41201e04c3fSmrg } 413cdc920a0Smrg return; 414cdc920a0Smrg } 415cdc920a0Smrg} 416cdc920a0Smrg 417cdc920a0Smrg 41801e04c3fSmrgvoid GLAPIENTRY 41901e04c3fSmrg_mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value) 42001e04c3fSmrg{ 42101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 42201e04c3fSmrg clear_bufferiv(ctx, buffer, drawbuffer, value, true); 42301e04c3fSmrg} 42401e04c3fSmrg 42501e04c3fSmrg 42601e04c3fSmrgvoid GLAPIENTRY 42701e04c3fSmrg_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 42801e04c3fSmrg{ 42901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 43001e04c3fSmrg clear_bufferiv(ctx, buffer, drawbuffer, value, false); 43101e04c3fSmrg} 43201e04c3fSmrg 43301e04c3fSmrg 434cdc920a0Smrg/** 43501e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the 43601e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake 43701e04c3fSmrg * direct state access clearing for the user. 438cdc920a0Smrg */ 439cdc920a0Smrgvoid GLAPIENTRY 44001e04c3fSmrg_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, 44101e04c3fSmrg GLint drawbuffer, const GLint *value) 442cdc920a0Smrg{ 44301e04c3fSmrg GLint oldfb; 44401e04c3fSmrg 44501e04c3fSmrg _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 44601e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 44701e04c3fSmrg _mesa_ClearBufferiv(buffer, drawbuffer, value); 44801e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 44901e04c3fSmrg} 45001e04c3fSmrg 451cdc920a0Smrg 45201e04c3fSmrg/** 45301e04c3fSmrg * New in GL 3.0 45401e04c3fSmrg * Clear unsigned integer color buffer (not depth, not stencil). 45501e04c3fSmrg */ 45601e04c3fSmrgstatic ALWAYS_INLINE void 45701e04c3fSmrgclear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 45801e04c3fSmrg const GLuint *value, bool no_error) 45901e04c3fSmrg{ 460af69d88dSmrg FLUSH_VERTICES(ctx, 0); 461cdc920a0Smrg FLUSH_CURRENT(ctx, 0); 462cdc920a0Smrg 463cdc920a0Smrg if (ctx->NewState) { 464cdc920a0Smrg _mesa_update_state( ctx ); 465cdc920a0Smrg } 466cdc920a0Smrg 467cdc920a0Smrg switch (buffer) { 468cdc920a0Smrg case GL_COLOR: 469cdc920a0Smrg { 470cdc920a0Smrg const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 47101e04c3fSmrg if (!no_error && mask == INVALID_MASK) { 4723464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 473cdc920a0Smrg drawbuffer); 474cdc920a0Smrg return; 475cdc920a0Smrg } 476af69d88dSmrg else if (mask && !ctx->RasterDiscard) { 477af69d88dSmrg union gl_color_union clearSave; 478af69d88dSmrg 479cdc920a0Smrg /* save color */ 480af69d88dSmrg clearSave = ctx->Color.ClearColor; 481cdc920a0Smrg /* set color */ 482af69d88dSmrg COPY_4V(ctx->Color.ClearColor.ui, value); 483cdc920a0Smrg /* clear buffer(s) */ 484cdc920a0Smrg ctx->Driver.Clear(ctx, mask); 485cdc920a0Smrg /* restore color */ 486af69d88dSmrg ctx->Color.ClearColor = clearSave; 487cdc920a0Smrg } 488cdc920a0Smrg } 489cdc920a0Smrg break; 490cdc920a0Smrg default: 49101e04c3fSmrg if (!no_error) { 49201e04c3fSmrg /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 49301e04c3fSmrg * of the OpenGL 4.5 spec states: 49401e04c3fSmrg * 49501e04c3fSmrg * "An INVALID_ENUM error is generated by ClearBufferuiv and 49601e04c3fSmrg * ClearNamedFramebufferuiv if buffer is not COLOR." 49701e04c3fSmrg */ 49801e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 49901e04c3fSmrg _mesa_enum_to_string(buffer)); 50001e04c3fSmrg } 501cdc920a0Smrg return; 502cdc920a0Smrg } 503cdc920a0Smrg} 504cdc920a0Smrg 505cdc920a0Smrg 50601e04c3fSmrgvoid GLAPIENTRY 50701e04c3fSmrg_mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer, 50801e04c3fSmrg const GLuint *value) 50901e04c3fSmrg{ 51001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 51101e04c3fSmrg clear_bufferuiv(ctx, buffer, drawbuffer, value, true); 51201e04c3fSmrg} 51301e04c3fSmrg 51401e04c3fSmrg 51501e04c3fSmrgvoid GLAPIENTRY 51601e04c3fSmrg_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 51701e04c3fSmrg{ 51801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 51901e04c3fSmrg clear_bufferuiv(ctx, buffer, drawbuffer, value, false); 52001e04c3fSmrg} 52101e04c3fSmrg 52201e04c3fSmrg 523cdc920a0Smrg/** 52401e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the 52501e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake 52601e04c3fSmrg * direct state access clearing for the user. 527cdc920a0Smrg */ 528cdc920a0Smrgvoid GLAPIENTRY 52901e04c3fSmrg_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, 53001e04c3fSmrg GLint drawbuffer, const GLuint *value) 531cdc920a0Smrg{ 53201e04c3fSmrg GLint oldfb; 533cdc920a0Smrg 53401e04c3fSmrg _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 53501e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 53601e04c3fSmrg _mesa_ClearBufferuiv(buffer, drawbuffer, value); 53701e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 53801e04c3fSmrg} 53901e04c3fSmrg 54001e04c3fSmrg 54101e04c3fSmrg/** 54201e04c3fSmrg * New in GL 3.0 54301e04c3fSmrg * Clear fixed-pt or float color buffer or depth buffer (not stencil). 54401e04c3fSmrg */ 54501e04c3fSmrgstatic ALWAYS_INLINE void 54601e04c3fSmrgclear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 54701e04c3fSmrg const GLfloat *value, bool no_error) 54801e04c3fSmrg{ 549af69d88dSmrg FLUSH_VERTICES(ctx, 0); 550cdc920a0Smrg FLUSH_CURRENT(ctx, 0); 551cdc920a0Smrg 552cdc920a0Smrg if (ctx->NewState) { 553cdc920a0Smrg _mesa_update_state( ctx ); 554cdc920a0Smrg } 555cdc920a0Smrg 556cdc920a0Smrg switch (buffer) { 557cdc920a0Smrg case GL_DEPTH: 558af69d88dSmrg /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 559af69d88dSmrg * 560af69d88dSmrg * "ClearBuffer generates an INVALID VALUE error if buffer is 561af69d88dSmrg * COLOR and drawbuffer is less than zero, or greater than the 562af69d88dSmrg * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 563af69d88dSmrg * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 564af69d88dSmrg */ 56501e04c3fSmrg if (!no_error && drawbuffer != 0) { 566cdc920a0Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 567cdc920a0Smrg drawbuffer); 568cdc920a0Smrg return; 569cdc920a0Smrg } 57001e04c3fSmrg else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer 57101e04c3fSmrg && !ctx->RasterDiscard) { 572cdc920a0Smrg /* Save current depth clear value, set to 'value', do the 573cdc920a0Smrg * depth clear and restore the clear value. 574cdc920a0Smrg * XXX in the future we may have a new ctx->Driver.ClearBuffer() 575cdc920a0Smrg * hook instead. 576cdc920a0Smrg */ 577cdc920a0Smrg const GLclampd clearSave = ctx->Depth.Clear; 578cdc920a0Smrg ctx->Depth.Clear = *value; 579cdc920a0Smrg ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH); 580cdc920a0Smrg ctx->Depth.Clear = clearSave; 581cdc920a0Smrg } 582cdc920a0Smrg /* clear depth buffer to value */ 583cdc920a0Smrg break; 584cdc920a0Smrg case GL_COLOR: 585cdc920a0Smrg { 586cdc920a0Smrg const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 58701e04c3fSmrg if (!no_error && mask == INVALID_MASK) { 588cdc920a0Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 589cdc920a0Smrg drawbuffer); 590cdc920a0Smrg return; 591cdc920a0Smrg } 592af69d88dSmrg else if (mask && !ctx->RasterDiscard) { 593af69d88dSmrg union gl_color_union clearSave; 594af69d88dSmrg 595cdc920a0Smrg /* save color */ 596af69d88dSmrg clearSave = ctx->Color.ClearColor; 597cdc920a0Smrg /* set color */ 598af69d88dSmrg COPY_4V(ctx->Color.ClearColor.f, value); 599cdc920a0Smrg /* clear buffer(s) */ 600cdc920a0Smrg ctx->Driver.Clear(ctx, mask); 601cdc920a0Smrg /* restore color */ 602af69d88dSmrg ctx->Color.ClearColor = clearSave; 603cdc920a0Smrg } 604cdc920a0Smrg } 605cdc920a0Smrg break; 606cdc920a0Smrg default: 60701e04c3fSmrg if (!no_error) { 60801e04c3fSmrg /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 60901e04c3fSmrg * of the OpenGL 4.5 spec states: 61001e04c3fSmrg * 61101e04c3fSmrg * "An INVALID_ENUM error is generated by ClearBufferfv and 61201e04c3fSmrg * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH." 61301e04c3fSmrg */ 61401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 61501e04c3fSmrg _mesa_enum_to_string(buffer)); 61601e04c3fSmrg } 617cdc920a0Smrg return; 618cdc920a0Smrg } 619cdc920a0Smrg} 620cdc920a0Smrg 621cdc920a0Smrg 62201e04c3fSmrgvoid GLAPIENTRY 62301e04c3fSmrg_mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer, 62401e04c3fSmrg const GLfloat *value) 62501e04c3fSmrg{ 62601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 62701e04c3fSmrg clear_bufferfv(ctx, buffer, drawbuffer, value, true); 62801e04c3fSmrg} 62901e04c3fSmrg 63001e04c3fSmrg 63101e04c3fSmrgvoid GLAPIENTRY 63201e04c3fSmrg_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 63301e04c3fSmrg{ 63401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 63501e04c3fSmrg clear_bufferfv(ctx, buffer, drawbuffer, value, false); 63601e04c3fSmrg} 63701e04c3fSmrg 63801e04c3fSmrg 63901e04c3fSmrg/** 64001e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the 64101e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake 64201e04c3fSmrg * direct state access clearing for the user. 64301e04c3fSmrg */ 64401e04c3fSmrgvoid GLAPIENTRY 64501e04c3fSmrg_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, 64601e04c3fSmrg GLint drawbuffer, const GLfloat *value) 64701e04c3fSmrg{ 64801e04c3fSmrg GLint oldfb; 64901e04c3fSmrg 65001e04c3fSmrg _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 65101e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 65201e04c3fSmrg _mesa_ClearBufferfv(buffer, drawbuffer, value); 65301e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 65401e04c3fSmrg} 65501e04c3fSmrg 65601e04c3fSmrg 657cdc920a0Smrg/** 658cdc920a0Smrg * New in GL 3.0 659cdc920a0Smrg * Clear depth/stencil buffer only. 660cdc920a0Smrg */ 66101e04c3fSmrgstatic ALWAYS_INLINE void 66201e04c3fSmrgclear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 66301e04c3fSmrg GLfloat depth, GLint stencil, bool no_error) 664cdc920a0Smrg{ 665af69d88dSmrg GLbitfield mask = 0; 666cdc920a0Smrg 667af69d88dSmrg FLUSH_VERTICES(ctx, 0); 668cdc920a0Smrg FLUSH_CURRENT(ctx, 0); 669cdc920a0Smrg 67001e04c3fSmrg if (!no_error) { 67101e04c3fSmrg if (buffer != GL_DEPTH_STENCIL) { 67201e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 67301e04c3fSmrg _mesa_enum_to_string(buffer)); 67401e04c3fSmrg return; 67501e04c3fSmrg } 676cdc920a0Smrg 67701e04c3fSmrg /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 67801e04c3fSmrg * 67901e04c3fSmrg * "ClearBuffer generates an INVALID VALUE error if buffer is 68001e04c3fSmrg * COLOR and drawbuffer is less than zero, or greater than the 68101e04c3fSmrg * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 68201e04c3fSmrg * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 68301e04c3fSmrg */ 68401e04c3fSmrg if (drawbuffer != 0) { 68501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 68601e04c3fSmrg drawbuffer); 68701e04c3fSmrg return; 68801e04c3fSmrg } 689cdc920a0Smrg } 690cdc920a0Smrg 691af69d88dSmrg if (ctx->RasterDiscard) 692af69d88dSmrg return; 693af69d88dSmrg 694cdc920a0Smrg if (ctx->NewState) { 695cdc920a0Smrg _mesa_update_state( ctx ); 696cdc920a0Smrg } 697cdc920a0Smrg 698af69d88dSmrg if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 699af69d88dSmrg mask |= BUFFER_BIT_DEPTH; 700af69d88dSmrg if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 701af69d88dSmrg mask |= BUFFER_BIT_STENCIL; 702af69d88dSmrg 703af69d88dSmrg if (mask) { 704cdc920a0Smrg /* save current clear values */ 705cdc920a0Smrg const GLclampd clearDepthSave = ctx->Depth.Clear; 706cdc920a0Smrg const GLuint clearStencilSave = ctx->Stencil.Clear; 707cdc920a0Smrg 708cdc920a0Smrg /* set new clear values */ 709cdc920a0Smrg ctx->Depth.Clear = depth; 710cdc920a0Smrg ctx->Stencil.Clear = stencil; 711cdc920a0Smrg 712cdc920a0Smrg /* clear buffers */ 713af69d88dSmrg ctx->Driver.Clear(ctx, mask); 714cdc920a0Smrg 715cdc920a0Smrg /* restore */ 716cdc920a0Smrg ctx->Depth.Clear = clearDepthSave; 717cdc920a0Smrg ctx->Stencil.Clear = clearStencilSave; 718cdc920a0Smrg } 719cdc920a0Smrg} 72001e04c3fSmrg 72101e04c3fSmrg 72201e04c3fSmrgvoid GLAPIENTRY 72301e04c3fSmrg_mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer, 72401e04c3fSmrg GLfloat depth, GLint stencil) 72501e04c3fSmrg{ 72601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 72701e04c3fSmrg clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true); 72801e04c3fSmrg} 72901e04c3fSmrg 73001e04c3fSmrg 73101e04c3fSmrgvoid GLAPIENTRY 73201e04c3fSmrg_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 73301e04c3fSmrg GLfloat depth, GLint stencil) 73401e04c3fSmrg{ 73501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 73601e04c3fSmrg clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false); 73701e04c3fSmrg} 73801e04c3fSmrg 73901e04c3fSmrg 74001e04c3fSmrg/** 74101e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the 74201e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake 74301e04c3fSmrg * direct state access clearing for the user. 74401e04c3fSmrg */ 74501e04c3fSmrgvoid GLAPIENTRY 74601e04c3fSmrg_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, 74701e04c3fSmrg GLint drawbuffer, GLfloat depth, GLint stencil) 74801e04c3fSmrg{ 74901e04c3fSmrg GLint oldfb; 75001e04c3fSmrg 75101e04c3fSmrg _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 75201e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 75301e04c3fSmrg _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); 75401e04c3fSmrg _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 75501e04c3fSmrg} 756