📄 fbobject.c
字号:
fb = lookup_framebuffer(ctx, framebuffers[i]);
if (fb) {
ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
/* check if deleting currently bound framebuffer object */
if (fb == ctx->DrawBuffer) {
/* bind default */
ASSERT(fb->RefCount >= 2);
_mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
/* remove from hash table immediately, to free the ID */
_mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
if (fb != &DummyFramebuffer) {
/* But the object will not be freed until it's no longer
* bound in any context.
*/
fb->RefCount--;
if (fb->RefCount == 0) {
fb->Delete(fb);
}
}
}
}
}
}
void GLAPIENTRY
_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
{
GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
return;
}
if (!framebuffers)
return;
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
for (i = 0; i < n; i++) {
GLuint name = first + i;
framebuffers[i] = name;
/* insert dummy placeholder into hash table */
_glthread_LOCK_MUTEX(ctx->Shared->Mutex);
_mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
}
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatusEXT(GLenum target)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
}
if (ctx->DrawBuffer->Name == 0) {
/* The window system / default framebuffer is always complete */
return GL_FRAMEBUFFER_COMPLETE_EXT;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
_mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
return ctx->DrawBuffer->_Status;
}
/**
* Do error checking common to glFramebufferTexture1D/2D/3DEXT.
* \return GL_TRUE if any error, GL_FALSE otherwise
*/
static GLboolean
error_check_framebuffer_texture(GLcontext *ctx, GLuint dims,
GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
ASSERT(dims >= 1 && dims <= 3);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture%dDEXT(target)", dims);
return GL_TRUE;
}
/* check framebuffer binding */
if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferTexture%dDEXT", dims);
return GL_TRUE;
}
/* only check textarget, level if texture ID is non-zero */
if (texture) {
if ((dims == 1 && textarget != GL_TEXTURE_1D) ||
(dims == 3 && textarget != GL_TEXTURE_3D) ||
(dims == 2 && textarget != GL_TEXTURE_2D &&
textarget != GL_TEXTURE_RECTANGLE_ARB &&
!IS_CUBE_FACE(textarget))) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture%dDEXT(textarget)", dims);
return GL_TRUE;
}
if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture%dDEXT(level)", dims);
return GL_TRUE;
}
}
return GL_FALSE;
}
void GLAPIENTRY
_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
struct gl_renderbuffer_attachment *att;
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (error_check_framebuffer_texture(ctx, 1, target, attachment,
textarget, texture, level))
return;
ASSERT(textarget == GL_TEXTURE_1D);
att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
return;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (texture) {
texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture1DEXT(texture)");
return;
}
if (texObj->Target != textarget) {
_mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */
"glFramebufferTexture1DEXT(texture target)");
return;
}
}
else {
/* remove texture attachment */
texObj = NULL;
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
}
void GLAPIENTRY
_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
struct gl_renderbuffer_attachment *att;
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (error_check_framebuffer_texture(ctx, 2, target, attachment,
textarget, texture, level))
return;
ASSERT(textarget == GL_TEXTURE_2D ||
textarget == GL_TEXTURE_RECTANGLE_ARB ||
IS_CUBE_FACE(textarget));
att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture2DEXT(attachment)");
return;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (texture) {
texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture2DEXT(texture)");
return;
}
if ((texObj->Target == GL_TEXTURE_2D && textarget != GL_TEXTURE_2D) ||
(texObj->Target == GL_TEXTURE_RECTANGLE_ARB
&& textarget != GL_TEXTURE_RECTANGLE_ARB) ||
(texObj->Target == GL_TEXTURE_CUBE_MAP
&& !IS_CUBE_FACE(textarget))) {
_mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */
"glFramebufferTexture2DEXT(texture target)");
return;
}
}
else {
/* remove texture attachment */
texObj = NULL;
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
}
void GLAPIENTRY
_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level, GLint zoffset)
{
struct gl_renderbuffer_attachment *att;
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (error_check_framebuffer_texture(ctx, 3, target, attachment,
textarget, texture, level))
return;
ASSERT(textarget == GL_TEXTURE_3D);
att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
return;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (texture) {
const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture3DEXT(texture)");
return;
}
if (texObj->Target != textarget) {
_mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */
"glFramebufferTexture3DEXT(texture target)");
return;
}
if (zoffset < 0 || zoffset >= maxSize) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture3DEXT(zoffset)");
return;
}
}
else {
/* remove texture attachment */
texObj = NULL;
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget,
level, zoffset);
}
void GLAPIENTRY
_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
GLenum renderbufferTarget,
GLuint renderbuffer)
{
struct gl_renderbuffer_attachment *att;
struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(target)");
return;
}
if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(renderbufferTarget)");
return;
}
if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
return;
}
att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(attachment)");
return;
}
if (renderbuffer) {
rb = lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferRenderbufferEXT(renderbuffer)");
return;
}
}
else {
/* remove renderbuffer attachment */
rb = NULL;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
assert(ctx->Driver.FramebufferRenderbuffer);
ctx->Driver.FramebufferRenderbuffer(ctx, att, rb);
}
void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
GLenum pname, GLint *params)
{
const struct gl_renderbuffer_attachment *att;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(target)");
return;
}
if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetFramebufferAttachmentParameterivEXT");
return;
}
att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(attachment)");
return;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
switch (pname) {
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
*params = att->Type;
return;
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
if (att->Type == GL_RENDERBUFFER_EXT) {
*params = att->Renderbuffer->Name;
}
else if (att->Type == GL_TEXTURE) {
*params = att->Texture->Name;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
if (att->Type == GL_TEXTURE) {
*params = att->TextureLevel;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
if (att->Type == GL_TEXTURE) {
*params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
if (att->Type == GL_TEXTURE) {
*params = att->Zoffset;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
}
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
return;
}
}
void GLAPIENTRY
_mesa_GenerateMipmapEXT(GLenum target)
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
switch (target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
/* OK, legal value */
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
return;
}
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
/* XXX this might not handle cube maps correctly */
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -