📄 buffers.c
字号:
/* * Mesa 3-D graphics library * Version: 7.1 * * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file buffers.c * General framebuffer-related functions, like glClear, glScissor, etc. */#include "glheader.h"#include "buffers.h"#include "colormac.h"#include "context.h"#include "enums.h"#include "fbobject.h"#include "state.h"#define BAD_MASK ~0u#if _HAVE_FULL_GLvoid GLAPIENTRY_mesa_ClearIndex( GLfloat c ){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (ctx->Color.ClearIndex == (GLuint) c) return; FLUSH_VERTICES(ctx, _NEW_COLOR); ctx->Color.ClearIndex = (GLuint) c; if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) { /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); }}#endif/** * Specify the clear values for the color buffers. * * \param red red color component. * \param green green color component. * \param blue blue color component. * \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 ){ GLfloat tmp[4]; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); tmp[0] = CLAMP(red, 0.0F, 1.0F); tmp[1] = CLAMP(green, 0.0F, 1.0F); tmp[2] = CLAMP(blue, 0.0F, 1.0F); tmp[3] = CLAMP(alpha, 0.0F, 1.0F); if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) return; /* no change */ FLUSH_VERTICES(ctx, _NEW_COLOR); COPY_4V(ctx->Color.ClearColor, tmp); if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) { /* it's OK to call glClearColor in CI mode but it should be a NOP */ (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor); }}/** * Clear buffers. * * \param mask bit-mask indicating the buffers to be cleared. * * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, * etc. If the rasterization mode is set to GL_RENDER then requests the driver * to clear the buffers, via the dd_function_table::Clear callback. */ void GLAPIENTRY_mesa_Clear( GLbitfield mask ){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 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 (ctx->NewState) { _mesa_update_state( ctx ); /* update _Xmin, etc */ } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glClear(incomplete framebuffer)"); return; } if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) return; if (ctx->RenderMode == GL_RENDER) { GLbitfield bufferMask; /* don't clear depth buffer if depth writing disabled */ if (!ctx->Depth.Mask) mask &= ~GL_DEPTH_BUFFER_BIT; /* Build the bitmask to send to device driver's Clear function. * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the * BUFFER_BIT_COLORn flags. */ bufferMask = 0; if (mask & GL_COLOR_BUFFER_BIT) { GLuint i; for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]); } } if ((mask & GL_DEPTH_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveDepthBuffer) { bufferMask |= BUFFER_BIT_DEPTH; } if ((mask & GL_STENCIL_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveStencilBuffer) { bufferMask |= BUFFER_BIT_STENCIL; } if ((mask & GL_ACCUM_BUFFER_BIT) && ctx->DrawBuffer->Visual.haveAccumBuffer) { bufferMask |= BUFFER_BIT_ACCUM; } ASSERT(ctx->Driver.Clear); ctx->Driver.Clear(ctx, bufferMask); }}/** * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are * available to the rendering context (for drawing or reading). * This depends on the type of framebuffer. For window system framebuffers * we look at the framebuffer's visual. But for user-create framebuffers we * look at the number of supported color attachments. * \param fb the framebuffer to draw to, or read from * \return bitmask of BUFFER_BIT_* flags */static GLbitfieldsupported_buffer_bitmask(const GLcontext *ctx, const struct gl_framebuffer *fb){ GLbitfield mask = 0x0; if (fb->Name > 0) { /* A user-created renderbuffer */ GLuint i; ASSERT(ctx->Extensions.EXT_framebuffer_object); for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { mask |= (BUFFER_BIT_COLOR0 << i); } } else { /* A window system framebuffer */ GLint i; mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ if (fb->Visual.stereoMode) { mask |= BUFFER_BIT_FRONT_RIGHT; if (fb->Visual.doubleBufferMode) { mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; } } else if (fb->Visual.doubleBufferMode) { mask |= BUFFER_BIT_BACK_LEFT; } for (i = 0; i < fb->Visual.numAuxBuffers; i++) { mask |= (BUFFER_BIT_AUX0 << i); } } return mask;}/** * Helper routine used by glDrawBuffer and glDrawBuffersARB. * Given a GLenum naming one or more color buffers (such as * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. */static GLbitfielddraw_buffer_enum_to_bitmask(GLenum buffer){ switch (buffer) { case GL_NONE: return 0; case GL_FRONT: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; case GL_BACK: return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; case GL_RIGHT: return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; case GL_FRONT_RIGHT: return BUFFER_BIT_FRONT_RIGHT; case GL_BACK_RIGHT: return BUFFER_BIT_BACK_RIGHT; case GL_BACK_LEFT: return BUFFER_BIT_BACK_LEFT; case GL_FRONT_AND_BACK: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; case GL_LEFT: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; case GL_FRONT_LEFT: return BUFFER_BIT_FRONT_LEFT; case GL_AUX0: return BUFFER_BIT_AUX0; case GL_AUX1: return BUFFER_BIT_AUX1; case GL_AUX2: return BUFFER_BIT_AUX2; case GL_AUX3: return BUFFER_BIT_AUX3; case GL_COLOR_ATTACHMENT0_EXT: return BUFFER_BIT_COLOR0; case GL_COLOR_ATTACHMENT1_EXT: return BUFFER_BIT_COLOR1; case GL_COLOR_ATTACHMENT2_EXT: return BUFFER_BIT_COLOR2; case GL_COLOR_ATTACHMENT3_EXT: return BUFFER_BIT_COLOR3; case GL_COLOR_ATTACHMENT4_EXT: return BUFFER_BIT_COLOR4; case GL_COLOR_ATTACHMENT5_EXT: return BUFFER_BIT_COLOR5; case GL_COLOR_ATTACHMENT6_EXT: return BUFFER_BIT_COLOR6; case GL_COLOR_ATTACHMENT7_EXT: return BUFFER_BIT_COLOR7; default: /* error */ return BAD_MASK; }}/** * Helper routine used by glReadBuffer. * Given a GLenum naming a color buffer, return the index of the corresponding * renderbuffer (a BUFFER_* value). * return -1 for an invalid buffer. */static GLintread_buffer_enum_to_index(GLenum buffer){ switch (buffer) { case GL_FRONT: return BUFFER_FRONT_LEFT; case GL_BACK: return BUFFER_BACK_LEFT; case GL_RIGHT: return BUFFER_FRONT_RIGHT; case GL_FRONT_RIGHT: return BUFFER_FRONT_RIGHT; case GL_BACK_RIGHT: return BUFFER_BACK_RIGHT; case GL_BACK_LEFT: return BUFFER_BACK_LEFT; case GL_LEFT: return BUFFER_FRONT_LEFT; case GL_FRONT_LEFT: return BUFFER_FRONT_LEFT; case GL_AUX0: return BUFFER_AUX0; case GL_AUX1: return BUFFER_AUX1; case GL_AUX2: return BUFFER_AUX2; case GL_AUX3: return BUFFER_AUX3; case GL_COLOR_ATTACHMENT0_EXT: return BUFFER_COLOR0; case GL_COLOR_ATTACHMENT1_EXT: return BUFFER_COLOR1; case GL_COLOR_ATTACHMENT2_EXT: return BUFFER_COLOR2; case GL_COLOR_ATTACHMENT3_EXT: return BUFFER_COLOR3; case GL_COLOR_ATTACHMENT4_EXT: return BUFFER_COLOR4; case GL_COLOR_ATTACHMENT5_EXT: return BUFFER_COLOR5; case GL_COLOR_ATTACHMENT6_EXT: return BUFFER_COLOR6; case GL_COLOR_ATTACHMENT7_EXT: return BUFFER_COLOR7; default: /* error */ return -1; }}/** * Called by glDrawBuffer(). * Specify which renderbuffer(s) to draw into for the first color output. * <buffer> can name zero, one, two or four renderbuffers! * \sa _mesa_DrawBuffersARB * * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. * * Note that the behaviour of this function depends on whether the * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or * a user-created framebuffer object (Name!=0). * In the former case, we update the per-context ctx->Color.DrawBuffer * state var _and_ the FB's ColorDrawBuffer state. * In the later case, we update the FB's ColorDrawBuffer state only. * * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the * new FB is a window system FB, we need to re-update the FB's * ColorDrawBuffer state to match the context. This is handled in * _mesa_update_framebuffer(). * * See the GL_EXT_framebuffer_object spec for more info. */void GLAPIENTRY_mesa_DrawBuffer(GLenum buffer){ GLbitfield destMask; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ if (MESA_VERBOSE & VERBOSE_API) { _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); } if (buffer == GL_NONE) { destMask = 0x0; } else { const GLbitfield supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); destMask = draw_buffer_enum_to_bitmask(buffer); if (destMask == BAD_MASK) { /* totally bogus buffer */ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)"); return; } destMask &= supportedMask; if (destMask == 0x0) { /* none of the named color buffers exist! */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)"); return; } } /* if we get here, there's no error so set new state */ _mesa_drawbuffers(ctx, 1, &buffer, &destMask); /* * Call device driver function. */ if (ctx->Driver.DrawBuffers) ctx->Driver.DrawBuffers(ctx, 1, &buffer); else if (ctx->Driver.DrawBuffer) ctx->Driver.DrawBuffer(ctx, buffer);}/** * Called by glDrawBuffersARB; specifies the destination color renderbuffers * for N fragment program color outputs.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -