merge from texman branch

This commit is contained in:
Brian Paul
2006-03-26 05:22:17 +00:00
parent 4cbd16ed3f
commit ea4fe661d7
27 changed files with 981 additions and 492 deletions

View File

@@ -36,6 +36,7 @@
#include "renderbuffer.h"
#include "state.h"
#include "teximage.h"
#include "texobj.h"
#include "texstore.h"
@@ -66,8 +67,8 @@ static struct gl_renderbuffer DummyRenderbuffer;
/**
* Helper routine for getting a gl_renderbuffer.
*/
static struct gl_renderbuffer *
lookup_renderbuffer(GLcontext *ctx, GLuint id)
struct gl_renderbuffer *
_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id)
{
struct gl_renderbuffer *rb;
@@ -83,8 +84,8 @@ lookup_renderbuffer(GLcontext *ctx, GLuint id)
/**
* Helper routine for getting a gl_framebuffer.
*/
static struct gl_framebuffer *
lookup_framebuffer(GLcontext *ctx, GLuint id)
struct gl_framebuffer *
_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id)
{
struct gl_framebuffer *fb;
@@ -209,7 +210,7 @@ _mesa_set_texture_attachment(GLcontext *ctx,
att->Complete = GL_FALSE;
if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
ctx->Driver.RenderbufferTexture(ctx, fb, att);
ctx->Driver.RenderTexture(ctx, fb, att);
}
}
@@ -223,6 +224,7 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx,
struct gl_renderbuffer_attachment *att,
struct gl_renderbuffer *rb)
{
/* XXX check if re-doing same attachment, exit early */
_mesa_remove_attachment(ctx, att);
att->Type = GL_RENDERBUFFER_EXT;
att->Renderbuffer = rb;
@@ -242,6 +244,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
{
struct gl_renderbuffer_attachment *att;
_glthread_LOCK_MUTEX(fb->Mutex);
if (rb)
_glthread_LOCK_MUTEX(rb->Mutex);
att = _mesa_get_attachment(ctx, fb, attachment);
ASSERT(att);
@@ -251,6 +257,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
else {
_mesa_remove_attachment(ctx, att);
}
if (rb)
_glthread_UNLOCK_MUTEX(rb->Mutex);
_glthread_UNLOCK_MUTEX(fb->Mutex);
}
@@ -554,7 +564,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (renderbuffer) {
struct gl_renderbuffer *rb = lookup_renderbuffer(ctx, renderbuffer);
struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (rb != NULL && rb != &DummyRenderbuffer)
return GL_TRUE;
}
@@ -579,7 +589,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (renderbuffer) {
newRb = lookup_renderbuffer(ctx, renderbuffer);
newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (newRb == &DummyRenderbuffer) {
/* ID was reserved, but no real renderbuffer object made yet */
newRb = NULL;
@@ -626,7 +636,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
for (i = 0; i < n; i++) {
if (renderbuffers[i] > 0) {
struct gl_renderbuffer *rb;
rb = lookup_renderbuffer(ctx, renderbuffers[i]);
rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
if (rb) {
/* check if deleting currently bound renderbuffer object */
if (rb == ctx->CurrentRenderbuffer) {
@@ -786,15 +796,26 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
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->InternalFormat);
assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
rb->DepthBits || rb->StencilBits || rb->IndexBits);
rb->InternalFormat = internalFormat;
rb->_BaseFormat = baseFormat;
}
else {
@@ -802,6 +823,7 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
rb->Width = 0;
rb->Height = 0;
rb->InternalFormat = GL_NONE;
rb->_ActualFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
rb->RedBits =
rb->GreenBits =
@@ -884,7 +906,7 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (framebuffer) {
struct gl_framebuffer *rb = lookup_framebuffer(ctx, framebuffer);
struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
if (rb != NULL && rb != &DummyFramebuffer)
return GL_TRUE;
}
@@ -892,13 +914,28 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
}
static void
check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
{
GLuint i;
ASSERT(ctx->Driver.RenderTexture);
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = fb->Attachment + i;
struct gl_texture_object *texObj = att->Texture;
if (texObj) {
ctx->Driver.RenderTexture(ctx, fb, att);
}
}
}
/**
* Examine all the framebuffer's attachments to see if any are textures.
* If so, call ctx->Driver.FinishRenderTexture() for each texture to
* notify the device driver that the texture image may have changed.
*/
static void
check_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
{
if (ctx->Driver.FinishRenderTexture) {
GLuint i;
@@ -922,6 +959,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!ctx->Extensions.EXT_framebuffer_object) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindFramebufferEXT(unsupported)");
return;
}
switch (target) {
#if FEATURE_EXT_framebuffer_blit
case GL_DRAW_FRAMEBUFFER_EXT:
@@ -954,7 +997,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
if (framebuffer) {
/* Binding a user-created framebuffer object */
newFb = lookup_framebuffer(ctx, framebuffer);
newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
if (newFb == &DummyFramebuffer) {
/* ID was reserved, but no real framebuffer object made yet */
newFb = NULL;
@@ -968,10 +1011,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
}
_mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
}
_glthread_LOCK_MUTEX(newFb->Mutex);
if (bindReadBuf)
newFb->RefCount++;
if (bindDrawBuf)
newFb->RefCount++;
_glthread_UNLOCK_MUTEX(newFb->Mutex);
}
else {
/* Binding the window system framebuffer (which was originally set
@@ -980,12 +1025,19 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
newFb = ctx->WinSysDrawBuffer;
}
ASSERT(newFb);
ASSERT(newFb != &DummyFramebuffer);
/*
* XXX check if re-binding same buffer and skip some of this code.
*/
if (bindReadBuf) {
oldFb = ctx->ReadBuffer;
if (oldFb && oldFb->Name != 0) {
_glthread_LOCK_MUTEX(oldFb->Mutex);
oldFb->RefCount--;
_glthread_UNLOCK_MUTEX(oldFb->Mutex);
if (oldFb->RefCount == 0) {
oldFb->Delete(oldFb);
}
@@ -997,16 +1049,20 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
oldFb = ctx->DrawBuffer;
if (oldFb && oldFb->Name != 0) {
/* check if old FB had any texture attachments */
if (ctx->Driver.FinishRenderTexture) {
check_texture_render(ctx, oldFb);
}
check_end_texture_render(ctx, oldFb);
/* check if time to delete this framebuffer */
_glthread_LOCK_MUTEX(oldFb->Mutex);
oldFb->RefCount--;
if (oldFb->RefCount == 0) {
oldFb->Delete(oldFb);
}
_glthread_UNLOCK_MUTEX(oldFb->Mutex);
}
ctx->DrawBuffer = newFb;
if (newFb->Name != 0) {
/* check if newly bound framebuffer has any texture attachments */
check_begin_texture_render(ctx, newFb);
}
}
if (ctx->Driver.BindFramebuffer) {
@@ -1027,7 +1083,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
for (i = 0; i < n; i++) {
if (framebuffers[i] > 0) {
struct gl_framebuffer *fb;
fb = lookup_framebuffer(ctx, framebuffers[i]);
fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
if (fb) {
ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
@@ -1045,7 +1101,9 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
/* But the object will not be freed until it's no longer
* bound in any context.
*/
_glthread_LOCK_MUTEX(fb->Mutex);
fb->RefCount--;
_glthread_UNLOCK_MUTEX(fb->Mutex);
if (fb->RefCount == 0) {
fb->Delete(fb);
}
@@ -1134,100 +1192,134 @@ _mesa_CheckFramebufferStatusEXT(GLenum target)
/**
* Do error checking common to glFramebufferTexture1D/2D/3DEXT.
* \return GL_TRUE if any error, GL_FALSE otherwise
* Common code called by glFramebufferTexture1D/2D/3DEXT().
*/
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;
}
/**
* XXX The code in _mesa_FramebufferTexture1/2/3DEXT could be probably
* be combined into one function.
*/
void GLAPIENTRY
_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
static void
framebuffer_texture(GLuint dims, GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level, GLint zoffset)
{
struct gl_renderbuffer_attachment *att;
struct gl_texture_object *texObj = NULL;
struct gl_framebuffer *fb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (error_check_framebuffer_texture(ctx, 1, target, attachment,
textarget, texture, level))
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture%dDEXT(target)", dims);
return;
}
ASSERT(textarget == GL_TEXTURE_1D);
fb = ctx->DrawBuffer;
ASSERT(fb);
/* XXX read blit */
att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
/* check framebuffer binding */
if (fb->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferTexture%dDEXT", dims);
return;
}
if (texture) {
texObj = _mesa_lookup_texture(ctx, texture);
}
/* Check dimension-dependent things */
switch (dims) {
case 1:
if (textarget != GL_TEXTURE_1D) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(textarget)");
return;
}
if (texObj && texObj->Target != GL_TEXTURE_1D) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferTexture1DEXT(texture target mismatch)");
return;
}
break;
case 2:
if (textarget != GL_TEXTURE_2D &&
textarget != GL_TEXTURE_RECTANGLE_ARB &&
!IS_CUBE_FACE(textarget)) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture2DEXT(textarget)");
return;
}
if (texObj) {
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,
"glFramebufferTexture1DEXT(texture target mismatch)");
return;
}
}
break;
case 3:
if (textarget != GL_TEXTURE_3D) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture3DEXT(textarget)");
return;
}
if (texObj && texObj->Target != GL_TEXTURE_3D) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferTexture3DEXT(texture target mismatch)");
return;
}
{
const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
if (zoffset < 0 || zoffset >= maxSize) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture3DEXT(zoffset)");
return;
}
}
break;
default:
_mesa_problem(ctx, "Unexpected dims in error_check_framebuffer_texture");
return;
}
if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture%dDEXT(level)", dims);
return;
}
att = _mesa_get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
"glFramebufferTexture%dDEXT(attachment)", dims);
return;
}
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (texture) {
struct gl_texture_object *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;
}
_mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att,
texObj, textarget, level, 0);
_glthread_LOCK_MUTEX(fb->Mutex);
if (texObj) {
_mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
level, zoffset);
}
else {
_mesa_remove_attachment(ctx, att);
}
_glthread_UNLOCK_MUTEX(fb->Mutex);
}
void GLAPIENTRY
_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
const GLint zoffset = 0;
framebuffer_texture(1, target, attachment, textarget, texture,
level, zoffset);
}
@@ -1235,51 +1327,9 @@ void GLAPIENTRY
_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
struct gl_renderbuffer_attachment *att;
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 = _mesa_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) {
struct gl_texture_object *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;
}
_mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att,
texObj, textarget, level, 0);
}
else {
_mesa_remove_attachment(ctx, att);
}
const GLint zoffset = 0;
framebuffer_texture(2, target, attachment, textarget, texture,
level, zoffset);
}
@@ -1288,54 +1338,12 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level, GLint zoffset)
{
struct gl_renderbuffer_attachment *att;
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 = _mesa_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);
struct gl_texture_object *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;
}
_mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att,
texObj, textarget, level,zoffset);
}
else {
_mesa_remove_attachment(ctx, att);
}
framebuffer_texture(3, target, attachment, textarget, texture,
level, zoffset);
}
void GLAPIENTRY
_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
GLenum renderbufferTarget,
@@ -1396,7 +1404,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
}
if (renderbuffer) {
rb = lookup_renderbuffer(ctx, renderbuffer);
rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferRenderbufferEXT(renderbuffer)");