📄 texstore.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.4
*
* Copyright (C) 1999-2005 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Brian Paul
*/
/*
* The GL texture image functions in teximage.c basically just do
* error checking and data structure allocation. They in turn call
* device driver functions which actually copy/convert/store the user's
* texture image data.
*
* However, most device drivers will be able to use the fallback functions
* in this file. That is, most drivers will have the following bit of
* code:
* ctx->Driver.TexImage1D = _mesa_store_teximage1d;
* ctx->Driver.TexImage2D = _mesa_store_teximage2d;
* ctx->Driver.TexImage3D = _mesa_store_teximage3d;
* etc...
*
* Texture image processing is actually kind of complicated. We have to do:
* Format/type conversions
* pixel unpacking
* pixel transfer (scale, bais, lookup, convolution!, etc)
*
* These functions can handle most everything, including processing full
* images and sub-images.
*/
#include "glheader.h"
#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
#include "convolve.h"
#include "image.h"
#include "macros.h"
#include "imports.h"
#include "texcompress.h"
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
static const GLint ZERO = 4, ONE = 5;
static GLboolean can_swizzle(GLenum logicalBaseFormat)
{
switch (logicalBaseFormat) {
case GL_RGBA:
case GL_RGB:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
case GL_ALPHA:
case GL_LUMINANCE:
return GL_TRUE;
default:
return GL_FALSE;
}
}
/**
* When promoting texture formats (see below) we need to compute the
* mapping of dest components back to source components.
* This function does that.
* \param logicalBaseFormat the logical format of the texture
* \param textureBaseFormat the final texture format
* \return map[4] the four mapping values
*/
static void
compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
GLubyte map[6])
{
map[ZERO] = ZERO;
map[ONE] = ONE;
/* compute mapping from dest components back to src components */
switch (textureBaseFormat) {
case GL_RGB:
case GL_RGBA:
switch (logicalBaseFormat) {
case GL_LUMINANCE:
map[0] = map[1] = map[2] = 0;
if (textureBaseFormat == GL_RGBA)
map[3] = ONE;
break;
case GL_ALPHA:
ASSERT(textureBaseFormat == GL_RGBA);
map[0] = map[1] = map[2] = ZERO;
map[3] = 0;
break;
case GL_INTENSITY:
map[0] = map[1] = map[2] = 0;
if (textureBaseFormat == GL_RGBA)
map[3] = 0;
break;
case GL_LUMINANCE_ALPHA:
ASSERT(textureBaseFormat == GL_RGBA);
map[0] = map[1] = map[2] = 0;
map[3] = 1;
break;
case GL_RGB:
ASSERT(textureBaseFormat == GL_RGBA);
map[0] = 0;
map[1] = 1;
map[2] = 2;
map[3] = ONE;
break;
case GL_RGBA:
ASSERT(textureBaseFormat == GL_RGBA);
map[0] = 0;
map[1] = 1;
map[2] = 2;
map[3] = 3;
break;
default:
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
map[0] = map[1] = map[2] = map[3] = 0;
}
break;
case GL_LUMINANCE_ALPHA:
switch (logicalBaseFormat) {
case GL_LUMINANCE:
map[0] = 0;
map[1] = ONE;
break;
case GL_ALPHA:
map[0] = ZERO;
map[1] = 0;
break;
case GL_INTENSITY:
map[0] = 0;
map[1] = 0;
break;
default:
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
map[0] = map[1] = 0;
}
break;
default:
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
map[0] = map[1] = 0;
break;
}
}
/**
* Make a temporary (color) texture image with GLfloat components.
* Apply all needed pixel unpacking and pixel transfer operations.
* Note that there are both logicalBaseFormat and textureBaseFormat parameters.
* Suppose the user specifies GL_LUMINANCE as the internal texture format
* but the graphics hardware doesn't support luminance textures. So, might
* use an RGB hardware format instead.
* If logicalBaseFormat != textureBaseFormat we have some extra work to do.
*
* \param ctx the rendering context
* \param dims image dimensions: 1, 2 or 3
* \param logicalBaseFormat basic texture derived from the user's
* internal texture format value
* \param textureBaseFormat the actual basic format of the texture
* \param srcWidth source image width
* \param srcHeight source image height
* \param srcDepth source image depth
* \param srcFormat source image format
* \param srcType source image type
* \param srcAddr source image address
* \param srcPacking source image pixel packing
* \return resulting image with format = textureBaseFormat and type = GLfloat.
*/
static GLfloat *
make_temp_float_image(GLcontext *ctx, GLuint dims,
GLenum logicalBaseFormat,
GLenum textureBaseFormat,
GLint srcWidth, GLint srcHeight, GLint srcDepth,
GLenum srcFormat, GLenum srcType,
const GLvoid *srcAddr,
const struct gl_pixelstore_attrib *srcPacking)
{
GLuint transferOps = ctx->_ImageTransferState;
GLfloat *tempImage;
ASSERT(dims >= 1 && dims <= 3);
ASSERT(logicalBaseFormat == GL_RGBA ||
logicalBaseFormat == GL_RGB ||
logicalBaseFormat == GL_LUMINANCE_ALPHA ||
logicalBaseFormat == GL_LUMINANCE ||
logicalBaseFormat == GL_ALPHA ||
logicalBaseFormat == GL_INTENSITY ||
logicalBaseFormat == GL_COLOR_INDEX ||
logicalBaseFormat == GL_DEPTH_COMPONENT);
ASSERT(textureBaseFormat == GL_RGBA ||
textureBaseFormat == GL_RGB ||
textureBaseFormat == GL_LUMINANCE_ALPHA ||
textureBaseFormat == GL_LUMINANCE ||
textureBaseFormat == GL_ALPHA ||
textureBaseFormat == GL_INTENSITY ||
textureBaseFormat == GL_COLOR_INDEX ||
textureBaseFormat == GL_DEPTH_COMPONENT);
/* conventional color image */
if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
(dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
(dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
/* need image convolution */
const GLuint preConvTransferOps
= (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
const GLuint postConvTransferOps
= (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
GLint img, row;
GLint convWidth, convHeight;
GLfloat *convImage;
/* pre-convolution image buffer (3D) */
tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
* 4 * sizeof(GLfloat));
if (!tempImage)
return NULL;
/* post-convolution image buffer (2D) */
convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
* 4 * sizeof(GLfloat));
if (!convImage) {
_mesa_free(tempImage);
return NULL;
}
/* loop over 3D image slices */
for (img = 0; img < srcDepth; img++) {
GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
/* unpack and do transfer ops up to convolution */
for (row = 0; row < srcHeight; row++) {
const GLvoid *src = _mesa_image_address(dims, srcPacking,
srcAddr, srcWidth, srcHeight,
srcFormat, srcType, img, row, 0);
_mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
srcFormat, srcType, src,
srcPacking,
preConvTransferOps);
dst += srcWidth * 4;
}
/* do convolution */
{
GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
convWidth = srcWidth;
convHeight = srcHeight;
if (dims == 1) {
ASSERT(ctx->Pixel.Convolution1DEnabled);
_mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
}
else {
if (ctx->Pixel.Convolution2DEnabled) {
_mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
src, convImage);
}
else {
ASSERT(ctx->Pixel.Separable2DEnabled);
_mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
src, convImage);
}
}
}
/* do post-convolution transfer and pack into tempImage */
{
const GLint logComponents
= _mesa_components_in_format(logicalBaseFormat);
const GLfloat *src = convImage;
GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
for (row = 0; row < convHeight; row++) {
_mesa_pack_rgba_span_float(ctx, convWidth,
(const GLfloat (*)[4]) src,
logicalBaseFormat, GL_FLOAT,
dst, &ctx->DefaultPacking,
postConvTransferOps);
src += convWidth * 4;
dst += convWidth * logComponents;
}
}
} /* loop over 3D image slices */
_mesa_free(convImage);
/* might need these below */
srcWidth = convWidth;
srcHeight = convHeight;
}
else {
/* no convolution */
const GLint components = _mesa_components_in_format(logicalBaseFormat);
const GLint srcStride = _mesa_image_row_stride(srcPacking,
srcWidth, srcFormat, srcType);
GLfloat *dst;
GLint img, row;
tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
* components * sizeof(GLfloat));
if (!tempImage)
return NULL;
dst = tempImage;
for (img = 0; img < srcDepth; img++) {
const GLubyte *src
= (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
srcWidth, srcHeight,
srcFormat, srcType,
img, 0, 0);
for (row = 0; row < srcHeight; row++) {
_mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -