📄 framebuffer.c
字号:
rb->RefCount--;
if (rb->RefCount == 0) {
rb->Delete(rb);
}
}
att->Type = GL_NONE;
att->Renderbuffer = NULL;
}
}
/**
* Resize the given framebuffer's renderbuffers to the new width and height.
* This should only be used for window-system framebuffers, not
* user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
* This will typically be called via ctx->Driver.ResizeBuffers()
*/
void
_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint width, GLuint height)
{
GLuint i;
/* For window system framebuffers, Name is zero */
assert(fb->Name == 0);
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {
struct gl_renderbuffer *rb = att->Renderbuffer;
/* only resize if size is changing */
if (rb->Width != width || rb->Height != height) {
if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
rb->Width = width;
rb->Height = height;
}
else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
}
}
}
}
fb->Width = width;
fb->Height = height;
/* to update scissor / window bounds */
ctx->NewState |= _NEW_BUFFERS;
}
/**
* Examine all the framebuffer's renderbuffers to update the Width/Height
* fields of the framebuffer. If we have renderbuffers with different
* sizes, set the framebuffer's width and height to zero.
* Note: this is only intended for user-created framebuffers, not
* window-system framebuffes.
*/
static void
update_framebuffer_size(struct gl_framebuffer *fb)
{
GLboolean haveSize = GL_FALSE;
GLuint i;
/* user-created framebuffers only */
assert(fb->Name);
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
const struct gl_renderbuffer *rb = att->Renderbuffer;
if (rb) {
if (haveSize) {
if (rb->Width != fb->Width && rb->Height != fb->Height) {
/* size mismatch! */
fb->Width = 0;
fb->Height = 0;
return;
}
}
else {
fb->Width = rb->Width;
fb->Height = rb->Height;
haveSize = GL_TRUE;
}
}
}
}
/**
* Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
* These values are computed from the buffer's width and height and
* the scissor box, if it's enabled.
* \param ctx the GL context.
*/
void
_mesa_update_draw_buffer_bounds(GLcontext *ctx)
{
struct gl_framebuffer *buffer = ctx->DrawBuffer;
if (buffer->Name) {
/* user-created framebuffer size depends on the renderbuffers */
update_framebuffer_size(buffer);
}
buffer->_Xmin = 0;
buffer->_Ymin = 0;
buffer->_Xmax = buffer->Width;
buffer->_Ymax = buffer->Height;
if (ctx->Scissor.Enabled) {
if (ctx->Scissor.X > buffer->_Xmin) {
buffer->_Xmin = ctx->Scissor.X;
}
if (ctx->Scissor.Y > buffer->_Ymin) {
buffer->_Ymin = ctx->Scissor.Y;
}
if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
}
if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
}
/* finally, check for empty region */
if (buffer->_Xmin > buffer->_Xmax) {
buffer->_Xmin = buffer->_Xmax;
}
if (buffer->_Ymin > buffer->_Ymax) {
buffer->_Ymin = buffer->_Ymax;
}
}
ASSERT(buffer->_Xmin <= buffer->_Xmax);
ASSERT(buffer->_Ymin <= buffer->_Ymax);
}
/**
* The glGet queries of the framebuffer red/green/blue size, stencil size,
* etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can
* change depending on the renderbuffer bindings. This function update's
* the given framebuffer's Visual from the current renderbuffer bindings.
* This is only intended for user-created framebuffers.
*/
void
_mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
{
GLuint i;
assert(fb->Name != 0);
_mesa_bzero(&fb->Visual, sizeof(fb->Visual));
fb->Visual.rgbMode = GL_TRUE;
/* find first RGB or CI renderbuffer */
for (i = 0; i < BUFFER_COUNT; i++) {
if (fb->Attachment[i].Renderbuffer) {
const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) {
fb->Visual.redBits = rb->ComponentSizes[0];
fb->Visual.greenBits = rb->ComponentSizes[1];
fb->Visual.blueBits = rb->ComponentSizes[2];
fb->Visual.alphaBits = rb->ComponentSizes[3];
fb->Visual.floatMode = GL_FALSE;
break;
}
else if (rb->_BaseFormat == GL_COLOR_INDEX) {
fb->Visual.indexBits = rb->ComponentSizes[0];
fb->Visual.rgbMode = GL_FALSE;
break;
}
}
}
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
fb->Visual.haveDepthBuffer = GL_TRUE;
fb->Visual.depthBits
= fb->Attachment[BUFFER_DEPTH].Renderbuffer->ComponentSizes[0];
}
if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
fb->Visual.haveStencilBuffer = GL_TRUE;
fb->Visual.stencilBits
= fb->Attachment[BUFFER_STENCIL].Renderbuffer->ComponentSizes[0];
}
compute_depth_max(fb);
}
/**
* Given a framebuffer and a buffer bit (like BUFFER_BIT_FRONT_LEFT), return
* the corresponding renderbuffer.
*/
static struct gl_renderbuffer *
get_renderbuffer(struct gl_framebuffer *fb, GLuint bufferBit)
{
GLuint index;
for (index = 0; index < BUFFER_COUNT; index++) {
if ((1 << index) == bufferBit) {
return fb->Attachment[index].Renderbuffer;
}
}
_mesa_problem(NULL, "Bad bufferBit in get_renderbuffer");
return NULL;
}
/**
* Update state related to the current draw/read framebuffers.
* If the current framebuffer is user-created, make sure it's complete.
*/
void
_mesa_update_framebuffer(GLcontext *ctx)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
GLuint output;
/* Completeness only matters for user-created framebuffers */
if (fb->Name != 0) {
_mesa_test_framebuffer_completeness(ctx, fb);
_mesa_update_framebuffer_visual(fb);
}
/*
* Update the list of drawing renderbuffer pointers.
* Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
* writing colors. We have a loop because glDrawBuffer(GL_FRONT_AND_BACK)
* can specify writing to two or four color buffers.
*/
for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) {
GLuint bufferMask = fb->_ColorDrawBufferMask[output];
GLuint count = 0;
GLuint bufferBit;
/* for each bit that's set in the bufferMask... */
for (bufferBit = 1; bufferMask; bufferBit <<= 1) {
if (bufferBit & bufferMask) {
struct gl_renderbuffer *rb = get_renderbuffer(fb, bufferBit);
if (rb) {
fb->_ColorDrawBuffers[output][count] = rb;
fb->_ColorDrawBit[output][count] = bufferBit;
count++;
}
else {
/*_mesa_warning(ctx, "DrawBuffer names a missing buffer!");*/
}
bufferMask &= ~bufferBit;
}
}
fb->_NumColorDrawBuffers[output] = count;
}
/*
* Update the read renderbuffer pointer.
* Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
*/
if (fb->_ColorReadBufferMask == 0x0)
fb->_ColorReadBuffer = NULL; /* legal! */
else
fb->_ColorReadBuffer = get_renderbuffer(fb, fb->_ColorReadBufferMask);
compute_depth_max(fb);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -