#include "main/convolve.h"
#endif
#include "main/enums.h"
+#include "main/fbobject.h"
#include "main/formats.h"
#include "main/image.h"
#include "main/imports.h"
#include "main/macros.h"
#include "main/mipmap.h"
-#include "main/pixel.h"
#include "main/texcompress.h"
#include "main/texfetch.h"
-#include "main/texformat.h"
#include "main/texgetimage.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.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_sampler.h"
#include "util/u_math.h"
struct st_texture_object *stObj = st_texture_object(texObj);
if (stObj->pt)
pipe_texture_reference(&stObj->pt, NULL);
+ if (stObj->sampler_view)
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
_mesa_delete_texture_object(ctx, texObj);
}
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;
depth,
usage);
+ stObj->pipe = st->pipe;
+
DBG("%s - success\n", __FUNCTION__);
}
{
const GLuint dstImageOffsets[1] = {0};
struct st_texture_image *stImage = st_texture_image(texImage);
- struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
gl_format mesa_format;
struct pipe_texture templ;
struct pipe_texture *src_tex;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *src_view;
struct pipe_surface *dst_surface;
struct pipe_transfer *tex_xfer;
void *map;
0, 0, 0, /* face, level are zero */
PIPE_TRANSFER_WRITE,
0, 0, width, height); /* x, y, w, h */
- map = screen->transfer_map(screen, tex_xfer);
+ map = pipe->transfer_map(pipe, tex_xfer);
_mesa_texstore(ctx, 2, GL_RGBA, mesa_format,
map, /* dest ptr */
pixels, /* source data */
unpack); /* source data packing */
- screen->transfer_unmap(screen, tex_xfer);
- screen->tex_transfer_destroy(tex_xfer);
+ pipe->transfer_unmap(pipe, tex_xfer);
+ pipe->tex_transfer_destroy(pipe, tex_xfer);
+
+ /* Create temporary sampler view */
+ u_sampler_view_default_template(&view_templ,
+ src_tex,
+ src_tex->format);
+ src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ);
+
/* copy / compress image */
util_blit_pixels_tex(ctx->st->blit,
- src_tex, /* pipe_texture (src) */
+ src_view, /* sampler view (src) */
0, 0, /* src x0, y0 */
width, height, /* src x1, y1 */
dst_surface, /* pipe_surface (dst) */
pipe_surface_reference(&dst_surface, NULL);
pipe_texture_reference(&src_tex, NULL);
+ pipe_sampler_view_reference(&src_view, NULL);
return GL_TRUE;
}
_mesa_align_free(texImage->Data);
}
- if (width == 0 || height == 0 || depth == 0) {
- /* stop after freeing old image */
- return;
- }
-
- /* If this is the only mipmap level in the texture, could call
- * bmBufferData with NULL data to free the old block and avoid
- * waiting on any outstanding fences.
+ /*
+ * See if the new image is somehow incompatible with the existing
+ * mipmap. If so, free the old mipmap.
*/
if (stObj->pt) {
if (stObj->teximage_realloc ||
level > (GLint) stObj->pt->last_level ||
- (stObj->pt->last_level == level &&
- stObj->pt->target != PIPE_TEXTURE_CUBE &&
- !st_texture_match_image(stObj->pt, &stImage->base,
- stImage->face, stImage->level))) {
+ !st_texture_match_image(stObj->pt, &stImage->base,
+ stImage->face, stImage->level)) {
DBG("release it\n");
pipe_texture_reference(&stObj->pt, NULL);
assert(!stObj->pt);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
stObj->teximage_realloc = FALSE;
}
}
+ if (width == 0 || height == 0 || depth == 0) {
+ /* stop after freeing old image */
+ return;
+ }
+
if (!stObj->pt) {
guess_and_alloc_texture(ctx->st, stObj, stImage);
if (!stObj->pt) {
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;
* 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;
+ GLuint i, bw, bh, lines;
+ _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
+ lines = (height + bh - 1) / bh;
+
+ for(i = 0; i < lines; ++i)
+ {
+ memcpy(dst, src, srcImageStride);
+ dst += dstRowStride;
+ src += srcImageStride;
+ }
+ }
}
else {
const GLuint srcImageStride =
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
struct st_texture_image *stImage = st_texture_image(texImage);
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct pipe_sampler_view *src_view = st_get_stobj_sampler_view(stObj);
const GLuint width = texImage->Width;
const GLuint height = texImage->Height;
struct pipe_surface *dst_surface;
/* blit/render/decompress */
util_blit_pixels_tex(ctx->st->blit,
- stImage->pt, /* pipe_texture (src) */
+ src_view, /* pipe_texture (src) */
0, 0, /* src x0, y0 */
width, height, /* src x1, y1 */
dst_surface, /* pipe_surface (dst) */
/* copy/pack data into user buffer */
if (st_equal_formats(stImage->pt->format, format, type)) {
/* memcpy */
- const uint bytesPerRow = width * pf_get_blocksize(stImage->pt->format);
- ubyte *map = screen->transfer_map(screen, tex_xfer);
+ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
+ ubyte *map = pipe->transfer_map(pipe, tex_xfer);
GLuint row;
for (row = 0; row < height; row++) {
GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
memcpy(dest, map, bytesPerRow);
map += tex_xfer->stride;
}
- screen->transfer_unmap(screen, tex_xfer);
+ pipe->transfer_unmap(pipe, tex_xfer);
}
else {
/* format translation via floats */
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);
+ pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba);
_mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
type, dest, &ctx->Pack, transferOps);
_mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+ screen->tex_transfer_destroy(tex_xfer);
+
/* destroy the temp / dest surface */
util_destroy_rgba_surface(dst_texture, dst_surface);
}
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 / pf_get_blocksize(stImage->pt->format);
+ texImage->RowStride = stImage->transfer->stride / util_format_get_blocksize(stImage->pt->format);
}
else {
/* Otherwise, the image should actually be stored in
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;
}
xoffset, yoffset,
width, height);
- srcBlockStride = pf_get_stride(pformat, width);
+ srcBlockStride = util_format_get_stride(pformat, width);
dstBlockStride = stImage->transfer->stride;
} else {
assert(stImage->pt);
return;
}
- assert(xoffset % pf_get_blockwidth(pformat) == 0);
- assert(yoffset % pf_get_blockheight(pformat) == 0);
- assert(width % pf_get_blockwidth(pformat) == 0);
- assert(height % pf_get_blockheight(pformat) == 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 += pf_get_blockheight(pformat)) {
+ 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(pformat, y);
- char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(pformat, y);
- memcpy(dst, src, pf_get_stride(pformat, 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) {
GLsizei width, GLsizei height)
{
struct pipe_context *pipe = ctx->st->pipe;
- struct pipe_screen *screen = pipe->screen;
struct pipe_transfer *src_trans;
GLvoid *texDest;
enum pipe_transfer_usage transfer_usage;
if ((baseFormat == GL_DEPTH_COMPONENT ||
baseFormat == GL_DEPTH_STENCIL) &&
- 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;
/* To avoid a large temp memory allocation, do copy row by row */
for (row = 0; row < height; row++, srcY += yStep) {
uint data[MAX_WIDTH];
- pipe_get_tile_z(src_trans, 0, srcY, width, 1, data);
+ pipe_get_tile_z(pipe, src_trans, 0, srcY, width, 1, data);
if (scaleOrBias) {
_mesa_scale_and_bias_depth_uint(ctx, width, data);
}
- pipe_put_tile_z(stImage->transfer, 0, row, width, 1, data);
+ pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data);
}
}
else {
/* RGBA format */
GLfloat *tempSrc =
- (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
if (tempSrc && texDest) {
const GLint dims = 2;
/* XXX this usually involves a lot of int/float conversion.
* try to avoid that someday.
*/
- pipe_get_tile_rgba(src_trans, 0, 0, width, height, tempSrc);
+ pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc);
/* Store into texture memory.
* Note that this does some special things such as pixel transfer
}
if (tempSrc)
- _mesa_free(tempSrc);
+ free(tempSrc);
}
st_texture_image_unmap(ctx->st, stImage);
- screen->tex_transfer_destroy(src_trans);
+ pipe->tex_transfer_destroy(pipe, src_trans);
}
+
+/**
+ * If the format of the src renderbuffer and the format of the dest
+ * texture are compatible (in terms of blitting), return a TGSI writemask
+ * to be used during the blit.
+ * If the src/dest are incompatible, return 0.
+ */
static unsigned
-compatible_src_dst_formats(const struct gl_renderbuffer *src,
+compatible_src_dst_formats(GLcontext *ctx,
+ const struct gl_renderbuffer *src,
const struct gl_texture_image *dst)
{
- const GLenum srcFormat = _mesa_get_format_base_format(src->Format);
- const GLenum dstLogicalFormat = _mesa_get_format_base_format(dst->TexFormat);
+ /* Get logical base formats for the src and dest.
+ * That is, use the user-requested formats and not the actual, device-
+ * chosen formats.
+ * For example, the user may have requested an A8 texture but the
+ * driver may actually be using an RGBA texture format. When we
+ * copy/blit to that texture, we only want to copy the Alpha channel
+ * and not the RGB channels.
+ *
+ * Similarly, when the src FBO was created an RGB format may have been
+ * requested but the driver actually chose an RGBA format. In that case,
+ * we don't want to copy the undefined Alpha channel to the dest texture
+ * (it should be 1.0).
+ */
+ const GLenum srcFormat = _mesa_base_fbo_format(ctx, src->InternalFormat);
+ const GLenum dstFormat = _mesa_base_tex_format(ctx, dst->InternalFormat);
- if (srcFormat == dstLogicalFormat) {
+ /**
+ * XXX when we have red-only and red/green renderbuffers we'll need
+ * to add more cases here (or implement a general-purpose routine that
+ * queries the existance of the R,G,B,A channels in the src and dest).
+ */
+ if (srcFormat == dstFormat) {
/* This is the same as matching_base_formats, which should
* always pass, as it did previously.
*/
return TGSI_WRITEMASK_XYZW;
}
- else if (srcFormat == GL_RGBA &&
- dstLogicalFormat == GL_RGB) {
- /* Add a single special case to cope with RGBA->RGB transfers,
- * setting A to 1.0 to cope with situations where the RGB
- * destination is actually stored as RGBA.
+ else if (srcFormat == GL_RGB && dstFormat == GL_RGBA) {
+ /* Make sure that A in the dest is 1. The actual src format
+ * may be RGBA and have undefined A values.
+ */
+ return TGSI_WRITEMASK_XYZ;
+ }
+ else if (srcFormat == GL_RGBA && dstFormat == GL_RGB) {
+ /* Make sure that A in the dest is 1. The actual dst format
+ * may be RGBA and will need A=1 to provide proper alpha values
+ * when sampled later.
*/
- return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */
+ return TGSI_WRITEMASK_XYZ;
}
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));
+ _mesa_lookup_enum_by_nr(dstFormat));
/* Otherwise fail.
*/
matching_base_formats =
(_mesa_get_format_base_format(strb->Base.Format) ==
_mesa_get_format_base_format(texImage->TexFormat));
- format_writemask = compatible_src_dst_formats(&strb->Base, texImage);
+ format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
if (ctx->_ImageTransferState == 0x0) {
}
util_blit_pixels_writemask(ctx->st->blit,
strb->surface,
+ st_renderbuffer_get_sampler_view(strb, pipe),
srcX, srcY0,
srcX + width, srcY1,
dest_surface,
st_texture_image_copy(st->pipe,
stObj->pt, dstLevel, /* dest texture, level */
stImage->pt, /* src texture */
- stImage->face
- );
+ stImage->face);
pipe_texture_reference(&stImage->pt, NULL);
}
else if (stImage->base.Data) {
/* More straightforward upload.
*/
-
st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel,
PIPE_TRANSFER_WRITE);
-
st_texture_image_data(st,
stObj->pt,
stImage->face,
dstLevel,
stImage->base.Data,
stImage->base.RowStride *
- pf_get_blocksize(stObj->pt->format),
+ util_format_get_blocksize(stObj->pt->format),
stImage->base.RowStride *
stImage->base.Height *
- pf_get_blocksize(stObj->pt->format));
+ util_format_get_blocksize(stObj->pt->format));
_mesa_align_free(stImage->base.Data);
stImage->base.Data = NULL;
}
firstImage->pt != stObj->pt &&
firstImage->pt->last_level >= stObj->lastLevel) {
pipe_texture_reference(&stObj->pt, firstImage->pt);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
}
/* bytes per pixel block (blocks are usually 1x1) */
stObj->pt->depth0 != firstImage->base.Depth2)
{
pipe_texture_reference(&stObj->pt, NULL);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
}
}