📄 framebuffer.c
字号:
/* 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 updates * the given framebuffer's Visual from the current renderbuffer bindings. * This is only intended for user-created framebuffers. * * Also note: ctx->DrawBuffer->Visual.depthBits might not equal * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. * The former one is used to convert floating point depth values into * integer Z values. */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; /* assume this */ /* 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; } 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) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); set_depth_renderbuffer(fb, wrapper); ASSERT(fb->_DepthBuffer->Wrapped == depthRb); } } else { /* depthRb may be null */ set_depth_renderbuffer(fb, 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) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); set_stencil_renderbuffer(fb, wrapper); ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); } } else { /* stencilRb may be null */ set_stencil_renderbuffer(fb, stencilRb); }}/** * Update the 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; /* * Fragment programs can write to multiple colorbuffers with * the GL_ARB_draw_buffers extension. */ for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) { GLbitfield bufferMask = fb->_ColorDrawBufferMask[output]; GLuint count = 0; GLuint i; /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK) * can specify writing to two or four color buffers (for example). */ for (i = 0; bufferMask && i < BUFFER_COUNT; i++) { const GLuint bufferBit = 1 << i; if (bufferBit & bufferMask) { struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; if (rb) { fb->_ColorDrawBuffers[output][count] = rb; count++; } else { /*_mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");*/ } bufferMask &= ~bufferBit; } } fb->_NumColorDrawBuffers[output] = count; }}/** * Update the 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){ if (fb->_ColorReadBufferIndex == -1) { fb->_ColorReadBuffer = NULL; /* legal! */ } else { ASSERT(fb->_ColorReadBufferIndex >= 0); ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); fb->_ColorReadBuffer = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; }}/** * Update state related to the current draw/read framebuffers. * Specifically, update these framebuffer fields: * _ColorDrawBuffers * _NumColorDrawBuffers * _ColorReadBuffer * _DepthBuffer * _StencilBuffer * If the current framebuffer is user-created, make sure it's complete. * The following functions can effect this state: glReadBuffer, * glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, * glRenderbufferStorageEXT. */void_mesa_update_framebuffer(GLcontext *ctx){ struct gl_framebuffer *fb = ctx->DrawBuffer; /* Completeness only matters for user-created framebuffers */ if (fb->Name != 0) { _mesa_test_framebuffer_completeness(ctx, fb); _mesa_update_framebuffer_visual(fb); } 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);}/** * 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 + -