#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);
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;
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.
/* 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;
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.
*/
{
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 ||
+ stObj->pt->block.size != blockSize)
{
pipe_texture_reference(&stObj->pt, NULL);
ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;