#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "mtypes.h"
#include "fbobject.h"
#include "renderbuffer.h"
#include "rbadaptors.h"
#define COLOR_INDEX32 0x424243
static void *
get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
if (!rb->Data)
return NULL;
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
return (GLubyte *) rb->Data + y * rb->Width + x;
}
static void
get_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, void *values)
{
const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
_mesa_memcpy(values, src, count * sizeof(GLubyte));
}
static void
get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLubyte *dst = (GLubyte *) values;
GLuint i;
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;
}
}
static void
put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = src[i];
}
}
}
else {
_mesa_memcpy(dst, values, count * sizeof(GLubyte));
}
}
static void
put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLubyte val = *((const GLubyte *) value);
GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = val;
}
}
}
else {
GLuint i;
for (i = 0; i < count; i++) {
dst[i] = val;
}
}
}
static void
put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[],
const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLuint i;
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];
*dst = src[i];
}
}
}
static void
put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLubyte val = *((const GLubyte *) value);
GLuint i;
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];
*dst = val;
}
}
}
static void *
get_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
if (!rb->Data)
return NULL;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
ASSERT(rb->Width > 0);
return (GLushort *) rb->Data + y * rb->Width + x;
}
static void
get_row_ushort(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_SHORT);
_mesa_memcpy(values, src, count * sizeof(GLushort));
}
static void
get_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLushort *dst = (GLushort *) values;
GLuint i;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
for (i = 0; i < count; i++) {
const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
dst[i] = *src;
}
}
static void
put_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLushort *src = (const GLushort *) values;
GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = src[i];
}
}
}
else {
_mesa_memcpy(dst, src, count * sizeof(GLushort));
}
}
static void
put_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLushort val = *((const GLushort *) value);
GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = val;
}
}
}
else {
GLuint i;
for (i = 0; i < count; i++) {
dst[i] = val;
}
}
}
static void
put_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *values,
const GLubyte *mask)
{
const GLushort *src = (const GLushort *) values;
GLuint i;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
*dst = src[i];
}
}
}
static void
put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLushort val = *((const GLushort *) value);
ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
*dst = val;
}
}
}
else {
GLuint i;
for (i = 0; i < count; i++) {
GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
*dst = val;
}
}
}
static void *
get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
if (!rb->Data)
return NULL;
ASSERT(rb->DataType == GL_UNSIGNED_INT ||
rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
return (GLuint *) rb->Data + y * rb->Width + x;
}
static void
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 ||
rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
_mesa_memcpy(values, src, count * sizeof(GLuint));
}
static void
get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLuint *dst = (GLuint *) values;
GLuint i;
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;
}
}
static void
put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLuint *src = (const GLuint *) values;
GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_INT ||
rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = src[i];
}
}
}
else {
_mesa_memcpy(dst, src, count * sizeof(GLuint));
}
}
static void
put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLuint val = *((const GLuint *) value);
GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
ASSERT(rb->DataType == GL_UNSIGNED_INT ||
rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = val;
}
}
}
else {
GLuint i;
for (i = 0; i < count; i++) {
dst[i] = val;
}
}
}
static void
put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *values,
const GLubyte *mask)
{
const GLuint *src = (const GLuint *) values;
GLuint i;
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];
*dst = src[i];
}
}
}
static void
put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *value,
const GLubyte *mask)
{
const GLuint val = *((const GLuint *) value);
GLuint i;
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];
*dst = val;
}
}
}
static void *
get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
ASSERT(rb->_ActualFormat == GL_RGB8);
return NULL;
}
static void
get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, void *values)
{
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];
dst[i * 4 + 1] = src[i * 3 + 1];
dst[i * 4 + 2] = src[i * 3 + 2];
dst[i * 4 + 3] = 255;
}
}
static void
get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLubyte *dst = (GLubyte *) values;
GLuint i;
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]);
dst[i * 4 + 0] = src[0];
dst[i * 4 + 1] = src[1];
dst[i * 4 + 2] = src[2];
dst[i * 4 + 3] = 255;
}
}
static void
put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
GLuint i;
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];
dst[i * 3 + 1] = src[i * 4 + 1];
dst[i * 3 + 2] = src[i * 4 + 2];
}
}
}
static void
put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
GLuint i;
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];
dst[i * 3 + 1] = src[i * 3 + 1];
dst[i * 3 + 2] = src[i * 3 + 2];
}
}
}
static void
put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLubyte val0 = ((const GLubyte *) value)[0];
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->_ActualFormat == GL_RGB8);
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
if (!mask && val0 == val1 && val1 == val2) {
_mesa_memset(dst, val0, 3 * count);
}
else {
GLuint i;
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
dst[i * 3 + 0] = val0;
dst[i * 3 + 1] = val1;
dst[i * 3 + 2] = val2;
}
}
}
}
static void
put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *values,
const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLuint i;
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]);
dst[0] = src[i * 4 + 0];
dst[1] = src[i * 4 + 1];
dst[2] = src[i * 4 + 2];
}
}
}
static void
put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLubyte val0 = ((const GLubyte *) value)[0];
const GLubyte val1 = ((const GLubyte *) value)[1];
const GLubyte val2 = ((const GLubyte *) value)[2];
GLuint i;
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]);
dst[0] = val0;
dst[1] = val1;
dst[2] = val2;
}
}
}
static void *
get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
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);
}
static void
get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, void *values)
{
const GLubyte *src = (const GLubyte *) 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(GLubyte));
}
static void
get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLuint *dst = (GLuint *) values;
GLuint i;
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;
}
}
static void
put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLuint *src = (const GLuint *) values;
GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
ASSERT(rb->_ActualFormat == GL_RGBA8);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = src[i];
}
}
}
else {
_mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte));
}
}
static void
put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
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->_ActualFormat == GL_RGBA8);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
dst[i * 4 + 0] = src[i * 3 + 0];
dst[i * 4 + 1] = src[i * 3 + 1];
dst[i * 4 + 2] = src[i * 3 + 2];
dst[i * 4 + 3] = 0xff;
}
}
}
static void
put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLuint val = *((const GLuint *) value);
GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
ASSERT(rb->_ActualFormat == GL_RGBA8);
if (!mask && val == 0) {
_mesa_bzero(dst, count * 4 * sizeof(GLubyte));
}
else {
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = val;
}
}
}
else {
GLuint i;
for (i = 0; i < count; i++) {
dst[i] = val;
}
}
}
}
static void
put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *values,
const GLubyte *mask)
{
const GLuint *src = (const GLuint *) values;
GLuint i;
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]);
*dst = src[i];
}
}
}
static void
put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLuint val = *((const GLuint *) value);
GLuint i;
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]);
*dst = val;
}
}
}
static void *
get_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
if (!rb->Data)
return NULL;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
return (GLushort *) rb->Data + 4 * (y * rb->Width + x);
}
static void
get_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, void *values)
{
const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
_mesa_memcpy(values, src, 4 * count * sizeof(GLshort));
}
static void
get_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLushort *dst = (GLushort *) values;
GLuint i;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
for (i = 0; i < count; i++) {
const GLushort *src
= (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
dst[i] = *src;
}
}
static void
put_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLushort *src = (const GLushort *) values;
GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i * 4 + 0] = src[i * 4 + 0];
dst[i * 4 + 1] = src[i * 4 + 1];
dst[i * 4 + 2] = src[i * 4 + 2];
dst[i * 4 + 3] = src[i * 4 + 3];
}
}
}
else {
_mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
}
}
static void
put_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLushort *src = (const GLushort *) values;
GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i * 4 + 0] = src[i * 3 + 0];
dst[i * 4 + 1] = src[i * 3 + 1];
dst[i * 4 + 2] = src[i * 3 + 2];
dst[i * 4 + 3] = 0xffff;
}
}
}
else {
_mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
}
}
static void
put_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLushort val0 = ((const GLushort *) value)[0];
const GLushort val1 = ((const GLushort *) value)[1];
const GLushort val2 = ((const GLushort *) value)[2];
const GLushort val3 = ((const GLushort *) value)[3];
GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
_mesa_bzero(dst, count * 4 * sizeof(GLushort));
}
else {
GLuint i;
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
dst[i * 4 + 0] = val0;
dst[i * 4 + 1] = val1;
dst[i * 4 + 2] = val2;
dst[i * 4 + 3] = val3;
}
}
}
}
static void
put_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
const GLint x[], const GLint y[], const void *values,
const GLubyte *mask)
{
const GLushort *src = (const GLushort *) values;
GLuint i;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
dst[0] = src[i * 4 + 0];
dst[1] = src[i * 4 + 1];
dst[2] = src[i * 4 + 2];
dst[3] = src[i * 4 + 3];
}
}
}
static void
put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLushort val0 = ((const GLushort *) value)[0];
const GLushort val1 = ((const GLushort *) value)[1];
const GLushort val2 = ((const GLushort *) value)[2];
const GLushort val3 = ((const GLushort *) value)[3];
GLuint i;
ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
dst[0] = val0;
dst[1] = val1;
dst[2] = val2;
dst[3] = val3;
}
}
}
GLboolean
_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
GLuint pixelSize;
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:
case GL_RGB4:
case GL_RGB5:
case GL_RGB8:
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;
rb->GetRow = get_row_ubyte3;
rb->GetValues = get_values_ubyte3;
rb->PutRow = put_row_ubyte3;
rb->PutRowRGB = put_row_rgb_ubyte3;
rb->PutMonoRow = put_mono_row_ubyte3;
rb->PutValues = put_values_ubyte3;
rb->PutMonoValues = put_mono_values_ubyte3;
rb->RedBits = 8 * sizeof(GLubyte);
rb->GreenBits = 8 * sizeof(GLubyte);
rb->BlueBits = 8 * sizeof(GLubyte);
rb->AlphaBits = 0;
pixelSize = 3 * sizeof(GLubyte);
break;
case GL_RGBA:
case GL_RGBA2:
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;
rb->GetRow = get_row_ubyte4;
rb->GetValues = get_values_ubyte4;
rb->PutRow = put_row_ubyte4;
rb->PutRowRGB = put_row_rgb_ubyte4;
rb->PutMonoRow = put_mono_row_ubyte4;
rb->PutValues = put_values_ubyte4;
rb->PutMonoValues = put_mono_values_ubyte4;
rb->RedBits = 8 * sizeof(GLubyte);
rb->GreenBits = 8 * sizeof(GLubyte);
rb->BlueBits = 8 * sizeof(GLubyte);
rb->AlphaBits = 8 * sizeof(GLubyte);
pixelSize = 4 * sizeof(GLubyte);
break;
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;
rb->GetRow = get_row_ushort4;
rb->GetValues = get_values_ushort4;
rb->PutRow = put_row_ushort4;
rb->PutRowRGB = put_row_rgb_ushort4;
rb->PutMonoRow = put_mono_row_ushort4;
rb->PutValues = put_values_ushort4;
rb->PutMonoValues = put_mono_values_ushort4;
rb->RedBits = 8 * sizeof(GLushort);
rb->GreenBits = 8 * sizeof(GLushort);
rb->BlueBits = 8 * sizeof(GLushort);
rb->AlphaBits = 8 * sizeof(GLushort);
pixelSize = 4 * sizeof(GLushort);
break;
#if 00
case GL_ALPHA8:
rb->_ActualFormat = GL_ALPHA8;
rb->_BaseFormat = GL_RGBA;
rb->DataType = GL_UNSIGNED_BYTE;
rb->GetPointer = get_pointer_alpha8;
rb->GetRow = get_row_alpha8;
rb->GetValues = get_values_alpha8;
rb->PutRow = put_row_alpha8;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_alpha8;
rb->PutValues = put_values_alpha8;
rb->PutMonoValues = put_mono_values_alpha8;
rb->RedBits = 0;
rb->GreenBits = 0;
rb->BlueBits = 0;
rb->AlphaBits = 8 * sizeof(GLubyte);
pixelSize = sizeof(GLubyte);
break;
#endif
case GL_STENCIL_INDEX:
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;
rb->GetRow = get_row_ubyte;
rb->GetValues = get_values_ubyte;
rb->PutRow = put_row_ubyte;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_ubyte;
rb->PutValues = put_values_ubyte;
rb->PutMonoValues = put_mono_values_ubyte;
rb->StencilBits = 8 * sizeof(GLubyte);
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;
rb->GetRow = get_row_ushort;
rb->GetValues = get_values_ushort;
rb->PutRow = put_row_ushort;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_ushort;
rb->PutValues = put_values_ushort;
rb->PutMonoValues = put_mono_values_ushort;
rb->StencilBits = 8 * sizeof(GLushort);
pixelSize = sizeof(GLushort);
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;
rb->GetRow = get_row_ushort;
rb->GetValues = get_values_ushort;
rb->PutRow = put_row_ushort;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_ushort;
rb->PutValues = put_values_ushort;
rb->PutMonoValues = put_mono_values_ushort;
rb->DepthBits = 8 * sizeof(GLushort);
pixelSize = sizeof(GLushort);
break;
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
rb->_BaseFormat = GL_DEPTH_COMPONENT;
rb->DataType = GL_UNSIGNED_INT;
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;
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;
rb->GetRow = get_row_ubyte;
rb->GetValues = get_values_ubyte;
rb->PutRow = put_row_ubyte;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_ubyte;
rb->PutValues = put_values_ubyte;
rb->PutMonoValues = put_mono_values_ubyte;
rb->IndexBits = 8 * sizeof(GLubyte);
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;
rb->GetRow = get_row_ushort;
rb->GetValues = get_values_ushort;
rb->PutRow = put_row_ushort;
rb->PutRowRGB = NULL;
rb->PutMonoRow = put_mono_row_ushort;
rb->PutValues = put_values_ushort;
rb->PutMonoValues = put_mono_values_ushort;
rb->IndexBits = 8 * sizeof(GLushort);
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;
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->IndexBits = 8 * sizeof(GLuint);
pixelSize = sizeof(GLuint);
break;
default:
_mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
return GL_FALSE;
}
ASSERT(rb->DataType);
ASSERT(rb->GetPointer);
ASSERT(rb->GetRow);
ASSERT(rb->GetValues);
ASSERT(rb->PutRow);
ASSERT(rb->PutMonoRow);
ASSERT(rb->PutValues);
ASSERT(rb->PutMonoValues);
if (rb->Data) {
_mesa_free(rb->Data);
rb->Data = NULL;
}
if (width > 0 && height > 0) {
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 (%d x %d x %d)",
width, height, pixelSize);
return GL_FALSE;
}
}
rb->Width = width;
rb->Height = height;
return GL_TRUE;
}
static GLboolean
alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
GLenum internalFormat, GLuint width, GLuint height)
{
ASSERT(arb != arb->Wrapped);
ASSERT(arb->_ActualFormat == GL_ALPHA8);
if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
width, height)) {
return GL_FALSE;
}
if (arb->Data) {
_mesa_free(arb->Data);
}
arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
if (arb->Data == NULL) {
arb->Width = 0;
arb->Height = 0;
_mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
return GL_FALSE;
}
arb->Width = width;
arb->Height = height;
return GL_TRUE;
}
static void
delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
{
if (arb->Data) {
_mesa_free(arb->Data);
}
ASSERT(arb->Wrapped);
ASSERT(arb != arb->Wrapped);
arb->Wrapped->Delete(arb->Wrapped);
arb->Wrapped = NULL;
_mesa_free(arb);
}
static void *
get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
GLint x, GLint y)
{
return NULL;
}
static void
get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
GLint x, GLint y, void *values)
{
const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
GLubyte *dst = (GLubyte *) values;
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
for (i = 0; i < count; i++) {
dst[i * 4 + 3] = src[i];
}
}
static void
get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
const GLint x[], const GLint y[], void *values)
{
GLubyte *dst = (GLubyte *) values;
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
for (i = 0; i < count; i++) {
const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
dst[i * 4 + 3] = *src;
}
}
static void
put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
dst[i] = src[i * 4 + 3];
}
}
}
static void
put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
GLint x, GLint y, const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
dst[i] = src[i * 4 + 3];
}
}
}
static void
put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
GLint x, GLint y, const void *value, const GLubyte *mask)
{
const GLubyte val = ((const GLubyte *) value)[3];
GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
if (mask) {
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
dst[i] = val;
}
}
}
else {
_mesa_memset(dst, val, count);
}
}
static void
put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
const GLint x[], const GLint y[],
const void *values, const GLubyte *mask)
{
const GLubyte *src = (const GLubyte *) values;
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
*dst = src[i * 4 + 3];
}
}
}
static void
put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
GLuint count, const GLint x[], const GLint y[],
const void *value, const GLubyte *mask)
{
const GLubyte val = ((const GLubyte *) value)[3];
GLuint i;
ASSERT(arb != arb->Wrapped);
ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
*dst = val;
}
}
}
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));
}
static void *
nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
{
return NULL;
}
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 = 0;
rb->Delete = _mesa_delete_renderbuffer;
rb->AllocStorage = NULL;
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;
rb->IndexBits = 0;
rb->DepthBits = 0;
rb->StencilBits = 0;
rb->Data = NULL;
rb->Wrapped = rb;
rb->GetPointer = nop_get_pointer;
rb->GetRow = NULL;
rb->GetValues = NULL;
rb->PutRow = NULL;
rb->PutRowRGB = NULL;
rb->PutMonoRow = NULL;
rb->PutValues = NULL;
rb->PutMonoValues = NULL;
}
struct gl_renderbuffer *
_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
{
struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
if (rb) {
_mesa_init_renderbuffer(rb, name);
}
return rb;
}
void
_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
{
if (rb->Data) {
_mesa_free(rb->Data);
}
_mesa_free(rb);
}
struct gl_renderbuffer *
_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
{
struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
if (rb) {
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
}
return rb;
}
GLboolean
_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint rgbBits, GLuint alphaBits,
GLboolean frontLeft, GLboolean backLeft,
GLboolean frontRight, GLboolean backRight)
{
GLuint b;
if (rgbBits > 16 || alphaBits > 16) {
_mesa_problem(ctx,
"Unsupported bit depth in _mesa_add_color_renderbuffers");
return GL_FALSE;
}
assert(MAX_COLOR_ATTACHMENTS >= 4);
for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
struct gl_renderbuffer *rb;
if (b == BUFFER_FRONT_LEFT && !frontLeft)
continue;
else if (b == BUFFER_BACK_LEFT && !backLeft)
continue;
else if (b == BUFFER_FRONT_RIGHT && !frontRight)
continue;
else if (b == BUFFER_BACK_RIGHT && !backRight)
continue;
assert(fb->Attachment[b].Renderbuffer == NULL);
rb = _mesa_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
return GL_FALSE;
}
if (rgbBits <= 8) {
if (alphaBits)
rb->_ActualFormat = GL_RGBA8;
else
rb->_ActualFormat = GL_RGB8;
}
else {
assert(rgbBits <= 16);
if (alphaBits)
rb->_ActualFormat = GL_RGBA16;
else
rb->_ActualFormat = GL_RGBA16;
}
rb->InternalFormat = rb->_ActualFormat;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, b, rb);
}
return GL_TRUE;
}
GLboolean
_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint indexBits,
GLboolean frontLeft, GLboolean backLeft,
GLboolean frontRight, GLboolean backRight)
{
GLuint b;
if (indexBits > 8) {
_mesa_problem(ctx,
"Unsupported bit depth in _mesa_add_color_index_renderbuffers");
return GL_FALSE;
}
assert(MAX_COLOR_ATTACHMENTS >= 4);
for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
struct gl_renderbuffer *rb;
if (b == BUFFER_FRONT_LEFT && !frontLeft)
continue;
else if (b == BUFFER_BACK_LEFT && !backLeft)
continue;
else if (b == BUFFER_FRONT_RIGHT && !frontRight)
continue;
else if (b == BUFFER_BACK_RIGHT && !backRight)
continue;
assert(fb->Attachment[b].Renderbuffer == NULL);
rb = _mesa_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
return GL_FALSE;
}
if (indexBits <= 8) {
rb->_ActualFormat = COLOR_INDEX32;
}
else {
rb->_ActualFormat = COLOR_INDEX32;
}
rb->InternalFormat = rb->_ActualFormat;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, b, rb);
}
return GL_TRUE;
}
GLboolean
_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint alphaBits,
GLboolean frontLeft, GLboolean backLeft,
GLboolean frontRight, GLboolean backRight)
{
GLuint b;
assert(fb->Name == 0);
if (alphaBits > 8) {
_mesa_problem(ctx,
"Unsupported bit depth in _mesa_add_alpha_renderbuffers");
return GL_FALSE;
}
assert(MAX_COLOR_ATTACHMENTS >= 4);
for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
struct gl_renderbuffer *arb;
if (b == BUFFER_FRONT_LEFT && !frontLeft)
continue;
else if (b == BUFFER_BACK_LEFT && !backLeft)
continue;
else if (b == BUFFER_FRONT_RIGHT && !frontRight)
continue;
else if (b == BUFFER_BACK_RIGHT && !backRight)
continue;
assert(fb->Attachment[b].Renderbuffer);
assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
arb = _mesa_new_renderbuffer(ctx, 0);
if (!arb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
return GL_FALSE;
}
arb->Wrapped = fb->Attachment[b].Renderbuffer;
arb->InternalFormat = arb->Wrapped->InternalFormat;
arb->_ActualFormat = GL_ALPHA8;
arb->_BaseFormat = arb->Wrapped->_BaseFormat;
arb->DataType = arb->Wrapped->DataType;
arb->AllocStorage = alloc_storage_alpha8;
arb->Delete = delete_renderbuffer_alpha8;
arb->GetPointer = get_pointer_alpha8;
arb->GetRow = get_row_alpha8;
arb->GetValues = get_values_alpha8;
arb->PutRow = put_row_alpha8;
arb->PutRowRGB = put_row_rgb_alpha8;
arb->PutMonoRow = put_mono_row_alpha8;
arb->PutValues = put_values_alpha8;
arb->PutMonoValues = put_mono_values_alpha8;
fb->Attachment[b].Renderbuffer = NULL;
_mesa_add_renderbuffer(fb, b, arb);
}
return GL_TRUE;
}
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);
}
GLboolean
_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint depthBits)
{
struct gl_renderbuffer *rb;
if (depthBits > 32) {
_mesa_problem(ctx,
"Unsupported depthBits in _mesa_add_depth_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
rb = _mesa_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
return GL_FALSE;
}
if (depthBits <= 16) {
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
}
else if (depthBits <= 24) {
rb->_ActualFormat = GL_DEPTH_COMPONENT24;
}
else {
rb->_ActualFormat = GL_DEPTH_COMPONENT32;
}
rb->InternalFormat = rb->_ActualFormat;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
return GL_TRUE;
}
GLboolean
_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint stencilBits)
{
struct gl_renderbuffer *rb;
if (stencilBits > 16) {
_mesa_problem(ctx,
"Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
rb = _mesa_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
return GL_FALSE;
}
if (stencilBits <= 8) {
rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
}
else {
rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
}
rb->InternalFormat = rb->_ActualFormat;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
return GL_TRUE;
}
GLboolean
_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint redBits, GLuint greenBits,
GLuint blueBits, GLuint alphaBits)
{
struct gl_renderbuffer *rb;
if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
_mesa_problem(ctx,
"Unsupported accumBits in _mesa_add_accum_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
rb = _mesa_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
return GL_FALSE;
}
rb->_ActualFormat = GL_RGBA16;
rb->InternalFormat = GL_RGBA16;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
return GL_TRUE;
}
GLboolean
_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint colorBits, GLuint numBuffers)
{
GLuint i;
if (colorBits > 16) {
_mesa_problem(ctx,
"Unsupported accumBits in _mesa_add_aux_renderbuffers");
return GL_FALSE;
}
assert(numBuffers < MAX_AUX_BUFFERS);
for (i = 0; i < numBuffers; i++) {
struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
return GL_FALSE;
}
if (colorBits <= 8) {
rb->_ActualFormat = GL_RGBA8;
}
else {
rb->_ActualFormat = GL_RGBA16;
}
rb->InternalFormat = rb->_ActualFormat;
rb->AllocStorage = _mesa_soft_renderbuffer_storage;
_mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
}
return GL_TRUE;
}
void
_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
GLboolean color,
GLboolean depth,
GLboolean stencil,
GLboolean accum,
GLboolean alpha,
GLboolean aux)
{
GLboolean frontLeft = GL_TRUE;
GLboolean backLeft = fb->Visual.doubleBufferMode;
GLboolean frontRight = fb->Visual.stereoMode;
GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
if (color) {
if (fb->Visual.rgbMode) {
assert(fb->Visual.redBits == fb->Visual.greenBits);
assert(fb->Visual.redBits == fb->Visual.blueBits);
_mesa_add_color_renderbuffers(NULL, fb,
fb->Visual.redBits,
fb->Visual.alphaBits,
frontLeft, backLeft,
frontRight, backRight);
}
else {
_mesa_add_color_index_renderbuffers(NULL, fb,
fb->Visual.indexBits,
frontLeft, backLeft,
frontRight, backRight);
}
}
if (depth) {
assert(fb->Visual.depthBits > 0);
_mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
}
if (stencil) {
assert(fb->Visual.stencilBits > 0);
_mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
}
if (accum) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.accumRedBits > 0);
assert(fb->Visual.accumGreenBits > 0);
assert(fb->Visual.accumBlueBits > 0);
_mesa_add_accum_renderbuffer(NULL, fb,
fb->Visual.accumRedBits,
fb->Visual.accumGreenBits,
fb->Visual.accumBlueBits,
fb->Visual.accumAlphaBits);
}
if (aux) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.numAuxBuffers > 0);
_mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
fb->Visual.numAuxBuffers);
}
if (alpha) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.alphaBits > 0);
_mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
frontLeft, backLeft,
frontRight, backRight);
}
#if 0
if (multisample) {
}
#endif
}
void
_mesa_add_renderbuffer(struct gl_framebuffer *fb,
GLuint bufferName, struct gl_renderbuffer *rb)
{
assert(fb);
assert(rb);
assert(bufferName < BUFFER_COUNT);
assert(bufferName == BUFFER_DEPTH ||
bufferName == BUFFER_STENCIL ||
fb->Attachment[bufferName].Renderbuffer == NULL);
if (fb->Name) {
assert(rb->Name);
}
else {
assert(!rb->Name);
}
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;
_mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
}
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;
}
void
_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
struct gl_renderbuffer *rb)
{
assert(ptr);
if (*ptr == rb) {
return;
}
if (*ptr) {
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--;
deleteFlag = (oldRb->RefCount == 0);
_glthread_UNLOCK_MUTEX(oldRb->Mutex);
if (deleteFlag) {
oldRb->Magic = 0;
oldRb->Delete(oldRb);
}
*ptr = NULL;
}
assert(!*ptr);
if (rb) {
assert(rb->Magic == RB_MAGIC);
_glthread_LOCK_MUTEX(rb->Mutex);
rb->RefCount++;
_glthread_UNLOCK_MUTEX(rb->Mutex);
*ptr = rb;
}
}
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;
dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
return dsrb;
}