📄 framebuffer.c
字号:
_mesa_bzero(&fb->Visual, sizeof(fb->Visual)); fb->Visual.rgbMode = GL_TRUE; /* assume this */#if 0 /* this _might_ be needed */ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { /* leave visual fields zero'd */ return; }#endif /* 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->RedBits; fb->Visual.greenBits = rb->GreenBits; fb->Visual.blueBits = rb->BlueBits; fb->Visual.alphaBits = rb->AlphaBits; fb->Visual.rgbBits = fb->Visual.redBits + fb->Visual.greenBits + fb->Visual.blueBits; fb->Visual.floatMode = GL_FALSE; break; } else if (rb->_BaseFormat == GL_COLOR_INDEX) { fb->Visual.indexBits = rb->IndexBits; 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->DepthBits; } if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { fb->Visual.haveStencilBuffer = GL_TRUE; fb->Visual.stencilBits = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits; } if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { fb->Visual.haveAccumBuffer = GL_TRUE; fb->Visual.accumRedBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->RedBits; fb->Visual.accumGreenBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->GreenBits; fb->Visual.accumBlueBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->BlueBits; fb->Visual.accumAlphaBits = fb->Attachment[BUFFER_ACCUM].Renderbuffer->AlphaBits; } compute_depth_max(fb);}/** * Update the framebuffer's _DepthBuffer field using the renderbuffer * found at the given attachment index. * * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, * create and install a depth wrapper/adaptor. * * \param fb the framebuffer whose _DepthBuffer field to update * \param attIndex indicates the renderbuffer to possibly wrap */void_mesa_update_depth_buffer(GLcontext *ctx, struct gl_framebuffer *fb, GLuint attIndex){ struct gl_renderbuffer *depthRb; /* only one possiblity for now */ ASSERT(attIndex == BUFFER_DEPTH); depthRb = fb->Attachment[attIndex].Renderbuffer; if (depthRb && depthRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ if (!fb->_DepthBuffer || fb->_DepthBuffer->Wrapped != depthRb || fb->_DepthBuffer->_BaseFormat != GL_DEPTH_COMPONENT) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); ASSERT(fb->_DepthBuffer->Wrapped == depthRb); } } else { /* depthRb may be null */ _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb); }}/** * Update the framebuffer's _StencilBuffer field using the renderbuffer * found at the given attachment index. * * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, * create and install a stencil wrapper/adaptor. * * \param fb the framebuffer whose _StencilBuffer field to update * \param attIndex indicates the renderbuffer to possibly wrap */void_mesa_update_stencil_buffer(GLcontext *ctx, struct gl_framebuffer *fb, GLuint attIndex){ struct gl_renderbuffer *stencilRb; ASSERT(attIndex == BUFFER_DEPTH || attIndex == BUFFER_STENCIL); stencilRb = fb->Attachment[attIndex].Renderbuffer; if (stencilRb && stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ if (!fb->_StencilBuffer || fb->_StencilBuffer->Wrapped != stencilRb || fb->_StencilBuffer->_BaseFormat != GL_STENCIL_INDEX) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); } } else { /* stencilRb may be null */ _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); }}/* * Example DrawBuffers scenarios: * * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to * "gl_FragColor" or program writes to the "result.color" register: * * fragment color output renderbuffer * --------------------- --------------- * color[0] Front, Back * * * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to * gl_FragData[i] or program writes to result.color[i] registers: * * fragment color output renderbuffer * --------------------- --------------- * color[0] Front * color[1] Aux0 * color[3] Aux1 * * * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to * gl_FragColor, or fixed function: * * fragment color output renderbuffer * --------------------- --------------- * color[0] Front, Aux0, Aux1 * * * In either case, the list of renderbuffers is stored in the * framebuffer->_ColorDrawBuffers[] array and * framebuffer->_NumColorDrawBuffers indicates the number of buffers. * The renderer (like swrast) has to look at the current fragment shader * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine * how to map color outputs to renderbuffers. * * Note that these two calls are equivalent (for fixed function fragment * shading anyway): * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); *//** * Update the (derived) list of color drawing renderbuffer pointers. * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers * writing colors. */static voidupdate_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb){ GLuint output; /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */ fb->_ColorDrawBuffers[0] = NULL; for (output = 0; output < fb->_NumColorDrawBuffers; output++) { GLint buf = fb->_ColorDrawBufferIndexes[output]; if (buf >= 0) { fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer; } else { fb->_ColorDrawBuffers[output] = NULL; } }}/** * Update the (derived) color read renderbuffer pointer. * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. */static voidupdate_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb){ (void) ctx; if (fb->_ColorReadBufferIndex == -1 || fb->DeletePending || fb->Width == 0 || fb->Height == 0) { fb->_ColorReadBuffer = NULL; /* legal! */ } else { ASSERT(fb->_ColorReadBufferIndex >= 0); ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); fb->_ColorReadBuffer = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; }}/** * Update a gl_framebuffer's derived state. * * Specifically, update these framebuffer fields: * _ColorDrawBuffers * _NumColorDrawBuffers * _ColorReadBuffer * _DepthBuffer * _StencilBuffer * * If the framebuffer is user-created, make sure it's complete. * * The following functions (at least) can effect framebuffer state: * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, * glRenderbufferStorageEXT. */static voidupdate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb){ if (fb->Name == 0) { /* This is a window-system framebuffer */ /* Need to update the FB's GL_DRAW_BUFFER state to match the * context state (GL_READ_BUFFER too). */ if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) { } } else { /* This is a user-created framebuffer. * Completeness only matters for user-created framebuffers. */ _mesa_test_framebuffer_completeness(ctx, fb); _mesa_update_framebuffer_visual(fb); } /* Strictly speaking, we don't need to update the draw-state * if this FB is bound as ctx->ReadBuffer (and conversely, the * read-state if this FB is bound as ctx->DrawBuffer), but no * harm. */ update_color_draw_buffers(ctx, fb); update_color_read_buffer(ctx, fb); _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); compute_depth_max(fb);}/** * Update state related to the current draw/read framebuffers. */void_mesa_update_framebuffer(GLcontext *ctx){ struct gl_framebuffer *drawFb = ctx->DrawBuffer; struct gl_framebuffer *readFb = ctx->ReadBuffer; update_framebuffer(ctx, drawFb); if (readFb != drawFb) update_framebuffer(ctx, readFb);}/** * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, * glCopyTex[Sub]Image, etc. exists. * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. * \return GL_TRUE if buffer exists, GL_FALSE otherwise */GLboolean_mesa_source_buffer_exists(GLcontext *ctx, GLenum format){ const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; } switch (format) { case GL_COLOR: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RGB: case GL_BGR: case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: case GL_COLOR_INDEX: if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { return GL_FALSE; } /* XXX enable this post 6.5 release: ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 || ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0); */ break; case GL_DEPTH: case GL_DEPTH_COMPONENT: if (!att[BUFFER_DEPTH].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); break; case GL_STENCIL: case GL_STENCIL_INDEX: if (!att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); break; case GL_DEPTH_STENCIL_EXT: if (!att[BUFFER_DEPTH].Renderbuffer || !att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); break; default: _mesa_problem(ctx, "Unexpected format 0x%x in _mesa_source_buffer_exists", format); return GL_FALSE; } /* OK */ return GL_TRUE;}/** * As above, but for drawing operations. * XXX code do some code merging w/ above function. */GLboolean_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format){ const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; } switch (format) { case GL_COLOR: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RGB: case GL_BGR: case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: case GL_COLOR_INDEX: /* nothing special */ /* Could assert that colorbuffer has RedBits > 0 */ break; case GL_DEPTH: case GL_DEPTH_COMPONENT: if (!att[BUFFER_DEPTH].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); break; case GL_STENCIL: case GL_STENCIL_INDEX: if (!att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); break; case GL_DEPTH_STENCIL_EXT: if (!att[BUFFER_DEPTH].Renderbuffer || !att[BUFFER_STENCIL].Renderbuffer) { return GL_FALSE; } ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); break; default: _mesa_problem(ctx, "Unexpected format 0x%x in _mesa_source_buffer_exists", format); return GL_FALSE; } /* OK */ return GL_TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -