summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2006-03-26 05:22:17 +0000
committerBrian Paul <[email protected]>2006-03-26 05:22:17 +0000
commitea4fe661d7f3a95d9db17e1475076f1badf8e1a6 (patch)
treeffc663f1a02dea07254e08620f8ad872fb1a3e20 /src
parent4cbd16ed3ffecd743b4921fab3a65f8510d151c9 (diff)
merge from texman branchmesa_20060325
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/common/driverfuncs.c3
-rw-r--r--src/mesa/drivers/dri/Makefile.template2
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c2
-rw-r--r--src/mesa/drivers/dri/common/drirenderbuffer.c4
-rw-r--r--src/mesa/main/dd.h10
-rw-r--r--src/mesa/main/depthstencil.c262
-rw-r--r--src/mesa/main/depthstencil.h19
-rw-r--r--src/mesa/main/drawpix.c24
-rw-r--r--src/mesa/main/fbobject.c346
-rw-r--r--src/mesa/main/fbobject.h8
-rw-r--r--src/mesa/main/framebuffer.c300
-rw-r--r--src/mesa/main/framebuffer.h8
-rw-r--r--src/mesa/main/image.c42
-rw-r--r--src/mesa/main/image.h7
-rw-r--r--src/mesa/main/mtypes.h37
-rw-r--r--src/mesa/main/renderbuffer.c144
-rw-r--r--src/mesa/main/renderbuffer.h5
-rw-r--r--src/mesa/main/teximage.c9
-rw-r--r--src/mesa/main/texobj.c29
-rw-r--r--src/mesa/main/texobj.h7
-rw-r--r--src/mesa/main/texrender.c20
-rw-r--r--src/mesa/main/texrender.h10
-rw-r--r--src/mesa/main/texstore.c41
-rw-r--r--src/mesa/main/texstore.h4
-rw-r--r--src/mesa/swrast/s_context.c81
-rw-r--r--src/mesa/swrast/s_context.h7
-rw-r--r--src/mesa/swrast/swrast.h4
27 files changed, 962 insertions, 473 deletions
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 7f577b6e7f6..9838e0b5ec0 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 35f7fd8a129..9e1b36252ff 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 883a89c8886..bad7073ed8b 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 29ba1ea8a30..990f71450db 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 4b2764979d8..4f1a962731d 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 90e434118e1..09524bba02e 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 76b75a0e361..3dde081f5a5 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 5c4f4545ea9..c82abccc41a 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 53c4d27e81a..ec690bdbf7f 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 c16f628a092..301e2da4495 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 5cea6d1a173..55e9bbc79d6 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -70,6 +70,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
* framebuffer objects ala GL_EXT_framebuffer_object.
@@ -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 51847b07c0f..1ff04085f34 100644
--- a/src/mesa/main/framebuffer.h
+++ b/src/mesa/main/framebuffer.h
@@ -53,6 +53,14 @@ 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);
extern GLboolean
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index 0a117a967b6..ee44e37295a 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 e31959565af..84faa03255e 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 c69b4a48b50..d2a0af1121d 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 1db5dce4fe4..aa14bf8634a 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 232bdfff9b3..d8358e213cb 100644
--- a/src/mesa/main/renderbuffer.h
+++ b/src/mesa/main/renderbuffer.h
@@ -42,6 +42,11 @@ _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,
GLboolean frontLeft, GLboolean backLeft,
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 15a12ee4dcc..ff1d51d7d09 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 59a1d9375ff..cfe9229cdb1 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 d00bf70a0d1..ac66ac69d3c 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"),
@@ -41,6 +41,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 );
extern void
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c
index dca93a1c04a..85565bfb1d4 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 1e11e505130..7c3fb0871bd 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 81453e34f4f..f5d23db6504 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -1226,6 +1226,43 @@ _mesa_texstore_argb8888(STORE_PARAMS)
!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 &&
+ srcFormat == GL_RGBA &&
srcType == GL_UNSIGNED_BYTE) {
int img, row, col;
@@ -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 381f610b5e9..b71bae24eb1 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 ee15813f3c6..ea283a19430 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 c1c01df8f56..5d9a35043be 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 dbc419b663a..4422195a524 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.