From ea4fe661d7f3a95d9db17e1475076f1badf8e1a6 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sun, 26 Mar 2006 05:22:17 +0000 Subject: merge from texman branch --- src/mesa/drivers/common/driverfuncs.c | 3 +- src/mesa/drivers/dri/Makefile.template | 2 +- src/mesa/drivers/dri/common/dri_util.c | 2 +- src/mesa/drivers/dri/common/drirenderbuffer.c | 4 +- src/mesa/main/dd.h | 10 +- src/mesa/main/depthstencil.c | 262 +++++++++++++------ src/mesa/main/depthstencil.h | 19 +- src/mesa/main/drawpix.c | 24 +- src/mesa/main/fbobject.c | 346 +++++++++++++------------- src/mesa/main/fbobject.h | 8 +- src/mesa/main/framebuffer.c | 300 +++++++++++++--------- src/mesa/main/framebuffer.h | 8 + src/mesa/main/image.c | 42 +++- src/mesa/main/image.h | 7 +- src/mesa/main/mtypes.h | 37 ++- src/mesa/main/renderbuffer.c | 144 +++++++---- src/mesa/main/renderbuffer.h | 5 + src/mesa/main/teximage.c | 9 +- src/mesa/main/texobj.c | 29 ++- src/mesa/main/texobj.h | 7 +- src/mesa/main/texrender.c | 20 +- src/mesa/main/texrender.h | 10 +- src/mesa/main/texstore.c | 41 ++- src/mesa/main/texstore.h | 4 +- src/mesa/swrast/s_context.c | 81 ++++++ src/mesa/swrast/s_context.h | 7 + src/mesa/swrast/swrast.h | 4 + 27 files changed, 962 insertions(+), 473 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 7f577b6e7f..9838e0b5ec 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -206,7 +206,8 @@ _mesa_init_driver_functions(struct dd_function_table *driver) #if FEATURE_EXT_framebuffer_object driver->NewFramebuffer = _mesa_new_framebuffer; driver->NewRenderbuffer = _mesa_new_soft_renderbuffer; - driver->RenderbufferTexture = _mesa_renderbuffer_texture; + driver->RenderTexture = _mesa_render_texture; + driver->FinishRenderTexture = _mesa_finish_render_texture; driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; #endif diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 35f7fd8a12..9e1b36252f 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME) depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) touch depend $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ - > /dev/null + >& /dev/null # Emacs tags diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 883a89c888..bad7073ed8 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -831,7 +831,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); _mesa_free(psp->pDevPriv); - (void)drmClose(psp->fd); + (void)drmCloseOnce(psp->fd); if ( psp->modes != NULL ) { (*dri_interface->destroyContextModes)( psp->modes ); } diff --git a/src/mesa/drivers/dri/common/drirenderbuffer.c b/src/mesa/drivers/dri/common/drirenderbuffer.c index 29ba1ea8a3..990f71450d 100644 --- a/src/mesa/drivers/dri/common/drirenderbuffer.c +++ b/src/mesa/drivers/dri/common/drirenderbuffer.c @@ -56,6 +56,8 @@ driNewRenderbuffer(GLenum format, GLvoid *addr, driRenderbuffer *drb; assert(format == GL_RGBA || + format == GL_RGB5 || + format == GL_RGBA8 || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32 || @@ -75,7 +77,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr, drb->Base.InternalFormat = format; - if (format == GL_RGBA) { + if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) { /* Color */ drb->Base._BaseFormat = GL_RGBA; drb->Base.DataType = GL_UNSIGNED_BYTE; diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 4b2764979d..4f1a962731 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -300,8 +300,8 @@ struct dd_function_table { */ void (*GetTexImage)( GLcontext *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels, - const struct gl_texture_object *texObj, - const struct gl_texture_image *texImage ); + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); /** * Called by glCopyTexImage1D(). @@ -807,9 +807,9 @@ struct dd_function_table { struct gl_framebuffer *fb, GLenum attachment, struct gl_renderbuffer *rb); - void (*RenderbufferTexture)(GLcontext *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att); + void (*RenderTexture)(GLcontext *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att); void (*FinishRenderTexture)(GLcontext *ctx, struct gl_renderbuffer_attachment *att); /*@}*/ diff --git a/src/mesa/main/depthstencil.c b/src/mesa/main/depthstencil.c index 90e434118e..09524bba02 100644 --- a/src/mesa/main/depthstencil.c +++ b/src/mesa/main/depthstencil.c @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -53,15 +53,15 @@ nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) /** - * Delete a depth or stencil renderbuffer. + * Delete a depth or stencil wrapper renderbuffer. */ static void delete_wrapper(struct gl_renderbuffer *rb) { struct gl_renderbuffer *dsrb = rb->Wrapped; - assert(dsrb); - assert(rb->InternalFormat == GL_DEPTH_COMPONENT24 || - rb->InternalFormat == GL_STENCIL_INDEX8_EXT); + ASSERT(dsrb); + ASSERT(rb->_ActualFormat == GL_DEPTH_COMPONENT24 || + rb->_ActualFormat == GL_STENCIL_INDEX8_EXT); /* decrement refcount on the wrapped buffer and delete it if necessary */ dsrb->RefCount--; if (dsrb->RefCount <= 0) { @@ -71,6 +71,30 @@ delete_wrapper(struct gl_renderbuffer *rb) } +/** + * Realloc storage for wrapper. + */ +static GLboolean +alloc_wrapper_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + /* just pass this on to the wrapped renderbuffer */ + struct gl_renderbuffer *dsrb = rb->Wrapped; + GLboolean retVal; + + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + + retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height); + if (retVal) { + rb->Width = width; + rb->Height = height; + } + return retVal; +} + + + + /*====================================================================== * Depth wrapper around depth/stencil renderbuffer */ @@ -84,6 +108,7 @@ get_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, GLuint *dst = (GLuint *) values; const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (!src) { dsrb->GetRow(ctx, dsrb, count, x, y, temp); @@ -102,6 +127,7 @@ get_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, GLuint temp[MAX_WIDTH], i; GLuint *dst = (GLuint *) values; ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); ASSERT(count <= MAX_WIDTH); /* don't bother trying direct access */ @@ -119,6 +145,7 @@ put_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, const GLuint *src = (const GLuint *) values; GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dst) { /* direct access */ @@ -150,6 +177,7 @@ put_mono_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, const GLuint shiftedVal = *((GLuint *) value) << 8; GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dst) { /* direct access */ @@ -181,6 +209,7 @@ put_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, struct gl_renderbuffer *dsrb = z24rb->Wrapped; const GLubyte *src = (const GLubyte *) values; ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { /* direct access */ @@ -235,7 +264,7 @@ _mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx, { struct gl_renderbuffer *z24rb; - ASSERT(dsrb->_BaseFormat == GL_DEPTH_STENCIL_EXT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); z24rb = _mesa_new_renderbuffer(ctx, 0); @@ -248,11 +277,13 @@ _mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx, z24rb->Width = dsrb->Width; z24rb->Height = dsrb->Height; z24rb->InternalFormat = GL_DEPTH_COMPONENT24_ARB; + z24rb->_ActualFormat = GL_DEPTH_COMPONENT24_ARB; z24rb->_BaseFormat = GL_DEPTH_COMPONENT; z24rb->DataType = GL_UNSIGNED_INT; z24rb->DepthBits = 24; z24rb->Data = NULL; z24rb->Delete = delete_wrapper; + z24rb->AllocStorage = alloc_wrapper_storage; z24rb->GetPointer = nop_get_pointer; z24rb->GetRow = get_row_z24; z24rb->GetValues = get_values_z24; @@ -279,6 +310,7 @@ get_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, GLubyte *dst = (GLubyte *) values; const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (!src) { dsrb->GetRow(ctx, dsrb, count, x, y, temp); @@ -297,6 +329,7 @@ get_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, GLuint temp[MAX_WIDTH], i; GLubyte *dst = (GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); ASSERT(count <= MAX_WIDTH); /* don't bother trying direct access */ @@ -314,6 +347,7 @@ put_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dst) { /* direct access */ @@ -345,6 +379,7 @@ put_mono_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, const GLubyte val = *((GLubyte *) value); GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dst) { /* direct access */ @@ -376,6 +411,7 @@ put_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, struct gl_renderbuffer *dsrb = s8rb->Wrapped; const GLubyte *src = (const GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { /* direct access */ @@ -429,7 +465,7 @@ _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb) { struct gl_renderbuffer *s8rb; - ASSERT(dsrb->_BaseFormat == GL_DEPTH_STENCIL_EXT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); s8rb = _mesa_new_renderbuffer(ctx, 0); @@ -442,11 +478,13 @@ _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb) s8rb->Width = dsrb->Width; s8rb->Height = dsrb->Height; s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT; + s8rb->_ActualFormat = GL_STENCIL_INDEX8_EXT; s8rb->_BaseFormat = GL_STENCIL_INDEX; s8rb->DataType = GL_UNSIGNED_BYTE; s8rb->StencilBits = 8; s8rb->Data = NULL; s8rb->Delete = delete_wrapper; + s8rb->AllocStorage = alloc_wrapper_storage; s8rb->GetPointer = nop_get_pointer; s8rb->GetRow = get_row_s8; s8rb->GetValues = get_values_s8; @@ -460,90 +498,158 @@ _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb) } + +/** + ** The following functions are useful for hardware drivers that only + ** implement combined depth/stencil buffers. + ** The GL_EXT_framebuffer_object extension allows indepedent depth and + ** stencil buffers to be used in any combination. + ** Therefore, we sometimes have to merge separate depth and stencil + ** renderbuffers into a single depth+stencil renderbuffer. And sometimes + ** we have to split combined depth+stencil renderbuffers into separate + ** renderbuffers. + **/ + + /** - * Merge data from a depth renderbuffer and a stencil renderbuffer into a - * combined depth/stencil renderbuffer. + * Extract stencil values from the combined depth/stencil renderbuffer, storing + * the values into a separate stencil renderbuffer. + * \param dsRb the source depth/stencil renderbuffer + * \param stencilRb the destination stencil renderbuffer + * (either 8-bit or 32-bit) */ void -_mesa_merge_depth_stencil_buffers(GLcontext *ctx, - struct gl_renderbuffer *dest, - struct gl_renderbuffer *depth, - struct gl_renderbuffer *stencil) +_mesa_extract_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb) { - GLuint depthVals[MAX_WIDTH]; - GLubyte stencilVals[MAX_WIDTH]; - GLuint combined[MAX_WIDTH]; - GLuint row, width; - - ASSERT(dest); - ASSERT(depth); - ASSERT(stencil); - - ASSERT(dest->InternalFormat == GL_DEPTH24_STENCIL8_EXT); - ASSERT(dest->DataType == GL_UNSIGNED_INT_24_8_EXT); - ASSERT(depth->InternalFormat == GL_DEPTH_COMPONENT24); - ASSERT(depth->DataType == GL_UNSIGNED_INT); - ASSERT(stencil->InternalFormat == GL_STENCIL_INDEX8_EXT); - ASSERT(stencil->DataType == GL_UNSIGNED_BYTE); - - ASSERT(dest->Width == depth->Width); - ASSERT(dest->Height == depth->Height); - ASSERT(dest->Width == stencil->Width); - ASSERT(dest->Height == stencil->Height); - - width = dest->Width; - for (row = 0; row < dest->Height; row++) { - GLuint i; - depth->GetRow(ctx, depth, width, 0, row, depthVals); - stencil->GetRow(ctx, stencil, width, 0, row, stencilVals); - for (i = 0; i < width; i++) { - combined[i] = (depthVals[i] << 8) | stencilVals[i]; + GLuint row, width, height; + + ASSERT(dsRb); + ASSERT(stencilRb); + + ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT || + stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + ASSERT(dsRb->Width == stencilRb->Width); + ASSERT(dsRb->Height == stencilRb->Height); + + width = dsRb->Width; + height = dsRb->Height; + + for (row = 0; row < height; row++) { + GLuint depthStencil[MAX_WIDTH]; + dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil); + if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { + /* 8bpp stencil */ + GLubyte stencil[MAX_WIDTH]; + GLuint i; + for (i = 0; i < width; i++) { + stencil[i] = depthStencil[i] & 0xff; + } + stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL); + } + else { + /* 32bpp stencil */ + /* the 24 depth bits will be ignored */ + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL); } - dest->PutRow(ctx, dest, width, 0, row, combined, NULL); } } /** - * Split combined depth/stencil renderbuffer data into separate depth/stencil - * buffers. + * Copy stencil values from a stencil renderbuffer into a combined + * depth/stencil renderbuffer. + * \param dsRb the destination depth/stencil renderbuffer + * \param stencilRb the source stencil buffer (either 8-bit or 32-bit) */ void -_mesa_split_depth_stencil_buffer(GLcontext *ctx, - struct gl_renderbuffer *source, - struct gl_renderbuffer *depth, - struct gl_renderbuffer *stencil) +_mesa_insert_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb) { - GLuint depthVals[MAX_WIDTH]; - GLubyte stencilVals[MAX_WIDTH]; - GLuint combined[MAX_WIDTH]; - GLuint row, width; - - ASSERT(source); - ASSERT(depth); - ASSERT(stencil); - - ASSERT(source->InternalFormat == GL_DEPTH24_STENCIL8_EXT); - ASSERT(source->DataType == GL_UNSIGNED_INT_24_8_EXT); - ASSERT(depth->InternalFormat == GL_DEPTH_COMPONENT24); - ASSERT(depth->DataType == GL_UNSIGNED_INT); - ASSERT(stencil->InternalFormat == GL_STENCIL_INDEX8_EXT); - ASSERT(stencil->DataType == GL_UNSIGNED_BYTE); - - ASSERT(source->Width == depth->Width); - ASSERT(source->Height == depth->Height); - ASSERT(source->Width == stencil->Width); - ASSERT(source->Height == stencil->Height); - - width = source->Width; - for (row = 0; row < source->Height; row++) { - GLuint i; - source->GetRow(ctx, source, width, 0, row, combined); - for (i = 0; i < width; i++) { - depthVals[i] = combined[i] >> 8; - stencilVals[i] = combined[i] & 0xff; + GLuint row, width, height; + + ASSERT(dsRb); + ASSERT(stencilRb); + + ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT || + stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + + ASSERT(dsRb->Width == stencilRb->Width); + ASSERT(dsRb->Height == stencilRb->Height); + + width = dsRb->Width; + height = dsRb->Height; + + for (row = 0; row < height; row++) { + GLuint depthStencil[MAX_WIDTH]; + + dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil); + + if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { + /* 8bpp stencil */ + GLubyte stencil[MAX_WIDTH]; + GLuint i; + stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil); + for (i = 0; i < width; i++) { + depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i]; + } + } + else { + /* 32bpp stencil buffer */ + GLuint stencil[MAX_WIDTH], i; + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil); + for (i = 0; i < width; i++) { + depthStencil[i] + = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff); + } + } + + dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL); + } +} + + +/** + * Convert the stencil buffer from 8bpp to 32bpp depth/stencil. + * \param stencilRb the stencil renderbuffer to promote + */ +void +_mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb) +{ + const GLsizei width = stencilRb->Width; + const GLsizei height = stencilRb->Height; + GLubyte *data; + GLint i, j, k; + + ASSERT(stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + ASSERT(stencilRb->Data); + + data = (GLubyte *) stencilRb->Data; + stencilRb->Data = NULL; + stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT, + width, height); + + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + + k = 0; + for (i = 0; i < height; i++) { + GLuint depthStencil[MAX_WIDTH]; + for (j = 0; j < width; j++) { + depthStencil[j] = data[k++]; } - depth->PutRow(ctx, depth, width, 0, row, depthVals, NULL); - stencil->PutRow(ctx, stencil, width, 0, row, stencilVals, NULL); + stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL); } + _mesa_free(data); + + stencilRb->_BaseFormat = GL_DEPTH_STENCIL_EXT; } diff --git a/src/mesa/main/depthstencil.h b/src/mesa/main/depthstencil.h index 76b75a0e36..3dde081f5a 100644 --- a/src/mesa/main/depthstencil.h +++ b/src/mesa/main/depthstencil.h @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -38,18 +38,19 @@ _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, extern void -_mesa_merge_depth_stencil_buffers(GLcontext *ctx, - struct gl_renderbuffer *dest, - struct gl_renderbuffer *depth, - struct gl_renderbuffer *stencil); +_mesa_extract_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); extern void -_mesa_split_depth_stencil_buffer(GLcontext *ctx, - struct gl_renderbuffer *source, - struct gl_renderbuffer *depth, - struct gl_renderbuffer *stencil); +_mesa_insert_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); +extern void +_mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb); + #endif /* DEPTHSTENCIL_H */ diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 5c4f4545ea..c82abccc41 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -149,12 +149,6 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawPixels (invalid fragment program)"); - return; - } - if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; @@ -164,6 +158,12 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, _mesa_update_state(ctx); } + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawPixels (invalid fragment program)"); + return; + } + if (error_check_format_type(ctx, format, type, GL_TRUE)) { /* found an error */ return; @@ -315,12 +315,6 @@ _mesa_Bitmap( GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBitmap (invalid fragment program)"); - return; - } - if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; @@ -334,6 +328,12 @@ _mesa_Bitmap( GLsizei width, GLsizei height, _mesa_update_state(ctx); } + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBitmap (invalid fragment program)"); + return; + } + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glBitmap(incomplete framebuffer)"); diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 53c4d27e81..ec690bdbf7 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -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,152 +1192,144 @@ _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) +static void +framebuffer_texture(GLuint dims, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint zoffset) { - ASSERT(dims >= 1 && dims <= 3); + 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 (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%dDEXT(target)", dims); - return GL_TRUE; + return; } + fb = ctx->DrawBuffer; + ASSERT(fb); + /* check framebuffer binding */ - if (ctx->DrawBuffer->Name == 0) { + if (fb->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%dDEXT", dims); - return GL_TRUE; + return; } - /* 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; - } + texObj = _mesa_lookup_texture(ctx, texture); + } - if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%dDEXT(level)", dims); - return GL_TRUE; + /* 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; } - 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) -{ - struct gl_renderbuffer_attachment *att; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (error_check_framebuffer_texture(ctx, 1, target, attachment, - textarget, texture, level)) + if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(level)", dims); return; + } - ASSERT(textarget == GL_TEXTURE_1D); - - /* XXX read blit */ - att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment); + 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_FramebufferTexture2DEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTexture1DEXT(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; + const GLint zoffset = 0; + framebuffer_texture(1, target, attachment, textarget, texture, + level, zoffset); +} - 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); - } +void GLAPIENTRY +_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + 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)"); diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index c16f628a09..301e2da449 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,6 +27,12 @@ #define FBOBJECT_H +extern struct gl_renderbuffer * +_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id); + +extern struct gl_framebuffer * +_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id); + extern struct gl_renderbuffer_attachment * _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment); diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 5cea6d1a17..55e9bbc79d 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -69,6 +69,48 @@ compute_depth_max(struct gl_framebuffer *fb) } +/** + * Set the framebuffer's _DepthBuffer field, taking care of + * reference counts, etc. + */ +static void +set_depth_renderbuffer(struct gl_framebuffer *fb, + struct gl_renderbuffer *rb) +{ + if (fb->_DepthBuffer) { + fb->_DepthBuffer->RefCount--; + if (fb->_DepthBuffer->RefCount <= 0) { + fb->_DepthBuffer->Delete(fb->_DepthBuffer); + } + } + fb->_DepthBuffer = rb; + if (rb) { + rb->RefCount++; + } +} + + +/** + * Set the framebuffer's _StencilBuffer field, taking care of + * reference counts, etc. + */ +static void +set_stencil_renderbuffer(struct gl_framebuffer *fb, + struct gl_renderbuffer *rb) +{ + if (fb->_StencilBuffer) { + fb->_StencilBuffer->RefCount--; + if (fb->_StencilBuffer->RefCount <= 0) { + fb->_StencilBuffer->Delete(fb->_StencilBuffer); + } + } + fb->_StencilBuffer = rb; + if (rb) { + rb->RefCount++; + } +} + + /** * Create and initialize a gl_framebuffer object. * This is intended for creating _window_system_ framebuffers, not generic @@ -127,6 +169,8 @@ _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual) _mesa_bzero(fb, sizeof(struct gl_framebuffer)); + _glthread_INIT_MUTEX(fb->Mutex); + /* save the visual */ fb->Visual = *visual; @@ -159,6 +203,7 @@ void _mesa_destroy_framebuffer(struct gl_framebuffer *fb) { if (fb) { + _glthread_DESTROY_MUTEX(fb->Mutex); _mesa_free_framebuffer_data(fb); _mesa_free(fb); } @@ -180,7 +225,9 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb) struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; if (att->Renderbuffer) { struct gl_renderbuffer *rb = att->Renderbuffer; + _glthread_LOCK_MUTEX(rb->Mutex); rb->RefCount--; + _glthread_UNLOCK_MUTEX(rb->Mutex); if (rb->RefCount == 0) { rb->Delete(rb); } @@ -189,22 +236,9 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb) att->Renderbuffer = NULL; } - if (fb->_DepthBuffer) { - struct gl_renderbuffer *rb = fb->_DepthBuffer; - rb->RefCount--; - if (rb->RefCount <= 0) { - rb->Delete(rb); - } - fb->_DepthBuffer = NULL; - } - if (fb->_StencilBuffer) { - struct gl_renderbuffer *rb = fb->_StencilBuffer; - rb->RefCount--; - if (rb->RefCount <= 0) { - rb->Delete(rb); - } - fb->_StencilBuffer = NULL; - } + /* unbind depth/stencil to decr ref counts */ + set_depth_renderbuffer(fb, NULL); + set_stencil_renderbuffer(fb, NULL); } @@ -224,6 +258,10 @@ _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, { GLuint i; + /* XXX I think we could check if the size is not changing + * and return early. + */ + /* For window system framebuffers, Name is zero */ assert(fb->Name == 0); @@ -233,23 +271,42 @@ _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer *rb = att->Renderbuffer; /* only resize if size is changing */ if (rb->Width != width || rb->Height != height) { + /* could just as well pass rb->_ActualFormat here */ if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { - rb->Width = width; - rb->Height = height; + ASSERT(rb->Width == width); + ASSERT(rb->Height == height); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + /* no return */ } } } } + if (fb->_DepthBuffer) { + struct gl_renderbuffer *rb = fb->_DepthBuffer; + if (rb->Width != width || rb->Height != height) { + if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + } + } + } + + if (fb->_StencilBuffer) { + struct gl_renderbuffer *rb = fb->_StencilBuffer; + if (rb->Width != width || rb->Height != height) { + if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + } + } + } + fb->Width = width; fb->Height = height; /* to update scissor / window bounds */ - if (ctx) - ctx->NewState |= _NEW_BUFFERS; + _mesa_update_draw_buffer_bounds(ctx); } @@ -400,80 +457,104 @@ _mesa_update_framebuffer_visual(struct gl_framebuffer *fb) /** - * Helper function for _mesa_update_framebuffer(). - * Set the actual depth renderbuffer for the given framebuffer. - * Take care of reference counts, etc. + * 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 */ -static void -set_depth_renderbuffer(struct gl_framebuffer *fb, - struct gl_renderbuffer *rb) +void +_mesa_update_depth_buffer(GLcontext *ctx, + struct gl_framebuffer *fb, + GLuint attIndex) { - if (fb->_DepthBuffer) { - fb->_DepthBuffer->RefCount--; - if (fb->_DepthBuffer->RefCount <= 0) { - fb->_DepthBuffer->Delete(fb->_DepthBuffer); + 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); } } - fb->_DepthBuffer = rb; - if (rb) - rb->RefCount++; + else { + /* depthRb may be null */ + set_depth_renderbuffer(fb, depthRb); + } } + /** - * \sa set_depth_renderbuffer. + * 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 */ -static void -set_stencil_renderbuffer(struct gl_framebuffer *fb, - struct gl_renderbuffer *rb) +void +_mesa_update_stencil_buffer(GLcontext *ctx, + struct gl_framebuffer *fb, + GLuint attIndex) { - if (fb->_StencilBuffer) { - fb->_StencilBuffer->RefCount--; - if (fb->_StencilBuffer->RefCount <= 0) { - fb->_StencilBuffer->Delete(fb->_StencilBuffer); + 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); } } - fb->_StencilBuffer = rb; - if (rb) - rb->RefCount++; + else { + /* stencilRb may be null */ + set_stencil_renderbuffer(fb, stencilRb); + } } /** - * 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. + * Update the list of color drawing renderbuffer pointers. + * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers + * writing colors. */ -void -_mesa_update_framebuffer(GLcontext *ctx) +static void +update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb) { - struct gl_framebuffer *fb = ctx->DrawBuffer; GLuint output; - /* Completeness only matters for user-created framebuffers */ - if (fb->Name != 0) { - _mesa_test_framebuffer_completeness(ctx, fb); - _mesa_update_framebuffer_visual(fb); - } - /* - * Update the list of color drawing renderbuffer pointers. - * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers - * writing colors. We need the inner loop here because - * glDrawBuffer(GL_FRONT_AND_BACK) can specify writing to two or four - * color buffers (for example). + * 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) { @@ -490,11 +571,16 @@ _mesa_update_framebuffer(GLcontext *ctx) } fb->_NumColorDrawBuffers[output] = count; } +} - /* - * Update the color read renderbuffer pointer. - * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. - */ + +/** + * Update the color read renderbuffer pointer. + * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. + */ +static void +update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb) +{ if (fb->_ColorReadBufferIndex == -1) { fb->_ColorReadBuffer = NULL; /* legal! */ } @@ -504,50 +590,38 @@ _mesa_update_framebuffer(GLcontext *ctx) fb->_ColorReadBuffer = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; } +} - /* - * Deal with GL_DEPTH_STENCIL renderbuffer(s) attached to the depth - * and/or stencil attachment points. If either of the DEPTH or STENCIL - * renderbuffer attachments are GL_DEPTH_STENCIL buffers, we need to set - * up depth/stencil renderbuffer wrappers. - */ - { - struct gl_renderbuffer *depthRb - = fb->Attachment[BUFFER_DEPTH].Renderbuffer; - struct gl_renderbuffer *stencilRb - = fb->Attachment[BUFFER_STENCIL].Renderbuffer; - - if (depthRb && depthRb->_BaseFormat == GL_DEPTH_STENCIL_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); - } - if (stencilRb && stencilRb->_BaseFormat == GL_DEPTH_STENCIL_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 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); } diff --git a/src/mesa/main/framebuffer.h b/src/mesa/main/framebuffer.h index 51847b07c0..1ff04085f3 100644 --- a/src/mesa/main/framebuffer.h +++ b/src/mesa/main/framebuffer.h @@ -52,6 +52,14 @@ _mesa_update_draw_buffer_bounds(GLcontext *ctx); extern void _mesa_update_framebuffer_visual(struct gl_framebuffer *fb); +extern void +_mesa_update_depth_buffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint attIndex); + +extern void +_mesa_update_stencil_buffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint attIndex); + extern void _mesa_update_framebuffer(GLcontext *ctx); diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 0a117a967b..ee44e37295 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -4312,3 +4312,43 @@ _mesa_clip_readpixels(const GLcontext *ctx, return GL_TRUE; } + +/** + * Clip the rectangle defined by (x, y, width, height) against the bounds + * specified by [xmin, xmax) and [ymin, ymax). + * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. + */ +GLboolean +_mesa_clip_to_region(GLint xmin, GLint ymin, + GLint xmax, GLint ymax, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < xmin) { + *width -= (xmin - *x); + *x = xmin; + } + + /* right clipping */ + if (*x + *width > xmax) + *width -= (*x + *width - xmax - 1); + + if (*width <= 0) + return GL_FALSE; + + /* bottom (or top) clipping */ + if (*y < ymin) { + *height -= (ymin - *y); + *y = ymin; + } + + /* top (or bottom) clipping */ + if (*y + *height > ymax) + *height -= (*y + *height - ymax - 1); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h index e31959565a..84faa03255 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -216,5 +216,10 @@ _mesa_clip_readpixels(const GLcontext *ctx, GLsizei *width, GLsizei *height, struct gl_pixelstore_attrib *pack); +extern GLboolean +_mesa_clip_to_region(GLint xmin, GLint ymin, + GLint xmax, GLint ymax, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ); #endif diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index c69b4a48b5..d2a0af1121 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -319,6 +319,28 @@ enum { #define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6) #define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7) +/** + * Mask of all the color buffer bits (but not accum). + */ +#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \ + BUFFER_BIT_BACK_LEFT | \ + BUFFER_BIT_FRONT_RIGHT | \ + BUFFER_BIT_BACK_RIGHT | \ + BUFFER_BIT_AUX0 | \ + BUFFER_BIT_AUX1 | \ + BUFFER_BIT_AUX2 | \ + BUFFER_BIT_AUX3 | \ + BUFFER_BIT_COLOR0 | \ + BUFFER_BIT_COLOR1 | \ + BUFFER_BIT_COLOR2 | \ + BUFFER_BIT_COLOR3 | \ + BUFFER_BIT_COLOR4 | \ + BUFFER_BIT_COLOR5 | \ + BUFFER_BIT_COLOR6 | \ + BUFFER_BIT_COLOR7) + + + /** * Data structure for color tables @@ -1232,6 +1254,7 @@ struct gl_texture_image GLuint Height; /**< = 2^HeightLog2 + 2*Border */ GLuint Depth; /**< = 2^DepthLog2 + 2*Border */ GLuint RowStride; /**< == Width unless IsClientData and padded */ + GLuint ImageStride; /**< Stride between images, in texels */ GLuint Width2; /**< = Width - 2*Border */ GLuint Height2; /**< = Height - 2*Border */ GLuint Depth2; /**< = Depth - 2*Border */ @@ -2024,14 +2047,17 @@ struct gl_shared_state */ struct gl_renderbuffer { + _glthread_Mutex Mutex; /**< for thread safety */ + GLuint ClassID; /**< Useful for drivers */ GLuint Name; GLint RefCount; GLuint Width, Height; - GLenum InternalFormat; /* The user-specified value */ - GLenum _BaseFormat; /* Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or */ - /* GL_STENCIL_INDEX. */ - GLenum DataType; /* Type of values passed to the Get/Put functions */ - GLubyte RedBits; /**< Bits per image component */ + GLenum InternalFormat; /**< The user-specified format */ + GLenum _ActualFormat; /**< The driver-chosen format */ + GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or + GL_STENCIL_INDEX. */ + GLenum DataType; /**< Type of values passed to the Get/Put functions */ + GLubyte RedBits; /**< Bits of red per pixel */ GLubyte GreenBits; GLubyte BlueBits; GLubyte AlphaBits; @@ -2139,6 +2165,7 @@ struct gl_renderbuffer_attachment */ struct gl_framebuffer { + _glthread_Mutex Mutex; /**< for thread safety */ GLuint Name; /* if zero, this is a window system framebuffer */ GLint RefCount; diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 1db5dce4fe..aa14bf8634 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -70,6 +70,9 @@ get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, if (!rb->Data) return NULL; ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + /* Can't assert _ActualFormat since these funcs may be used for serveral + * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc). + */ return (GLubyte *) rb->Data + y * rb->Width + x; } @@ -90,7 +93,7 @@ get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { GLubyte *dst = (GLubyte *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; dst[i] = *src; @@ -104,7 +107,7 @@ put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLubyte *src = (const GLubyte *) values; GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); if (mask) { GLuint i; for (i = 0; i < count; i++) { @@ -125,7 +128,7 @@ put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLubyte val = *((const GLubyte *) value); GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); if (mask) { GLuint i; for (i = 0; i < count; i++) { @@ -150,7 +153,7 @@ put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLubyte *src = (const GLubyte *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; @@ -167,7 +170,7 @@ put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLubyte val = *((const GLubyte *) value); GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; @@ -443,6 +446,7 @@ static void * get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) { + ASSERT(rb->_ActualFormat == GL_RGB8); /* No direct access since this buffer is RGB but caller will be * treating it as if it were RGBA. */ @@ -457,6 +461,7 @@ get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x); GLubyte *dst = (GLubyte *) values; GLuint i; + ASSERT(rb->_ActualFormat == GL_RGB8); ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { dst[i * 4 + 0] = src[i * 3 + 0]; @@ -473,7 +478,8 @@ get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { GLubyte *dst = (GLubyte *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { const GLubyte *src = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); @@ -493,7 +499,8 @@ put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i * 3 + 0] = src[i * 4 + 0]; @@ -512,7 +519,8 @@ put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i * 3 + 0] = src[i * 3 + 0]; @@ -532,7 +540,8 @@ put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLubyte val1 = ((const GLubyte *) value)[1]; const GLubyte val2 = ((const GLubyte *) value)[2]; GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); if (!mask && val0 == val1 && val1 == val2) { /* optimized case */ _mesa_memset(dst, val0, 3 * count); @@ -558,7 +567,8 @@ put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, /* note: incoming values are RGB+A! */ const GLubyte *src = (const GLubyte *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); @@ -580,7 +590,8 @@ put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, const GLubyte val1 = ((const GLubyte *) value)[1]; const GLubyte val2 = ((const GLubyte *) value)[2]; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGB8); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); @@ -604,6 +615,7 @@ get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, if (!rb->Data) return NULL; ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); return (GLubyte *) rb->Data + 4 * (y * rb->Width + x); } @@ -614,6 +626,7 @@ get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLbyte *src = (const GLbyte *) rb->Data + 4 * (y * rb->Width + x); ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); _mesa_memcpy(values, src, 4 * count * sizeof(GLbyte)); } @@ -625,7 +638,8 @@ get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, /* treat 4*GLubyte as 1*GLuint */ GLuint *dst = (GLuint *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); for (i = 0; i < count; i++) { const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); dst[i] = *src; @@ -640,7 +654,8 @@ put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, /* treat 4*GLubyte as 1*GLuint */ const GLuint *src = (const GLuint *) values; GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x); - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); if (mask) { GLuint i; for (i = 0; i < count; i++) { @@ -663,7 +678,8 @@ put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x); GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i * 4 + 0] = src[i * 3 + 0]; @@ -682,7 +698,8 @@ put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, /* treat 4*GLubyte as 1*GLuint */ const GLuint val = *((const GLuint *) value); GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x); - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); if (!mask && val == 0) { /* common case */ _mesa_bzero(dst, count * 4 * sizeof(GLubyte)); @@ -715,7 +732,8 @@ put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, /* treat 4*GLubyte as 1*GLuint */ const GLuint *src = (const GLuint *) values; GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); @@ -733,7 +751,8 @@ put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, /* treat 4*GLubyte as 1*GLuint */ const GLuint val = *((const GLuint *) value); GLuint i; - assert(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(rb->_ActualFormat == GL_RGBA8); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); @@ -919,9 +938,10 @@ put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, * This function also plugs in the appropriate GetPointer, Get/PutRow and * Get/PutValues functions. */ -static GLboolean -soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, - GLenum internalFormat, GLuint width, GLuint height) +GLboolean +_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) { GLuint pixelSize; @@ -943,6 +963,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, case GL_RGB10: case GL_RGB12: case GL_RGB16: + rb->_ActualFormat = GL_RGB8; rb->_BaseFormat = GL_RGB; rb->DataType = GL_UNSIGNED_BYTE; rb->GetPointer = get_pointer_ubyte3; @@ -964,6 +985,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: + rb->_ActualFormat = GL_RGBA8; rb->_BaseFormat = GL_RGBA; rb->DataType = GL_UNSIGNED_BYTE; rb->GetPointer = get_pointer_ubyte4; @@ -983,6 +1005,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: + rb->_ActualFormat = GL_RGBA16; rb->_BaseFormat = GL_RGBA; rb->DataType = GL_UNSIGNED_SHORT; rb->GetPointer = get_pointer_ushort4; @@ -1000,7 +1023,8 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = 4 * sizeof(GLushort); break; #if 00 - case ALPHA8: + case GL_ALPHA8: + rb->_ActualFormat = GL_ALPHA8; rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */ rb->DataType = GL_UNSIGNED_BYTE; rb->GetPointer = get_pointer_alpha8; @@ -1022,6 +1046,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: + rb->_ActualFormat = GL_STENCIL_INDEX8_EXT; rb->_BaseFormat = GL_STENCIL_INDEX; rb->DataType = GL_UNSIGNED_BYTE; rb->GetPointer = get_pointer_ubyte; @@ -1036,6 +1061,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = sizeof(GLubyte); break; case GL_STENCIL_INDEX16_EXT: + rb->_ActualFormat = GL_STENCIL_INDEX16_EXT; rb->_BaseFormat = GL_STENCIL_INDEX; rb->DataType = GL_UNSIGNED_SHORT; rb->GetPointer = get_pointer_ushort; @@ -1051,6 +1077,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: + rb->_ActualFormat = GL_DEPTH_COMPONENT16; rb->_BaseFormat = GL_DEPTH_COMPONENT; rb->DataType = GL_UNSIGNED_SHORT; rb->GetPointer = get_pointer_ushort; @@ -1076,14 +1103,19 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, rb->PutMonoRow = put_mono_row_uint; rb->PutValues = put_values_uint; rb->PutMonoValues = put_mono_values_uint; - if (internalFormat == GL_DEPTH_COMPONENT24) + if (internalFormat == GL_DEPTH_COMPONENT24) { + rb->_ActualFormat = GL_DEPTH_COMPONENT24; rb->DepthBits = 24; - else + } + else { + rb->_ActualFormat = GL_DEPTH_COMPONENT32; rb->DepthBits = 32; + } pixelSize = sizeof(GLuint); break; case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: + rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; rb->_BaseFormat = GL_DEPTH_STENCIL_EXT; rb->DataType = GL_UNSIGNED_INT_24_8_EXT; rb->GetPointer = get_pointer_uint; @@ -1099,6 +1131,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = sizeof(GLuint); break; case GL_COLOR_INDEX8_EXT: + rb->_ActualFormat = GL_COLOR_INDEX8_EXT; rb->_BaseFormat = GL_COLOR_INDEX; rb->DataType = GL_UNSIGNED_BYTE; rb->GetPointer = get_pointer_ubyte; @@ -1113,6 +1146,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = sizeof(GLubyte); break; case GL_COLOR_INDEX16_EXT: + rb->_ActualFormat = GL_COLOR_INDEX16_EXT; rb->_BaseFormat = GL_COLOR_INDEX; rb->DataType = GL_UNSIGNED_SHORT; rb->GetPointer = get_pointer_ushort; @@ -1127,6 +1161,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = sizeof(GLushort); break; case COLOR_INDEX32: + rb->_ActualFormat = COLOR_INDEX32; rb->_BaseFormat = GL_COLOR_INDEX; rb->DataType = GL_UNSIGNED_INT; rb->GetPointer = get_pointer_uint; @@ -1141,7 +1176,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, pixelSize = sizeof(GLuint); break; default: - _mesa_problem(ctx, "Bad internalFormat in soft_renderbuffer_storage"); + _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage"); return GL_FALSE; } @@ -1171,7 +1206,6 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, rb->Width = width; rb->Height = height; - rb->InternalFormat = internalFormat; return GL_TRUE; } @@ -1198,6 +1232,7 @@ alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLenum internalFormat, GLuint width, GLuint height) { ASSERT(arb != arb->Wrapped); + ASSERT(arb->_ActualFormat == GL_ALPHA8); /* first, pass the call to the wrapped RGB buffer */ if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, @@ -1220,7 +1255,6 @@ alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, arb->Width = width; arb->Height = height; - arb->InternalFormat = internalFormat; return GL_TRUE; } @@ -1418,6 +1452,9 @@ nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) void _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) { + _glthread_INIT_MUTEX(rb->Mutex); + + rb->ClassID = 0; rb->Name = name; rb->RefCount = 1; rb->Delete = _mesa_delete_renderbuffer; @@ -1430,6 +1467,7 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) rb->Width = 0; rb->Height = 0; rb->InternalFormat = GL_NONE; + rb->_ActualFormat = GL_NONE; rb->_BaseFormat = GL_NONE; rb->DataType = GL_NONE; rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0; @@ -1479,6 +1517,7 @@ _mesa_delete_renderbuffer(struct gl_renderbuffer *rb) if (rb->Data) { _mesa_free(rb->Data); } + _glthread_INIT_MUTEX(rb->Mutex); _mesa_free(rb); } @@ -1494,9 +1533,9 @@ _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name) { struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); if (rb) { - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; /* Normally, one would setup the PutRow, GetRow, etc functions here. - * But we're doing that in the soft_renderbuffer_storage() function + * But we're doing that in the _mesa_soft_renderbuffer_storage() function * instead. */ } @@ -1550,19 +1589,20 @@ _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, if (rgbBits <= 8) { if (alphaBits) - rb->InternalFormat = GL_RGBA8; + rb->_ActualFormat = GL_RGBA8; else - rb->InternalFormat = GL_RGB8; + rb->_ActualFormat = GL_RGB8; } else { assert(rgbBits <= 16); if (alphaBits) - rb->InternalFormat = GL_RGBA16; + rb->_ActualFormat = GL_RGBA16; else - rb->InternalFormat = GL_RGBA16; /* don't really have RGB16 yet */ + rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */ } + rb->InternalFormat = rb->_ActualFormat; - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, b, rb); } @@ -1617,12 +1657,14 @@ _mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, if (indexBits <= 8) { /* only support GLuint for now */ /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/ - rb->InternalFormat = COLOR_INDEX32; + rb->_ActualFormat = COLOR_INDEX32; } else { - rb->InternalFormat = COLOR_INDEX32; + rb->_ActualFormat = COLOR_INDEX32; } - rb->AllocStorage = soft_renderbuffer_storage; + rb->InternalFormat = rb->_ActualFormat; + + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, b, rb); } @@ -1693,6 +1735,7 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, * values. */ arb->InternalFormat = arb->Wrapped->InternalFormat; + arb->_ActualFormat = GL_ALPHA8; arb->_BaseFormat = arb->Wrapped->_BaseFormat; arb->DataType = arb->Wrapped->DataType; arb->AllocStorage = alloc_storage_alpha8; @@ -1746,16 +1789,17 @@ _mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, } if (depthBits <= 16) { - rb->InternalFormat = GL_DEPTH_COMPONENT16; + rb->_ActualFormat = GL_DEPTH_COMPONENT16; } else if (depthBits <= 24) { - rb->InternalFormat = GL_DEPTH_COMPONENT24; + rb->_ActualFormat = GL_DEPTH_COMPONENT24; } else { - rb->InternalFormat = GL_DEPTH_COMPONENT32; + rb->_ActualFormat = GL_DEPTH_COMPONENT32; } + rb->InternalFormat = rb->_ActualFormat; - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); return GL_TRUE; @@ -1791,14 +1835,15 @@ _mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, } if (stencilBits <= 8) { - rb->InternalFormat = GL_STENCIL_INDEX8_EXT; + rb->_ActualFormat = GL_STENCIL_INDEX8_EXT; } else { /* not really supported (see s_stencil.c code) */ - rb->InternalFormat = GL_STENCIL_INDEX16_EXT; + rb->_ActualFormat = GL_STENCIL_INDEX16_EXT; } + rb->InternalFormat = rb->_ActualFormat; - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); return GL_TRUE; @@ -1834,8 +1879,9 @@ _mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, return GL_FALSE; } + rb->_ActualFormat = GL_RGBA16; rb->InternalFormat = GL_RGBA16; - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); return GL_TRUE; @@ -1878,13 +1924,14 @@ _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, } if (colorBits <= 8) { - rb->InternalFormat = GL_RGBA8; + rb->_ActualFormat = GL_RGBA8; } else { - rb->InternalFormat = GL_RGBA16; + rb->_ActualFormat = GL_RGBA16; } + rb->InternalFormat = rb->_ActualFormat; - rb->AllocStorage = soft_renderbuffer_storage; + rb->AllocStorage = _mesa_soft_renderbuffer_storage; _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); } return GL_TRUE; @@ -2018,7 +2065,8 @@ _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name) /* init fields not covered by _mesa_new_renderbuffer() */ dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; - dsrb->AllocStorage = soft_renderbuffer_storage; + dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; + dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; return dsrb; } diff --git a/src/mesa/main/renderbuffer.h b/src/mesa/main/renderbuffer.h index 232bdfff9b..d8358e213c 100644 --- a/src/mesa/main/renderbuffer.h +++ b/src/mesa/main/renderbuffer.h @@ -41,6 +41,11 @@ extern struct gl_renderbuffer * _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name); +extern GLboolean +_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height); + extern GLboolean _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, GLuint rgbBits, GLuint alphaBits, diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 15a12ee4dc..ff1d51d7d0 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -117,6 +117,7 @@ static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); data += (img->RowStride - img->Width) * c; } + /* XXX use img->ImageStride here */ _mesa_printf("\n"); } #endif @@ -1052,6 +1053,7 @@ clear_teximage_fields(struct gl_texture_image *img) img->Height = 0; img->Depth = 0; img->RowStride = 0; + img->ImageStride = 0; img->Width2 = 0; img->Height2 = 0; img->Depth2 = 0; @@ -1097,6 +1099,7 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, img->Height = height; img->Depth = depth; img->RowStride = width; + img->ImageStride = width * height; img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ @@ -2049,8 +2052,8 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ) { const struct gl_texture_unit *texUnit; - const struct gl_texture_object *texObj; - const struct gl_texture_image *texImage; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; GLint maxLevels = 0; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -2169,7 +2172,7 @@ update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, att->CubeMapFace == face) { ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); /* Tell driver about the new renderbuffer texture */ - ctx->Driver.RenderbufferTexture(ctx, ctx->DrawBuffer, att); + ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); } } } diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 59a1d9375f..cfe9229cdb 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -50,6 +50,19 @@ /** \name Internal functions */ /*@{*/ + +/** + * Return the gl_texture_object for a given ID. + */ +struct gl_texture_object * +_mesa_lookup_texture(GLcontext *ctx, GLuint id) +{ + return (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, id); +} + + + /** * Allocate and initialize a new texture object. But don't put it into the * texture object hash table. @@ -682,8 +695,8 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) for (i = 0; i < n; i++) { if (textures[i] > 0) { - struct gl_texture_object *delObj = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, textures[i]); + struct gl_texture_object *delObj + = _mesa_lookup_texture(ctx, textures[i]); if (delObj) { /* Check if texture is bound to any framebuffer objects. @@ -817,8 +830,7 @@ _mesa_BindTexture( GLenum target, GLuint texName ) } else { /* non-default texture object */ - const struct _mesa_HashTable *hash = ctx->Shared->TexObjects; - newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName); + newTexObj = _mesa_lookup_texture(ctx, texName); if (newTexObj) { /* error checking */ if (newTexObj->Target != 0 && newTexObj->Target != target) { @@ -935,8 +947,7 @@ _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, for (i = 0; i < n; i++) { if (texName[i] > 0) { - struct gl_texture_object *t = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]); + struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]); if (t) { t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); if (ctx->Driver.PrioritizeTexture) @@ -985,8 +996,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName, _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); return GL_FALSE; } - t = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]); + t = _mesa_lookup_texture(ctx, texName[i]); if (!t) { _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); return GL_FALSE; @@ -1033,8 +1043,7 @@ _mesa_IsTexture( GLuint texture ) if (!texture) return GL_FALSE; - t = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texture); + t = _mesa_lookup_texture(ctx, texture); /* IsTexture is true only after object has been bound once. */ return t && t->Target; diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index d00bf70a0d..ac66ac69d3 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -5,9 +5,9 @@ /* * Mesa 3-D graphics library - * Version: 4.1 + * Version: 6.5 * - * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -40,6 +40,9 @@ */ /*@{*/ +extern struct gl_texture_object * +_mesa_lookup_texture(GLcontext *ctx, GLuint id); + extern struct gl_texture_object * _mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target ); diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c index dca93a1c04..85565bfb1d 100644 --- a/src/mesa/main/texrender.c +++ b/src/mesa/main/texrender.c @@ -163,7 +163,6 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) trb->Zoffset = att->Zoffset; - trb->Base.RefCount = 1; trb->Base.Width = trb->TexImage->Width; trb->Base.Height = trb->TexImage->Height; trb->Base.InternalFormat = trb->TexImage->InternalFormat; /* XXX fix? */ @@ -195,12 +194,14 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits; att->Renderbuffer = &(trb->Base); + trb->Base.RefCount++; } /** - * Called when rendering to a texture image begins. + * Called when rendering to a texture image begins, or when changing + * the dest mipmap level, cube face, etc. * This is a fallback routine for software render-to-texture. * * Called via the glRenderbufferTexture1D/2D/3D() functions @@ -216,9 +217,9 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) * \sa _mesa_framebuffer_renderbuffer */ void -_mesa_renderbuffer_texture(GLcontext *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att) +_mesa_render_texture(GLcontext *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; @@ -241,3 +242,12 @@ _mesa_renderbuffer_texture(GLcontext *ctx, } +void +_mesa_finish_render_texture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att) +{ + /* do nothing */ + /* The renderbuffer texture wrapper will get deleted by the + * normal mechanism for deleting renderbuffers. + */ +} diff --git a/src/mesa/main/texrender.h b/src/mesa/main/texrender.h index 1e11e50513..7c3fb0871b 100644 --- a/src/mesa/main/texrender.h +++ b/src/mesa/main/texrender.h @@ -3,9 +3,13 @@ extern void -_mesa_renderbuffer_texture(GLcontext *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att); +_mesa_render_texture(GLcontext *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att); + +extern void +_mesa_finish_render_texture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att); #endif /* TEXRENDER_H */ diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 81453e34f4..f5d23db650 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -1222,6 +1222,43 @@ _mesa_texstore_argb8888(STORE_PARAMS) dstImage += dstImageStride; } } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcFormat == GL_RGBA && + (srcType == GL_UNSIGNED_BYTE && littleEndian)) { + + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + + /* For some reason, streaming copies to write-combined regions + * are extremely sensitive to the characteristics of how the + * source data is retrieved. By reordering the source reads to + * be in-order, the speed of this operation increases by half. + * Strangely the same isn't required for the RGB path, above. + */ + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + *(GLuint *)(dstRow + col * 4) = (srcRow[col * 4 + RCOMP] << 16 | + srcRow[col * 4 + GCOMP] << 8 | + srcRow[col * 4 + BCOMP] << 0 | + srcRow[col * 4 + ACOMP] << 24); + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } else if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && dstFormat == &_mesa_texformat_argb8888 && @@ -4039,8 +4076,8 @@ _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight, void _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels, - const struct gl_texture_object *texObj, - const struct gl_texture_image *texImage) + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) { GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h index 381f610b5e..b71bae24eb 100644 --- a/src/mesa/main/texstore.h +++ b/src/mesa/main/texstore.h @@ -231,8 +231,8 @@ _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, extern void _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels, - const struct gl_texture_object *texObj, - const struct gl_texture_image *texImage); + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); extern void diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index ee15813f3c..ea283a1943 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -32,6 +32,7 @@ #include "colormac.h" #include "mtypes.h" #include "program.h" +#include "teximage.h" #include "swrast.h" #include "s_blend.h" #include "s_context.h" @@ -372,6 +373,83 @@ _swrast_validate_blend_func( GLcontext *ctx, GLuint n, } +/** + * Make sure we have texture image data for all the textures we may need + * for subsequent rendering. + */ +static void +_swrast_validate_texture_images(GLcontext *ctx) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint u; + + if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) { + /* no textures enabled, or no way to validate images! */ + return; + } + + for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; + ASSERT(texObj); + if (texObj) { + GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + GLuint face; + for (face = 0; face < numFaces; face++) { + GLuint lvl; + for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { + struct gl_texture_image *texImg = texObj->Image[face][lvl]; + if (texImg && !texImg->Data) { + swrast->ValidateTextureImage(ctx, texObj, face, lvl); + ASSERT(texObj->Image[face][lvl]->Data); + } + } + } + } + } + } +} + + +/** + * Free the texture image data attached to all currently enabled + * textures. Meant to be called by device drivers when transitioning + * from software to hardware rendering. + */ +void +_swrast_eject_texture_images(GLcontext *ctx) +{ + GLuint u; + + if (!ctx->Texture._EnabledUnits) { + /* no textures enabled */ + return; + } + + for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; + ASSERT(texObj); + if (texObj) { + GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + GLuint face; + for (face = 0; face < numFaces; face++) { + GLuint lvl; + for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { + struct gl_texture_image *texImg = texObj->Image[face][lvl]; + if (texImg && texImg->Data) { + _mesa_free_texmemory(texImg->Data); + texImg->Data = NULL; + } + } + } + } + } + } +} + + + static void _swrast_sleep( GLcontext *ctx, GLbitfield new_state ) { @@ -456,6 +534,9 @@ _swrast_validate_derived( GLcontext *ctx ) if (swrast->NewState & _NEW_TEXTURE) _swrast_update_texture_samplers( ctx ); + if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) + _swrast_validate_texture_images( ctx ); + swrast->NewState = 0; swrast->StateChanges = 0; swrast->InvalidateState = _swrast_invalidate_state; diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h index c1c01df8f5..5d9a35043b 100644 --- a/src/mesa/swrast/s_context.h +++ b/src/mesa/swrast/s_context.h @@ -226,6 +226,11 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *, const SWvertex *, const SWvertex *); +typedef void (*validate_texture_image_func)(GLcontext *ctx, + struct gl_texture_object *texObj, + GLuint face, GLuint level); + + /** \defgroup Bitmasks * Bitmasks to indicate which rasterization options are enabled * (RasterMask) @@ -363,6 +368,8 @@ typedef struct */ GLchan *TexelBuffer; + validate_texture_image_func ValidateTextureImage; + } SWcontext; diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h index dbc419b663..4422195a52 100644 --- a/src/mesa/swrast/swrast.h +++ b/src/mesa/swrast/swrast.h @@ -250,6 +250,10 @@ _swrast_copy_texsubimage3d(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height); +extern void +_swrast_eject_texture_images(GLcontext *ctx); + + /** * The driver interface for the software rasterizer. * XXX this may go away. -- cgit v1.2.3