📄 fbobject.c
字号:
assert(fb->Name != 0); numImages = 0; fb->Width = 0; fb->Height = 0; /* Start at -2 to more easily loop over all attachment points */ for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { struct gl_renderbuffer_attachment *att; GLenum f; if (i == -2) { att = &fb->Attachment[BUFFER_DEPTH]; test_attachment_completeness(ctx, GL_DEPTH, att); if (!att->Complete) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; fbo_incomplete("depth attachment incomplete", -1); return; } } else if (i == -1) { att = &fb->Attachment[BUFFER_STENCIL]; test_attachment_completeness(ctx, GL_STENCIL, att); if (!att->Complete) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; fbo_incomplete("stencil attachment incomplete", -1); return; } } else { att = &fb->Attachment[BUFFER_COLOR0 + i]; test_attachment_completeness(ctx, GL_COLOR, att); if (!att->Complete) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; fbo_incomplete("color attachment incomplete", i); return; } } if (att->Type == GL_TEXTURE) { const struct gl_texture_image *texImg = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; w = texImg->Width; h = texImg->Height; f = texImg->_BaseFormat; numImages++; if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT && f != GL_DEPTH_STENCIL_EXT) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; fbo_incomplete("texture attachment incomplete", -1); return; } } else if (att->Type == GL_RENDERBUFFER_EXT) { w = att->Renderbuffer->Width; h = att->Renderbuffer->Height; f = att->Renderbuffer->InternalFormat; numImages++; } else { assert(att->Type == GL_NONE); continue; } if (numImages == 1) { /* set required width, height and format */ width = w; height = h; if (i >= 0) intFormat = f; } else { /* check that width, height, format are same */ if (w != width || h != height) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; fbo_incomplete("width or height mismatch", -1); return; } if (intFormat != GL_NONE && f != intFormat) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; fbo_incomplete("format mismatch", -1); return; } } } /* Check that all DrawBuffers are present */ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { if (fb->ColorDrawBuffer[i] != GL_NONE) { const struct gl_renderbuffer_attachment *att = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[i]); assert(att); if (att->Type == GL_NONE) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; fbo_incomplete("missing drawbuffer", i); return; } } } /* Check that the ReadBuffer is present */ if (fb->ColorReadBuffer != GL_NONE) { const struct gl_renderbuffer_attachment *att = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); assert(att); if (att->Type == GL_NONE) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; fbo_incomplete("missing readbuffer", -1); return; } } /* Check if any renderbuffer is attached more than once. * Note that there's one exception: a GL_DEPTH_STENCIL renderbuffer can be * bound to both the stencil and depth attachment points at the same time. */ for (i = 0; i < BUFFER_COUNT - 1; i++) { struct gl_renderbuffer *rb_i = fb->Attachment[i].Renderbuffer; if (rb_i) { GLint j; for (j = i + 1; j < BUFFER_COUNT; j++) { struct gl_renderbuffer *rb_j = fb->Attachment[j].Renderbuffer; if (rb_i == rb_j && rb_i->_BaseFormat != GL_DEPTH_STENCIL_EXT) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT; fbo_incomplete("multiply bound renderbuffer", -1); return; } } } } if (numImages == 0) { fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; fbo_incomplete("no attachments", -1); return; } /* * If we get here, the framebuffer is complete! */ fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; fb->Width = w; fb->Height = h;}GLboolean GLAPIENTRY_mesa_IsRenderbufferEXT(GLuint renderbuffer){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (renderbuffer) { struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (rb != NULL && rb != &DummyRenderbuffer) return GL_TRUE; } return GL_FALSE;}void GLAPIENTRY_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer){ struct gl_renderbuffer *newRb, *oldRb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (renderbuffer) { newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (newRb == &DummyRenderbuffer) { /* ID was reserved, but no real renderbuffer object made yet */ newRb = NULL; } if (!newRb) { /* create new renderbuffer object */ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); if (!newRb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); return; } ASSERT(newRb->AllocStorage); _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); } newRb->RefCount++; } else { newRb = NULL; } oldRb = ctx->CurrentRenderbuffer; if (oldRb) { oldRb->RefCount--; if (oldRb->RefCount == 0) { oldRb->Delete(oldRb); } } ASSERT(newRb != &DummyRenderbuffer); ctx->CurrentRenderbuffer = newRb;}void GLAPIENTRY_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers){ GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_BUFFERS); for (i = 0; i < n; i++) { if (renderbuffers[i] > 0) { struct gl_renderbuffer *rb; rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); if (rb) { /* check if deleting currently bound renderbuffer object */ if (rb == ctx->CurrentRenderbuffer) { /* bind default */ ASSERT(rb->RefCount >= 2); _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } /* remove from hash table immediately, to free the ID */ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); if (rb != &DummyRenderbuffer) { /* But the object will not be freed until it's no longer * bound in any context. */ rb->RefCount--; if (rb->RefCount == 0) { rb->Delete(rb); } } } } }}void GLAPIENTRY_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers){ GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); return; } if (!renderbuffers) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); for (i = 0; i < n; i++) { GLuint name = first + i; renderbuffers[i] = name; /* insert dummy placeholder into hash table */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }}/** * Given an internal format token for a render buffer, return the * corresponding base format. * This is very similar to _mesa_base_tex_format() but the set of valid * internal formats is somewhat different. * * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT * GL_DEPTH_STENCIL_EXT or zero if error. */GLenum_mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat){ switch (internalFormat) { case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: return GL_RGB; case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: return GL_RGBA; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: return GL_STENCIL_INDEX; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: return GL_DEPTH_COMPONENT; case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: if (ctx->Extensions.EXT_packed_depth_stencil) return GL_DEPTH_STENCIL_EXT; else return 0; /* XXX add floating point formats eventually */ default: return 0; }}void GLAPIENTRY_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height){ struct gl_renderbuffer *rb; GLenum baseFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)"); return; } baseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (baseFormat == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(internalFormat)"); return; } if (width < 1 || width > ctx->Const.MaxRenderbufferSize) { _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(width)"); return; } if (height < 1 || height > ctx->Const.MaxRenderbufferSize) { _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(height)"); return; } rb = ctx->CurrentRenderbuffer; if (!rb) { _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferStorageEXT"); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (rb->InternalFormat == internalFormat && rb->Width == width && rb->Height == height) { /* no change in allocation needed */ return; } /* These MUST get set by the AllocStorage func */ rb->_ActualFormat = 0; rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = rb->IndexBits = rb->DepthBits = rb->StencilBits = 0; /* Now allocate the storage */ ASSERT(rb->AllocStorage); if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { /* No error - check/set fields now */ assert(rb->_ActualFormat); assert(rb->Width == width); assert(rb->Height == height); assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits || rb->DepthBits || rb->StencilBits || rb->IndexBits); rb->InternalFormat = internalFormat; rb->_BaseFormat = baseFormat; } else { /* Probably ran out of memory - clear the fields */ rb->Width = 0; rb->Height = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -