#include "colormac.h"
#include "context.h"
#include "convolve.h"
#include "image.h"
#include "imports.h"
#include "macros.h"
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_span.h"
static GLchan *
read_color_image( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint stride, i;
GLchan *image, *dst;
image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
if (!image)
return NULL;
_swrast_use_read_buffer(ctx);
RENDER_START(swrast,ctx);
dst = image;
stride = width * 4;
for (i = 0; i < height; i++) {
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
(GLchan (*)[4]) dst );
dst += stride;
}
RENDER_FINISH(swrast,ctx);
_swrast_use_draw_buffer(ctx);
return image;
}
static GLfloat *
read_depth_image( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat *image, *dst;
GLint i;
image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
if (!image)
return NULL;
RENDER_START(swrast,ctx);
dst = image;
for (i = 0; i < height; i++) {
_mesa_read_depth_span_float(ctx, width, x, y + i, dst);
dst += width;
}
RENDER_FINISH(swrast,ctx);
return image;
}
static GLboolean
is_depth_format(GLenum format)
{
switch (format) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_SGIX:
case GL_DEPTH_COMPONENT24_SGIX:
case GL_DEPTH_COMPONENT32_SGIX:
return GL_TRUE;
default:
return GL_FALSE;
}
}
void
_swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLint border )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
ASSERT(ctx->Driver.TexImage1D);
if (is_depth_format(internalFormat)) {
GLfloat *image = read_depth_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
(*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
width, border,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
GLchan *image = read_color_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
(*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
void
_swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
ASSERT(ctx->Driver.TexImage2D);
if (is_depth_format(internalFormat)) {
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
(*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
width, height, border,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
(*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
void
_swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
ASSERT(ctx->Driver.TexImage1D);
if (texImage->Format == GL_DEPTH_COMPONENT) {
GLfloat *image = read_depth_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
return;
}
(*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
GLchan *image = read_color_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
return;
}
(*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
void
_swrast_copy_texsubimage2d( GLcontext *ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
ASSERT(ctx->Driver.TexImage2D);
if (texImage->Format == GL_DEPTH_COMPONENT) {
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
return;
}
(*ctx->Driver.TexSubImage2D)(ctx, target, level,
xoffset, yoffset, width, height,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
return;
}
(*ctx->Driver.TexSubImage2D)(ctx, target, level,
xoffset, yoffset, width, height,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
void
_swrast_copy_texsubimage3d( GLcontext *ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
ASSERT(ctx->Driver.TexImage3D);
if (texImage->Format == GL_DEPTH_COMPONENT) {
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
return;
}
(*ctx->Driver.TexSubImage3D)(ctx, target, level,
xoffset, yoffset, zoffset, width, height, 1,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
return;
}
(*ctx->Driver.TexSubImage3D)(ctx, target, level,
xoffset, yoffset, zoffset, width, height, 1,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}