X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fmain%2Frenderbuffer.c;h=5bef7c84fb203ececf97b686b9e3c60f3ba879f9;hb=54b0ed8360019fc6e0234c2c3413be40fe4d3b59;hp=4a0a63c56f42275307be7cb680bd96a28846695a;hpb=0efc17c105f8239bf4fb128d570f2d343c45d430;p=mesa.git diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 4a0a63c56f4..5bef7c84fb2 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.5 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -47,6 +47,8 @@ #include "fbobject.h" #include "renderbuffer.h" +#include "rbadaptors.h" + /* 32-bit color index format. Not a public format. */ #define COLOR_INDEX32 0x424243 @@ -70,6 +72,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 +95,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 +109,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 +130,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 +155,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 +172,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]; @@ -313,11 +318,12 @@ put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, static void * get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb, - GLint x, GLint y) + GLint x, GLint y) { if (!rb->Data) return NULL; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); return (GLuint *) rb->Data + y * rb->Width + x; } @@ -327,7 +333,8 @@ get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, void *values) { const void *src = rb->GetPointer(ctx, rb, x, y); - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); _mesa_memcpy(values, src, count * sizeof(GLuint)); } @@ -338,7 +345,8 @@ get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { GLuint *dst = (GLuint *) values; GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); for (i = 0; i < count; i++) { const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; dst[i] = *src; @@ -352,7 +360,8 @@ put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLuint *src = (const GLuint *) values; GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (mask) { GLuint i; for (i = 0; i < count; i++) { @@ -373,7 +382,8 @@ put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLuint val = *((const GLuint *) value); GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); if (mask) { GLuint i; for (i = 0; i < count; i++) { @@ -398,7 +408,8 @@ put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLuint *src = (const GLuint *) values; GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; @@ -415,7 +426,8 @@ put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, { const GLuint val = *((const GLuint *) value); GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + ASSERT(rb->DataType == GL_UNSIGNED_INT || + rb->DataType == GL_UNSIGNED_INT_24_8_EXT); for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; @@ -436,6 +448,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. */ @@ -450,6 +463,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]; @@ -466,7 +480,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]); @@ -486,7 +501,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]; @@ -505,7 +521,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]; @@ -525,7 +542,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); @@ -551,7 +569,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]); @@ -573,7 +592,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]); @@ -597,6 +617,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); } @@ -605,9 +626,10 @@ static void get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, void *values) { - const GLbyte *src = (const GLbyte *) rb->Data + 4 * (y * rb->Width + x); + const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x); ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - _mesa_memcpy(values, src, 4 * count * sizeof(GLbyte)); + ASSERT(rb->_ActualFormat == GL_RGBA8); + _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte)); } @@ -618,7 +640,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; @@ -633,7 +656,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++) { @@ -656,7 +680,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]; @@ -675,7 +700,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)); @@ -708,7 +734,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]); @@ -726,7 +753,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]); @@ -912,12 +940,22 @@ 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; + /* first clear these fields */ + rb->RedBits = + rb->GreenBits = + rb->BlueBits = + rb->AlphaBits = + rb->IndexBits = + rb->DepthBits = + rb->StencilBits = 0; + switch (internalFormat) { case GL_RGB: case GL_R3_G3_B2: @@ -927,6 +965,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; @@ -948,6 +987,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; @@ -967,6 +1007,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; @@ -984,7 +1025,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; @@ -1006,6 +1048,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; @@ -1020,6 +1063,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; @@ -1035,6 +1079,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; @@ -1060,10 +1105,35 @@ 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; - rb->DepthBits = 8 * sizeof(GLuint); + if (internalFormat == GL_DEPTH_COMPONENT24) { + rb->_ActualFormat = GL_DEPTH_COMPONENT24; + rb->DepthBits = 24; + } + 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; + rb->GetRow = get_row_uint; + rb->GetValues = get_values_uint; + rb->PutRow = put_row_uint; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_uint; + rb->PutValues = put_values_uint; + rb->PutMonoValues = put_mono_values_uint; + rb->DepthBits = 24; + rb->StencilBits = 8; 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; @@ -1078,6 +1148,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; @@ -1092,6 +1163,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; @@ -1106,7 +1178,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; } @@ -1120,26 +1192,33 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, ASSERT(rb->PutMonoValues); /* free old buffer storage */ - if (rb->Data) + if (rb->Data) { _mesa_free(rb->Data); + rb->Data = NULL; + } - /* allocate new buffer storage */ - rb->Data = _mesa_malloc(width * height * pixelSize); - if (rb->Data == NULL) { - rb->Width = 0; - rb->Height = 0; - _mesa_error(ctx, GL_OUT_OF_MEMORY, "software renderbuffer allocation"); - return GL_FALSE; + if (width > 0 && height > 0) { + /* allocate new buffer storage */ + rb->Data = malloc(width * height * pixelSize); + + if (rb->Data == NULL) { + rb->Width = 0; + rb->Height = 0; + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "software renderbuffer allocation (%d x %d x %d)", + width, height, pixelSize); + return GL_FALSE; + } } rb->Width = width; rb->Height = height; - rb->InternalFormat = internalFormat; return GL_TRUE; } + /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ @@ -1160,6 +1239,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, @@ -1182,7 +1262,6 @@ alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, arb->Width = width; arb->Height = height; - arb->InternalFormat = internalFormat; return GL_TRUE; } @@ -1357,6 +1436,17 @@ put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, } +static void +copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src) +{ + ASSERT(dst->_ActualFormat == GL_ALPHA8); + ASSERT(src->_ActualFormat == GL_ALPHA8); + ASSERT(dst->Width == src->Width); + ASSERT(dst->Height == src->Height); + + _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte)); +} + /**********************************************************************/ /**********************************************************************/ @@ -1380,8 +1470,12 @@ 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->Magic = RB_MAGIC; + rb->ClassID = 0; rb->Name = name; - rb->RefCount = 1; + rb->RefCount = 0; rb->Delete = _mesa_delete_renderbuffer; /* The rest of these should be set later by the caller of this function or @@ -1392,12 +1486,18 @@ _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->ComponentType = GL_UNSIGNED_NORMALIZED; /* ARB_fbo */ + rb->ColorEncoding = GL_LINEAR; /* ARB_fbo */ + rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0; rb->IndexBits = 0; rb->DepthBits = 0; rb->StencilBits = 0; + + rb->DataType = GL_NONE; rb->Data = NULL; /* Point back to ourself so that we don't have to check for Wrapped==NULL @@ -1433,7 +1533,7 @@ _mesa_new_renderbuffer(GLcontext *ctx, GLuint name) /** * Delete a gl_framebuffer. - * This is the default function for framebuffer->Delete(). + * This is the default function for renderbuffer->Delete(). */ void _mesa_delete_renderbuffer(struct gl_renderbuffer *rb) @@ -1456,9 +1556,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. */ } @@ -1512,19 +1612,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); } @@ -1579,12 +1680,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); } @@ -1655,6 +1758,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; @@ -1679,6 +1783,27 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, } +/** + * For framebuffers that use a software alpha channel wrapper + * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers, + * copy the back buffer alpha channel into the front buffer alpha channel. + */ +void +_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb) +{ + if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) + copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer, + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + + + if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) + copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer, + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); +} + + /** * Add a software-based depth renderbuffer to the given framebuffer. * This is a helper routine for device drivers when creating a @@ -1708,13 +1833,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->_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; @@ -1750,14 +1879,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; @@ -1793,8 +1923,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; @@ -1824,7 +1955,7 @@ _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, return GL_FALSE; } - assert(numBuffers < MAX_AUX_BUFFERS); + assert(numBuffers <= MAX_AUX_BUFFERS); for (i = 0; i < numBuffers; i++) { struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); @@ -1837,13 +1968,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; @@ -1941,12 +2073,16 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb, { assert(fb); assert(rb); -#if 00 - /* there should be no previous renderbuffer on this attachment point! */ - assert(fb->Attachment[bufferName].Renderbuffer == NULL); -#endif assert(bufferName < BUFFER_COUNT); + /* There should be no previous renderbuffer on this attachment point, + * with the exception of depth/stencil since the same renderbuffer may + * be used for both. + */ + assert(bufferName == BUFFER_DEPTH || + bufferName == BUFFER_STENCIL || + fb->Attachment[bufferName].Renderbuffer == NULL); + /* winsys vs. user-created buffer cross check */ if (fb->Name) { assert(rb->Name); @@ -1955,7 +2091,119 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb, assert(!rb->Name); } + /* If Mesa's compiled with deep color channels (16 or 32 bits / channel) + * and the device driver is expecting 8-bit values (GLubyte), we can + * use a "renderbuffer adaptor/wrapper" to do the necessary conversions. + */ + if (rb->_BaseFormat == GL_RGBA) { + if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) { + GET_CURRENT_CONTEXT(ctx); + rb = _mesa_new_renderbuffer_16wrap8(ctx, rb); + } + else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) { + GET_CURRENT_CONTEXT(ctx); + rb = _mesa_new_renderbuffer_32wrap8(ctx, rb); + } + else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) { + GET_CURRENT_CONTEXT(ctx); + rb = _mesa_new_renderbuffer_32wrap16(ctx, rb); + } + } + fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; fb->Attachment[bufferName].Complete = GL_TRUE; - fb->Attachment[bufferName].Renderbuffer = rb; + _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); +} + + +/** + * Remove the named renderbuffer from the given framebuffer. + */ +void +_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName) +{ + struct gl_renderbuffer *rb; + + assert(bufferName < BUFFER_COUNT); + + rb = fb->Attachment[bufferName].Renderbuffer; + if (!rb) + return; + + _mesa_reference_renderbuffer(&rb, NULL); + + fb->Attachment[bufferName].Renderbuffer = NULL; +} + + +/** + * Set *ptr to point to rb. If *ptr points to another renderbuffer, + * dereference that buffer first. The new renderbuffer's refcount will + * be incremented. The old renderbuffer's refcount will be decremented. + */ +void +_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr, + struct gl_renderbuffer *rb) +{ + assert(ptr); + if (*ptr == rb) { + /* no change */ + return; + } + + if (*ptr) { + /* Unreference the old renderbuffer */ + GLboolean deleteFlag = GL_FALSE; + struct gl_renderbuffer *oldRb = *ptr; + + assert(oldRb->Magic == RB_MAGIC); + _glthread_LOCK_MUTEX(oldRb->Mutex); + assert(oldRb->Magic == RB_MAGIC); + ASSERT(oldRb->RefCount > 0); + oldRb->RefCount--; + /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ + deleteFlag = (oldRb->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldRb->Mutex); + + if (deleteFlag) { + oldRb->Magic = 0; /* now invalid memory! */ + oldRb->Delete(oldRb); + } + + *ptr = NULL; + } + assert(!*ptr); + + if (rb) { + assert(rb->Magic == RB_MAGIC); + /* reference new renderbuffer */ + _glthread_LOCK_MUTEX(rb->Mutex); + rb->RefCount++; + /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ + _glthread_UNLOCK_MUTEX(rb->Mutex); + *ptr = rb; + } +} + + +/** + * Create a new combined depth/stencil renderbuffer for implementing + * the GL_EXT_packed_depth_stencil extension. + * \return new depth/stencil renderbuffer + */ +struct gl_renderbuffer * +_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name) +{ + struct gl_renderbuffer *dsrb; + + dsrb = _mesa_new_renderbuffer(ctx, name); + if (!dsrb) + return NULL; + + /* init fields not covered by _mesa_new_renderbuffer() */ + dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; + dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; + dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; + + return dsrb; }