merge from texman branch
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 26 Mar 2006 05:22:17 +0000 (05:22 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 26 Mar 2006 05:22:17 +0000 (05:22 +0000)
27 files changed:
src/mesa/drivers/common/driverfuncs.c
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/drirenderbuffer.c
src/mesa/main/dd.h
src/mesa/main/depthstencil.c
src/mesa/main/depthstencil.h
src/mesa/main/drawpix.c
src/mesa/main/fbobject.c
src/mesa/main/fbobject.h
src/mesa/main/framebuffer.c
src/mesa/main/framebuffer.h
src/mesa/main/image.c
src/mesa/main/image.h
src/mesa/main/mtypes.h
src/mesa/main/renderbuffer.c
src/mesa/main/renderbuffer.h
src/mesa/main/teximage.c
src/mesa/main/texobj.c
src/mesa/main/texobj.h
src/mesa/main/texrender.c
src/mesa/main/texrender.h
src/mesa/main/texstore.c
src/mesa/main/texstore.h
src/mesa/swrast/s_context.c
src/mesa/swrast/s_context.h
src/mesa/swrast/swrast.h

index 7f577b6e7f6789158b9f65bf894e42ee35c65005..9838e0b5ec0c0acbf2210e54cf381fae29ee17cd 100644 (file)
@@ -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
 
index 35f7fd8a12994254dcd0bbbbb55a1833ff39fc7e..9e1b36252ffeb286649ee648316c703de8e75b62 100644 (file)
@@ -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
index 883a89c8886e5671a23e9f19840698a55bb46905..bad7073ed8bd96bf373bda582d3a23bdddabb412 100644 (file)
@@ -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 );
        }
index 29ba1ea8a3032bf932745d3ba8a4cdbbe8eaaa99..990f71450dbbcf06dea9fd9fc14bc9dde175b7d7 100644 (file)
@@ -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;
index 4b2764979d89ec0afde0997a8a6ccf6e40a9b916..4f1a962731d94620740e16e152940cd0ba929de6 100644 (file)
@@ -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);
    /*@}*/
index 90e434118e1c1e57aa8526f470884bb9306c1a23..09524bba02e767fe7b0837d4fe94348504a03f78 100644 (file)
@@ -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;
 }
index 76b75a0e36192cfb25331a0ddb0d9d4b387582cd..3dde081f5a5666ac0cd535299a97a2eee24379dd 100644 (file)
@@ -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 */
index 5c4f4545ea9cebb82af381f6c5ccab39577ad055..c82abccc41ace331851fef84de889e5ad310bf2d 100644 (file)
@@ -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)");
index 53c4d27e81af95b91aeed6a9b2c8c215beb47e24..ec690bdbf7f4d34cf2080d8063e713c9e6b71301 100644 (file)
@@ -36,6 +36,7 @@
 #include "renderbuffer.h"
 #include "state.h"
 #include "teximage.h"
+#include "texobj.h"
 #include "texstore.h"
 
 
@@ -66,8 +67,8 @@ static struct gl_renderbuffer DummyRenderbuffer;
 /**
  * Helper routine for getting a gl_renderbuffer.
  */
-static struct gl_renderbuffer *
-lookup_renderbuffer(GLcontext *ctx, GLuint id)
+struct gl_renderbuffer *
+_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id)
 {
    struct gl_renderbuffer *rb;
 
@@ -83,8 +84,8 @@ lookup_renderbuffer(GLcontext *ctx, GLuint id)
 /**
  * Helper routine for getting a gl_framebuffer.
  */
-static struct gl_framebuffer *
-lookup_framebuffer(GLcontext *ctx, GLuint id)
+struct gl_framebuffer *
+_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id)
 {
    struct gl_framebuffer *fb;
 
@@ -209,7 +210,7 @@ _mesa_set_texture_attachment(GLcontext *ctx,
    att->Complete = GL_FALSE;
 
    if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
-      ctx->Driver.RenderbufferTexture(ctx, fb, att);
+      ctx->Driver.RenderTexture(ctx, fb, att);
    }
 }
 
@@ -223,6 +224,7 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx,
                                   struct gl_renderbuffer_attachment *att,
                                   struct gl_renderbuffer *rb)
 {
+   /* XXX check if re-doing same attachment, exit early */
    _mesa_remove_attachment(ctx, att);
    att->Type = GL_RENDERBUFFER_EXT;
    att->Renderbuffer = rb;
@@ -242,6 +244,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
 {
    struct gl_renderbuffer_attachment *att;
 
+   _glthread_LOCK_MUTEX(fb->Mutex);
+   if (rb)
+      _glthread_LOCK_MUTEX(rb->Mutex);
+
    att = _mesa_get_attachment(ctx, fb, attachment);
    ASSERT(att);
 
@@ -251,6 +257,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
    else {
       _mesa_remove_attachment(ctx, att);
    }
+
+   if (rb)
+      _glthread_UNLOCK_MUTEX(rb->Mutex);
+   _glthread_UNLOCK_MUTEX(fb->Mutex);
 }
 
 
@@ -554,7 +564,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    if (renderbuffer) {
-      struct gl_renderbuffer *rb = lookup_renderbuffer(ctx, renderbuffer);
+      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
       if (rb != NULL && rb != &DummyRenderbuffer)
          return GL_TRUE;
    }
@@ -579,7 +589,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
    if (renderbuffer) {
-      newRb = lookup_renderbuffer(ctx, renderbuffer);
+      newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
       if (newRb == &DummyRenderbuffer) {
          /* ID was reserved, but no real renderbuffer object made yet */
          newRb = NULL;
@@ -626,7 +636,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
    for (i = 0; i < n; i++) {
       if (renderbuffers[i] > 0) {
         struct gl_renderbuffer *rb;
-        rb = lookup_renderbuffer(ctx, renderbuffers[i]);
+        rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
         if (rb) {
             /* check if deleting currently bound renderbuffer object */
             if (rb == ctx->CurrentRenderbuffer) {
@@ -786,15 +796,26 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
       return;
    }
 
+   /* These MUST get set by the AllocStorage func */
+   rb->_ActualFormat = 0;
+   rb->RedBits =
+   rb->GreenBits =
+   rb->BlueBits =
+   rb->AlphaBits =
+   rb->IndexBits =
+   rb->DepthBits =
+   rb->StencilBits = 0;
+
    /* Now allocate the storage */
    ASSERT(rb->AllocStorage);
    if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
       /* No error - check/set fields now */
+      assert(rb->_ActualFormat);
       assert(rb->Width == width);
       assert(rb->Height == height);
-      assert(rb->InternalFormat);
       assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
              rb->DepthBits || rb->StencilBits || rb->IndexBits);
+      rb->InternalFormat = internalFormat;
       rb->_BaseFormat = baseFormat;
    }
    else {
@@ -802,6 +823,7 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
       rb->Width = 0;
       rb->Height = 0;
       rb->InternalFormat = GL_NONE;
+      rb->_ActualFormat = GL_NONE;
       rb->_BaseFormat = GL_NONE;
       rb->RedBits =
       rb->GreenBits =
@@ -884,7 +906,7 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    if (framebuffer) {
-      struct gl_framebuffer *rb = lookup_framebuffer(ctx, framebuffer);
+      struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
       if (rb != NULL && rb != &DummyFramebuffer)
          return GL_TRUE;
    }
@@ -892,13 +914,28 @@ _mesa_IsFramebufferEXT(GLuint framebuffer)
 }
 
 
+static void
+check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+   GLuint i;
+   ASSERT(ctx->Driver.RenderTexture);
+   for (i = 0; i < BUFFER_COUNT; i++) {
+      struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+      struct gl_texture_object *texObj = att->Texture;
+      if (texObj) {
+         ctx->Driver.RenderTexture(ctx, fb, att);
+      }
+   }
+}
+
+
 /**
  * Examine all the framebuffer's attachments to see if any are textures.
  * If so, call ctx->Driver.FinishRenderTexture() for each texture to
  * notify the device driver that the texture image may have changed.
  */
 static void
-check_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
 {
    if (ctx->Driver.FinishRenderTexture) {
       GLuint i;
@@ -922,6 +959,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (!ctx->Extensions.EXT_framebuffer_object) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBindFramebufferEXT(unsupported)");
+      return;
+   }
+
    switch (target) {
 #if FEATURE_EXT_framebuffer_blit
    case GL_DRAW_FRAMEBUFFER_EXT:
@@ -954,7 +997,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
 
    if (framebuffer) {
       /* Binding a user-created framebuffer object */
-      newFb = lookup_framebuffer(ctx, framebuffer);
+      newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
       if (newFb == &DummyFramebuffer) {
          /* ID was reserved, but no real framebuffer object made yet */
          newFb = NULL;
@@ -968,10 +1011,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
         }
          _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
       }
+      _glthread_LOCK_MUTEX(newFb->Mutex);
       if (bindReadBuf)
          newFb->RefCount++;
       if (bindDrawBuf)
          newFb->RefCount++;
+      _glthread_UNLOCK_MUTEX(newFb->Mutex);
    }
    else {
       /* Binding the window system framebuffer (which was originally set
@@ -980,12 +1025,19 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
       newFb = ctx->WinSysDrawBuffer;
    }
 
+   ASSERT(newFb);
    ASSERT(newFb != &DummyFramebuffer);
 
+   /*
+    * XXX check if re-binding same buffer and skip some of this code.
+    */
+
    if (bindReadBuf) {
       oldFb = ctx->ReadBuffer;
       if (oldFb && oldFb->Name != 0) {
+         _glthread_LOCK_MUTEX(oldFb->Mutex);
          oldFb->RefCount--;
+         _glthread_UNLOCK_MUTEX(oldFb->Mutex);
          if (oldFb->RefCount == 0) {
             oldFb->Delete(oldFb);
          }
@@ -997,16 +1049,20 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
       oldFb = ctx->DrawBuffer;
       if (oldFb && oldFb->Name != 0) {
          /* check if old FB had any texture attachments */
-         if (ctx->Driver.FinishRenderTexture) {
-            check_texture_render(ctx, oldFb);
-         }
+         check_end_texture_render(ctx, oldFb);
          /* check if time to delete this framebuffer */
+         _glthread_LOCK_MUTEX(oldFb->Mutex);
          oldFb->RefCount--;
          if (oldFb->RefCount == 0) {
             oldFb->Delete(oldFb);
          }
+         _glthread_UNLOCK_MUTEX(oldFb->Mutex);
       }
       ctx->DrawBuffer = newFb;
+      if (newFb->Name != 0) {
+         /* check if newly bound framebuffer has any texture attachments */
+         check_begin_texture_render(ctx, newFb);
+      }
    }
 
    if (ctx->Driver.BindFramebuffer) {
@@ -1027,7 +1083,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
    for (i = 0; i < n; i++) {
       if (framebuffers[i] > 0) {
         struct gl_framebuffer *fb;
-        fb = lookup_framebuffer(ctx, framebuffers[i]);
+        fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
         if (fb) {
             ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
 
@@ -1045,7 +1101,9 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
                /* But the object will not be freed until it's no longer
                 * bound in any context.
                 */
+               _glthread_LOCK_MUTEX(fb->Mutex);
                fb->RefCount--;
+               _glthread_UNLOCK_MUTEX(fb->Mutex);
                if (fb->RefCount == 0) {
                   fb->Delete(fb);
                }
@@ -1134,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)");
index c16f628a0927a32dbc439e633cd9c6420ec33210..301e2da449555d400c0ba6dd0a4503f7973e701c 100644 (file)
@@ -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"),
 #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);
index 5cea6d1a173942ff061bd7350e07b4d79fd48b51..55e9bbc79d681ae6a35e3a33c98b9fdb376a5adf 100644 (file)
@@ -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);
 }
 
index 51847b07c0fb5c47aaab2a0d2af189ae6bfd15b9..1ff04085f34352fe93d3cf0f0a16519bb1e34e41 100644 (file)
@@ -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);
 
index 0a117a967b67dc19876f91b126d50c6820d14a06..ee44e37295abed87645367418df1d84411a2ae15 100644 (file)
@@ -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;
+}
index e31959565afca5e109b9e6f23de092cc2578ce84..84faa03255eb0ee75db4a0186248638be74c4b3f 100644 (file)
@@ -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
index c69b4a48b5036eedf8c95a9415711be8c49c436a..d2a0af1121d00559806c336cf6227a67c36accdd 100644 (file)
@@ -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;
 
index 1db5dce4fe49bcd041a722a5f24c614c6293a785..aa14bf8634a0720e4be63970edfddfb12193d335 100644 (file)
@@ -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;
 }
index 232bdfff9b3c38fe17170c3c31ea8909036b1dde..d8358e213cb4039eac085f10146737cfdbc51864 100644 (file)
@@ -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,
index 15a12ee4dcc72e045a81158a8c2aa5d4039f1f0b..ff1d51d7d0900021c34835cb65f2da31bd478efd 100644 (file)
@@ -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);
          }
       }
    }
index 59a1d9375ff0f98ea33c364b995380643928046a..cfe9229cdb19b14c1a2a45cb32e3e247dc499bc1 100644 (file)
 /** \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;
index d00bf70a0d10d890eb348ed40d3e3565af7d8ab6..ac66ac69d3cc3001400d659473d9a1c081730ded 100644 (file)
@@ -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 );
 
index dca93a1c04aeaf223143950c4a7fd219c8fbf0cb..85565bfb1d47770035415b5f4ab5c55706463958 100644 (file)
@@ -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.
+    */
+}
index 1e11e50513066fd89cd21d253fa1de5e9f51ef25..7c3fb0871bd5117bb1c3bfc18fc84be93ec97660 100644 (file)
@@ -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 */
index 81453e34f4f642b0afa329b7d4e18b2e036457dd..f5d23db65042d21554b32d723808864da928adea 100644 (file)
@@ -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;
 
index 381f610b5e94c7f945c7bb985627c82e77bd7b77..b71bae24eb1fe3bc0e7cf0c551a5179af8c55bb3 100644 (file)
@@ -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
index ee15813f3c616067902c46c000c6b81536d0dc7d..ea283a194302b2deb8669dfa8ee47e0b87201a1e 100644 (file)
@@ -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;
index c1c01df8f566b5e2aac863b0308def7b1d0716d3..5d9a35043bee33c57c5b27b4576cfbc701b34ca7 100644 (file)
@@ -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;
 
 
index dbc419b663a48f0b6dd5ec4e5a3770af01c2c866..4422195a524fb37304bd1399780c7b9bb463498a 100644 (file)
@@ -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.