📄 buffers.c
字号:
}
/* if we get here, there's no error so set new state */
_mesa_drawbuffers(ctx, 1, &buffer, &destMask);
}
/**
* Called by glDrawBuffersARB; specifies the destination color buffers
* for N fragment program color outputs.
*
* XXX This function is called by _mesa_PopAttrib() and we need to do
* some more work to deal with the current framebuffer binding state!
*/
void GLAPIENTRY
_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
{
GLint output;
GLuint usedBufferMask, supportedMask;
GLuint bufferID;
GLuint destMask[MAX_DRAW_BUFFERS];
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (!ctx->Extensions.ARB_draw_buffers) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB");
return;
}
if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
_mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
return;
}
bufferID = ctx->DrawBuffer->Name;
supportedMask = supported_buffer_bitmask(ctx, bufferID);
usedBufferMask = 0x0;
/* complicated error checking... */
for (output = 0; output < n; output++) {
if (buffers[output] == GL_NONE) {
destMask[output] = 0x0;
}
else {
destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
if (destMask[output] == BAD_MASK
|| _mesa_bitcount(destMask[output]) > 1) {
_mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
return;
}
destMask[output] &= supportedMask;
if (destMask[output] == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glDrawBuffersARB(unsupported buffer)");
return;
}
if (destMask[output] & usedBufferMask) {
/* can't specify a dest buffer more than once! */
_mesa_error(ctx, GL_INVALID_OPERATION,
"glDrawBuffersARB(duplicated buffer)");
return;
}
/* update bitmask */
usedBufferMask |= destMask[output];
}
}
/* OK, if we get here, there were no errors so set the new state */
_mesa_drawbuffers(ctx, n, buffers, destMask);
}
/**
* Set color output state. Traditionally, there was only one color
* output, but fragment programs can now have several distinct color
* outputs (see GL_ARB_draw_buffers). This function sets the state
* for one such color output.
*/
static void
set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, GLuint destMask)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
ASSERT(output < ctx->Const.MaxDrawBuffers);
fb->ColorDrawBuffer[output] = buffer;
fb->_ColorDrawBufferMask[output] = destMask;
if (fb->Name == 0) {
/* Set traditional state var */
ctx->Color.DrawBuffer[output] = buffer;
}
/* not really needed, will be set later */
fb->_NumColorDrawBuffers[output] = 0;
}
/**
* Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and
* _mesa_PopAttrib to set drawbuffer state.
*/
void
_mesa_drawbuffers(GLcontext *ctx, GLsizei n, const GLenum *buffers,
const GLuint *destMask)
{
GLuint mask[MAX_DRAW_BUFFERS];
GLint output;
if (!destMask) {
/* compute destMask values now */
const GLuint bufferID = ctx->DrawBuffer->Name;
const GLuint supportedMask = supported_buffer_bitmask(ctx, bufferID);
for (output = 0; output < n; output++) {
mask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
ASSERT(mask[output] != BAD_MASK);
mask[output] &= supportedMask;
}
destMask = mask;
}
for (output = 0; output < n; output++) {
set_color_output(ctx, output, buffers[output], destMask[output]);
}
/* set remaining color outputs to NONE */
for (output = n; output < ctx->Const.MaxDrawBuffers; output++) {
set_color_output(ctx, output, GL_NONE, 0x0);
}
ctx->NewState |= _NEW_COLOR;
/*
* Call device driver function.
*/
if (ctx->Driver.DrawBuffers)
ctx->Driver.DrawBuffers(ctx, n, buffers);
else if (ctx->Driver.DrawBuffer)
ctx->Driver.DrawBuffer(ctx, buffers[0]);
}
/**
* Set the color buffer source for reading pixels.
*
* \param mode color buffer.
*
* \sa glReadBuffer().
*
*/
void GLAPIENTRY
_mesa_ReadBuffer(GLenum buffer)
{
struct gl_framebuffer *fb;
GLuint srcMask, supportedMask;
GLuint bufferID;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
fb = ctx->ReadBuffer;
bufferID = fb->Name;
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
if (bufferID > 0 && buffer == GL_NONE) {
/* legal! */
srcMask = 0x0;
}
else {
/* general case */
srcMask = read_buffer_enum_to_bitmask(buffer);
if (srcMask == BAD_MASK) {
_mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer)");
return;
}
supportedMask = supported_buffer_bitmask(ctx, bufferID);
if ((srcMask & supportedMask) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer)");
return;
}
}
if (bufferID == 0) {
ctx->Pixel.ReadBuffer = buffer;
}
fb->ColorReadBuffer = buffer;
fb->_ColorReadBufferMask = srcMask;
ctx->NewState |= _NEW_PIXEL;
/*
* Call device driver function.
*/
if (ctx->Driver.ReadBuffer)
(*ctx->Driver.ReadBuffer)(ctx, buffer);
}
#if _HAVE_FULL_GL
/**
* GL_MESA_resize_buffers extension.
*
* When this function is called, we'll ask the window system how large
* the current window is. If it's a new size, we'll call the driver's
* ResizeBuffers function. The driver will then resize its color buffers
* as needed, and maybe call the swrast's routine for reallocating
* swrast-managed depth/stencil/accum/etc buffers.
* \note This function may be called from within Mesa or called by the
* user directly (see the GL_MESA_resize_buffers extension).
*/
void GLAPIENTRY
_mesa_ResizeBuffersMESA( void )
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glResizeBuffersMESA\n");
if (ctx->DrawBuffer && ctx->DrawBuffer->Name == 0) {
GLuint newWidth, newHeight;
GLframebuffer *buffer = ctx->DrawBuffer;
/* ask device driver for size of output buffer */
ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
/* see if size of device driver's color buffer (window) has changed */
if (buffer->Width != newWidth || buffer->Height != newHeight) {
if (ctx->Driver.ResizeBuffers)
ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
}
}
if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer
&& ctx->ReadBuffer->Name == 0) {
GLuint newWidth, newHeight;
GLframebuffer *buffer = ctx->ReadBuffer;
/* ask device driver for size of read buffer */
ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
/* see if size of device driver's color buffer (window) has changed */
if (buffer->Width != newWidth || buffer->Height != newHeight) {
if (ctx->Driver.ResizeBuffers)
ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
}
}
ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
}
/*
* XXX move somewhere else someday?
*/
void GLAPIENTRY
_mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
{
GET_CURRENT_CONTEXT(ctx);
if (!ctx->Extensions.ARB_multisample) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB");
return;
}
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
ctx->Multisample.SampleCoverageInvert = invert;
ctx->NewState |= _NEW_MULTISAMPLE;
}
#endif /* _HAVE_FULL_GL */
/**
* Define the scissor box.
*
* \param x, y coordinates of the scissor box lower-left corner.
* \param width width of the scissor box.
* \param height height of the scissor box.
*
* \sa glScissor().
*
* Verifies the parameters and updates __GLcontextRec::Scissor. On a
* change flushes the vertices and notifies the driver via
* the dd_function_table::Scissor callback.
*/
void GLAPIENTRY
_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (width < 0 || height < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
return;
}
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
if (x == ctx->Scissor.X &&
y == ctx->Scissor.Y &&
width == ctx->Scissor.Width &&
height == ctx->Scissor.Height)
return;
FLUSH_VERTICES(ctx, _NEW_SCISSOR);
ctx->Scissor.X = x;
ctx->Scissor.Y = y;
ctx->Scissor.Width = width;
ctx->Scissor.Height = height;
if (ctx->Driver.Scissor)
ctx->Driver.Scissor( ctx, x, y, width, height );
}
/**********************************************************************/
/** \name Initialization */
/*@{*/
/**
* Initialize the context's scissor state.
* \param ctx the GL context.
*/
void
_mesa_init_scissor(GLcontext *ctx)
{
/* Scissor group */
ctx->Scissor.Enabled = GL_FALSE;
ctx->Scissor.X = 0;
ctx->Scissor.Y = 0;
ctx->Scissor.Width = 0;
ctx->Scissor.Height = 0;
}
/**
* Initialize the context's multisample state.
* \param ctx the GL context.
*/
void
_mesa_init_multisample(GLcontext *ctx)
{
ctx->Multisample.Enabled = GL_FALSE;
ctx->Multisample.SampleAlphaToCoverage = GL_FALSE;
ctx->Multisample.SampleAlphaToOne = GL_FALSE;
ctx->Multisample.SampleCoverage = GL_FALSE;
ctx->Multisample.SampleCoverageValue = 1.0;
ctx->Multisample.SampleCoverageInvert = GL_FALSE;
}
/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -