#include "main/texobj.h"
#include "main/texstore.h"
+#include "state_tracker/st_debug.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_fbo.h"
#include "state_tracker/st_cb_texture.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_tile.h"
#include "util/u_blit.h"
+#include "util/u_format.h"
#include "util/u_surface.h"
#include "util/u_math.h"
}
-/**
- * Return nominal bytes per texel for a compressed format, 0 for non-compressed
- * format.
- */
-static GLuint
-compressed_num_bytes(gl_format format)
-{
- switch (format) {
-#if FEATURE_texture_fxt1
- case MESA_FORMAT_RGB_FXT1:
- case MESA_FORMAT_RGBA_FXT1:
-#endif
-#if FEATURE_texture_s3tc
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- return 2;
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- return 4;
-#endif
- default:
- return 0;
- }
-}
-
-
-static GLboolean
-is_compressed_mesa_format(gl_format format)
-{
- switch (format) {
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- case MESA_FORMAT_SRGB_DXT1:
- case MESA_FORMAT_SRGBA_DXT1:
- case MESA_FORMAT_SRGBA_DXT3:
- case MESA_FORMAT_SRGBA_DXT5:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
/** called via ctx->Driver.NewTextureImage() */
static struct gl_texture_image *
st_NewTextureImage(GLcontext * ctx)
default_usage(enum pipe_format fmt)
{
GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER;
- if (pf_is_depth_stencil(fmt))
+ if (util_format_is_depth_or_stencil(fmt))
usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
else
usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
stObj->base.MinFilter == GL_LINEAR ||
stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||
stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&
+ !stObj->base.GenerateMipmap &&
stImage->level == firstLevel) {
+ /* only alloc space for a single mipmap level */
lastLevel = firstLevel;
}
else {
+ /* alloc space for a full mipmap */
GLuint l2width = util_logbase2(width);
GLuint l2height = util_logbase2(height);
GLuint l2depth = util_logbase2(depth);
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = st_mesa_format_to_pipe_format(mesa_format);
- pf_get_block(templ.format, &templ.block);
- templ.width[0] = width;
- templ.height[0] = height;
- templ.depth[0] = 1;
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.depth0 = 1;
templ.last_level = 0;
templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
src_tex = screen->texture_create(screen, &templ);
}
#endif
- /* choose the texture format */
- texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
- format, type);
-
_mesa_set_fetch_functions(texImage, dims);
if (_mesa_is_format_compressed(texImage->TexFormat)) {
*/
if (!compressed_src &&
!ctx->Mesa_DXTn &&
- is_compressed_mesa_format(texImage->TexFormat) &&
+ _mesa_is_format_compressed(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target,
if (stImage->pt) {
if (format == GL_DEPTH_COMPONENT &&
- pf_is_depth_and_stencil(stImage->pt->format))
+ util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
texImage->Width,
texImage->Height,
texImage->Depth);
- dstRowStride =
- _mesa_compressed_row_stride(texImage->TexFormat, width);
+ dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
assert(dims != 3);
}
else {
* conversion and copy:
*/
if (compressed_src) {
- memcpy(texImage->Data, pixels, imageSize);
+ const GLuint srcImageStride = _mesa_format_row_stride(texImage->TexFormat, width);
+ if(dstRowStride == srcImageStride)
+ memcpy(texImage->Data, pixels, imageSize);
+ else
+ {
+ char *dst = texImage->Data;
+ const char *src = pixels;
+ int i;
+
+ for(i = 0; i < height; ++i)
+ {
+ memcpy(dst, src, srcImageStride);
+ dst += dstRowStride;
+ src += srcImageStride;
+ }
+ }
}
else {
const GLuint srcImageStride =
/* copy/pack data into user buffer */
if (st_equal_formats(stImage->pt->format, format, type)) {
/* memcpy */
- const uint bytesPerRow = width * pf_get_size(stImage->pt->format);
+ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
ubyte *map = screen->transfer_map(screen, tex_xfer);
GLuint row;
for (row = 0; row < height; row++) {
GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
height, format, type, row, 0);
+ if (ST_DEBUG & DEBUG_FALLBACK)
+ debug_printf("%s: fallback format translation\n", __FUNCTION__);
+
/* get float[4] rgba row from surface */
pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba);
GLubyte *dest;
if (stImage->pt &&
- pf_is_compressed(stImage->pt->format) &&
+ util_format_is_compressed(stImage->pt->format) &&
!compressed_dst) {
/* Need to decompress the texture.
* We'll do this by rendering a textured quad.
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
stImage->base.Height);
- texImage->RowStride = stImage->transfer->stride / stImage->pt->block.size;
+ texImage->RowStride = stImage->transfer->stride / util_format_get_blocksize(stImage->pt->format);
}
else {
/* Otherwise, the image should actually be stored in
/* See if we can do texture compression with a blit/render.
*/
if (!ctx->Mesa_DXTn &&
- is_compressed_mesa_format(texImage->TexFormat) &&
+ _mesa_is_format_compressed(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target,
unsigned face = _mesa_tex_target_to_face(target);
if (format == GL_DEPTH_COMPONENT &&
- pf_is_depth_and_stencil(stImage->pt->format))
+ util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
done:
_mesa_unmap_teximage_pbo(ctx, packing);
- if (stImage->pt) {
+ if (stImage->pt && texImage->Data) {
st_texture_image_unmap(ctx->st, stImage);
texImage->Data = NULL;
}
struct gl_texture_image *texImage)
{
struct st_texture_image *stImage = st_texture_image(texImage);
- struct pipe_format_block block;
int srcBlockStride;
int dstBlockStride;
int y;
+ enum pipe_format pformat= stImage->pt->format;
if (stImage->pt) {
unsigned face = _mesa_tex_target_to_face(target);
xoffset, yoffset,
width, height);
- block = stImage->pt->block;
- srcBlockStride = pf_get_stride(&block, width);
+ srcBlockStride = util_format_get_stride(pformat, width);
dstBlockStride = stImage->transfer->stride;
} else {
assert(stImage->pt);
return;
}
- assert(xoffset % block.width == 0);
- assert(yoffset % block.height == 0);
- assert(width % block.width == 0);
- assert(height % block.height == 0);
+ assert(xoffset % util_format_get_blockwidth(pformat) == 0);
+ assert(yoffset % util_format_get_blockheight(pformat) == 0);
+ assert(width % util_format_get_blockwidth(pformat) == 0);
+ assert(height % util_format_get_blockheight(pformat) == 0);
- for (y = 0; y < height; y += block.height) {
+ for (y = 0; y < height; y += util_format_get_blockheight(pformat)) {
/* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */
- const char *src = (const char*)data + srcBlockStride * pf_get_nblocksy(&block, y);
- char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(&block, y);
- memcpy(dst, src, pf_get_stride(&block, width));
+ const char *src = (const char*)data + srcBlockStride * util_format_get_nblocksy(pformat, y);
+ char *dst = (char*)texImage->Data + dstBlockStride * util_format_get_nblocksy(pformat, y);
+ memcpy(dst, src, util_format_get_stride(pformat, width));
}
if (stImage->pt) {
struct pipe_transfer *src_trans;
GLvoid *texDest;
enum pipe_transfer_usage transfer_usage;
+
+ if (ST_DEBUG & DEBUG_FALLBACK)
+ debug_printf("%s: fallback processing\n", __FUNCTION__);
assert(width <= MAX_WIDTH);
srcX, srcY,
width, height);
- if (baseFormat == GL_DEPTH_COMPONENT &&
- pf_is_depth_and_stencil(stImage->pt->format))
+ if ((baseFormat == GL_DEPTH_COMPONENT ||
+ baseFormat == GL_DEPTH_STENCIL) &&
+ util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
destX, destY, width, height);
if (baseFormat == GL_DEPTH_COMPONENT ||
- baseFormat == GL_DEPTH24_STENCIL8) {
+ baseFormat == GL_DEPTH_STENCIL) {
const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
ctx->Pixel.DepthBias != 0.0F);
GLint row, yStep;
return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */
}
else {
+ if (ST_DEBUG & DEBUG_FALLBACK)
+ debug_printf("%s failed for src %s, dst %s\n",
+ __FUNCTION__,
+ _mesa_lookup_enum_by_nr(srcFormat),
+ _mesa_lookup_enum_by_nr(dstLogicalFormat));
+
/* Otherwise fail.
*/
return 0;
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, level);
struct st_texture_image *stImage = st_texture_image(texImage);
- const GLenum texBaseFormat = texImage->InternalFormat;
+ const GLenum texBaseFormat = texImage->_BaseFormat;
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct st_renderbuffer *strb;
struct pipe_context *pipe = ctx->st->pipe;
/* determine if copying depth or color data */
if (texBaseFormat == GL_DEPTH_COMPONENT ||
- texBaseFormat == GL_DEPTH24_STENCIL8) {
+ texBaseFormat == GL_DEPTH_STENCIL) {
strb = st_renderbuffer(fb->_DepthBuffer);
}
- else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
- strb = st_renderbuffer(fb->_StencilBuffer);
- }
else {
/* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
strb = st_renderbuffer(fb->_ColorReadBuffer);
if (ctx->_ImageTransferState == 0x0) {
- if (matching_base_formats &&
+ if (pipe->surface_copy &&
+ matching_base_formats &&
src_format == dest_format &&
!do_flip)
{
use_fallback = GL_FALSE;
}
else if (format_writemask &&
+ texBaseFormat != GL_DEPTH_COMPONENT &&
+ texBaseFormat != GL_DEPTH_STENCIL &&
screen->is_format_supported(screen, src_format,
PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_SAMPLER,
}
-/**
- * Compute which mipmap levels that really need to be sent to the hardware.
- * This depends on the base image size, GL_TEXTURE_MIN_LOD,
- * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
- */
-static void
-calculate_first_last_level(struct st_texture_object *stObj)
-{
- struct gl_texture_object *tObj = &stObj->base;
-
- /* These must be signed values. MinLod and MaxLod can be negative numbers,
- * and having firstLevel and lastLevel as signed prevents the need for
- * extra sign checks.
- */
- GLint firstLevel;
- GLint lastLevel;
-
- /* Yes, this looks overly complicated, but it's all needed.
- */
- switch (tObj->Target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_CUBE_MAP:
- if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
- /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
- */
- firstLevel = lastLevel = tObj->BaseLevel;
- }
- else {
- firstLevel = 0;
- lastLevel = MIN2(tObj->MaxLevel,
- (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
- }
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_TEXTURE_4D_SGIS:
- firstLevel = lastLevel = 0;
- break;
- default:
- return;
- }
-
- stObj->lastLevel = lastLevel;
-}
-
-
static void
copy_image_data_to_texture(struct st_context *st,
struct st_texture_object *stObj,
pipe_texture_reference(&stImage->pt, NULL);
}
else if (stImage->base.Data) {
- assert(stImage->base.Data != NULL);
-
/* More straightforward upload.
*/
dstLevel,
stImage->base.Data,
stImage->base.RowStride *
- stObj->pt->block.size,
+ util_format_get_blocksize(stObj->pt->format),
stImage->base.RowStride *
stImage->base.Height *
- stObj->pt->block.size);
+ util_format_get_blocksize(stObj->pt->format));
_mesa_align_free(stImage->base.Data);
stImage->base.Data = NULL;
}
{
struct st_texture_object *stObj = st_texture_object(tObj);
const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
- GLuint cpp, face;
+ GLuint blockSize, face;
struct st_texture_image *firstImage;
*needFlush = GL_FALSE;
- /* We know/require this is true by now:
- */
- assert(stObj->base._Complete);
+ if (stObj->base._Complete) {
+ /* The texture is complete and we know exactly how many mipmap levels
+ * are present/needed. This is conditional because we may be called
+ * from the st_generate_mipmap() function when the texture object is
+ * incomplete. In that case, we'll have set stObj->lastLevel before
+ * we get here.
+ */
+ if (stObj->base.MinFilter == GL_LINEAR ||
+ stObj->base.MinFilter == GL_NEAREST)
+ stObj->lastLevel = stObj->base.BaseLevel;
+ else
+ stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel;
+ }
- /* What levels must the texture include at a minimum?
- */
- calculate_first_last_level(stObj);
firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
/* If both firstImage and stObj point to a texture which can contain
pipe_texture_reference(&stObj->pt, firstImage->pt);
}
- /* FIXME: determine format block instead of cpp */
- if (_mesa_is_format_compressed(firstImage->base.TexFormat)) {
- cpp = compressed_num_bytes(firstImage->base.TexFormat);
- }
- else {
- cpp = _mesa_get_format_bytes(firstImage->base.TexFormat);
- }
+ /* bytes per pixel block (blocks are usually 1x1) */
+ blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat);
/* If we already have a gallium texture, check that it matches the texture
* object's format, target, size, num_levels, etc.
if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
stObj->pt->format != fmt ||
stObj->pt->last_level < stObj->lastLevel ||
- stObj->pt->width[0] != firstImage->base.Width2 ||
- stObj->pt->height[0] != firstImage->base.Height2 ||
- stObj->pt->depth[0] != firstImage->base.Depth2 ||
- /* Nominal bytes per pixel: */
- stObj->pt->block.size / stObj->pt->block.width != cpp)
+ stObj->pt->width0 != firstImage->base.Width2 ||
+ stObj->pt->height0 != firstImage->base.Height2 ||
+ stObj->pt->depth0 != firstImage->base.Depth2)
{
pipe_texture_reference(&stObj->pt, NULL);
ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;