#include "main/mfeatures.h"
#include "main/bufferobj.h"
-#if FEATURE_convolve
-#include "main/convolve.h"
-#endif
#include "main/enums.h"
#include "main/fbobject.h"
#include "main/formats.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_flush.h"
#include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_format.h"
#include "state_tracker/st_texture.h"
#include "state_tracker/st_gen_mipmap.h"
-#include "state_tracker/st_inlines.h"
#include "state_tracker/st_atom.h"
#include "pipe/p_context.h"
* We use the given st_texture_image as a clue to determine the size of the
* mipmap image at level=0.
*
+ * \return GL_TRUE for success, GL_FALSE if out of memory.
*/
-static void
+static GLboolean
guess_and_alloc_texture(struct st_context *st,
struct st_texture_object *stObj,
const struct st_texture_image *stImage)
(dims >= 3 && depth == 1) ) {
/* we can't determine the image size at level=0 */
stObj->width0 = stObj->height0 = stObj->depth0 = 0;
- return;
+ /* this is not an out of memory error */
+ return GL_TRUE;
}
}
* the level=0 mipmap image.
*/
- /* Guess a reasonable value for lastLevel. This is probably going
- * to be wrong fairly often and might mean that we have to look at
- * resizable buffers, or require that buffers implement lazy
- * pagetable arrangements.
+ /* Guess a reasonable value for lastLevel. With OpenGL we have no
+ * idea how many mipmap levels will be in a texture until we start
+ * to render with it. Make an educated guess here but be prepared
+ * to re-allocating a texture buffer with space for more (or fewer)
+ * mipmap levels later.
*/
if ((stObj->base.MinFilter == GL_NEAREST ||
stObj->base.MinFilter == GL_LINEAR ||
depth,
bindings);
- DBG("%s - success\n", __FUNCTION__);
+ DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
+
+ return stObj->pt != NULL;
}
/* Put user's tex data into the temporary texture
*/
- tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex,
+ tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex,
0, 0, 0, /* face, level are zero */
PIPE_TRANSFER_WRITE,
0, 0, width, height); /* x, y, w, h */
struct pipe_screen *screen = st->pipe->screen;
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
- GLint postConvWidth, postConvHeight;
- GLint texelBytes, sizeInBytes;
GLuint dstRowStride = 0;
struct gl_pixelstore_attrib unpackNB;
enum pipe_transfer_usage transfer_usage = 0;
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
+ /* The Mesa/Gallium state tracker does not implement the imaging extensions
+ * such as convolution.
+ */
+ assert(!ctx->Extensions.ARB_imaging);
+ assert(!ctx->Extensions.EXT_convolution);
+
/* switch to "normal" */
if (stObj->surface_based) {
_mesa_clear_texture_object(ctx, texObj);
texImage->Border = 0;
border = 0;
}
-
- postConvWidth = width;
- postConvHeight = height;
+ else {
+ assert(texImage->Width == width);
+ assert(texImage->Height == height);
+ assert(texImage->Depth == depth);
+ }
stImage->face = _mesa_tex_target_to_face(target);
stImage->level = level;
-#if FEATURE_convolve
- if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
- _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
- &postConvHeight);
- }
-#endif
-
_mesa_set_fetch_functions(texImage, dims);
- if (_mesa_is_format_compressed(texImage->TexFormat)) {
- /* must be a compressed format */
- texelBytes = 0;
- }
- else {
- texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
-
- /* Minimum pitch of 32 bytes */
- if (postConvWidth * texelBytes < 32) {
- postConvWidth = 32 / texelBytes;
- texImage->RowStride = postConvWidth;
- }
-
- /* we'll set RowStride elsewhere when the texture is a "mapped" state */
- /*assert(texImage->RowStride == postConvWidth);*/
- }
-
/* Release the reference to a potentially orphaned buffer.
* Release any old malloced memory.
*/
}
if (!stObj->pt) {
- guess_and_alloc_texture(st, stObj, stImage);
- if (!stObj->pt) {
+ if (!guess_and_alloc_texture(st, stObj, stImage)) {
/* Probably out of memory.
* Try flushing any pending rendering, then retry.
*/
st_finish(st);
- guess_and_alloc_texture(st, stObj, stImage);
- if (!stObj->pt) {
+ if (!guess_and_alloc_texture(st, stObj, stImage)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
return;
}
assert(!stImage->pt);
+ /* Check if this texture image can live inside the texture object's buffer.
+ * If so, store the image there. Otherwise the image will temporarily live
+ * in its own buffer.
+ */
if (stObj->pt &&
st_texture_match_image(stObj->pt, &stImage->base,
- stImage->face, stImage->level)) {
+ stImage->face, stImage->level)) {
pipe_resource_reference(&stImage->pt, stObj->pt);
assert(stImage->pt);
if (!stImage->pt)
DBG("XXX: Image did not fit into texture - storing in local memory!\n");
- /* st_CopyTexImage calls this function with pixels == NULL, with
- * the expectation that the texture will be set up but nothing
- * more will be done. This is where those calls return:
+ /* Pixel data may come from regular user memory or a PBO. For the later,
+ * do bounds checking and map the PBO to read pixels data from it.
+ *
+ * XXX we should try to use a GPU-accelerated path to copy the image data
+ * from the PBO to the texture.
*/
if (compressed_src) {
pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
pixels, unpack, "glTexImage");
}
- /* Note: we can't check for pixels==NULL until after we've allocated
- * memory for the texture.
- */
-
/* See if we can do texture compression with a blit/render.
*/
if (!compressed_src &&
}
}
+ /*
+ * Prepare to store the texture data. Either map the gallium texture buffer
+ * memory or malloc space for it.
+ */
if (stImage->pt) {
+ /* Store the image in the gallium texture memory buffer */
if (format == GL_DEPTH_COMPONENT &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
transfer_usage = PIPE_TRANSFER_WRITE;
texImage->Data = st_texture_image_map(st, stImage, 0,
- transfer_usage, 0, 0,
- stImage->base.Width,
- stImage->base.Height);
+ transfer_usage, 0, 0, width, height);
if(stImage->transfer)
dstRowStride = stImage->transfer->stride;
}
else {
/* Allocate regular memory and store the image there temporarily. */
- if (_mesa_is_format_compressed(texImage->TexFormat)) {
- sizeInBytes = _mesa_format_image_size(texImage->TexFormat,
- texImage->Width,
- texImage->Height,
- texImage->Depth);
- dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
- assert(dims != 3);
- }
- else {
- dstRowStride = postConvWidth * texelBytes;
- sizeInBytes = depth * dstRowStride * postConvHeight;
- }
+ GLuint imageSize = _mesa_format_image_size(texImage->TexFormat,
+ width, height, depth);
+ dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
- texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
+ texImage->Data = _mesa_align_malloc(imageSize, 16);
}
if (!texImage->Data) {
return;
}
- if (!pixels)
+ if (!pixels) {
+ /* We've allocated texture memory, but have no pixel data - all done. */
goto done;
+ }
DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
- width, height, depth, width * texelBytes, dstRowStride);
+ width, height, depth, width, dstRowStride);
- /* Copy data. Would like to know when it's ok for us to eg. use
- * the blitter to copy. Or, use the hardware to do the format
- * conversion and copy:
+ /* Copy user texture image into the texture buffer.
*/
if (compressed_src) {
- const GLuint srcImageStride = _mesa_format_row_stride(texImage->TexFormat, width);
- if(dstRowStride == srcImageStride)
+ const GLuint srcRowStride =
+ _mesa_format_row_stride(texImage->TexFormat, width);
+ if (dstRowStride == srcRowStride) {
memcpy(texImage->Data, pixels, imageSize);
- else
- {
+ }
+ 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);
+ for (i = 0; i < lines; ++i) {
+ memcpy(dst, src, srcRowStride);
dst += dstRowStride;
- src += srcImageStride;
+ src += srcRowStride;
}
}
}
/* map next slice of 3D texture */
texImage->Data = st_texture_image_map(st, stImage, i + 1,
transfer_usage, 0, 0,
- stImage->base.Width,
- stImage->base.Height);
+ width, height);
src += srcImageStride;
}
}
PIPE_TEX_MIPFILTER_NEAREST);
/* map the dst_surface so we can read from it */
- tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+ tex_xfer = pipe_get_transfer(st_context(ctx)->pipe,
dst_texture, 0, 0, 0,
PIPE_TRANSFER_READ,
0, 0, width, height);
/* Image is stored in hardware format in a buffer managed by the
* kernel. Need to explicitly map and unmap it.
*/
- unsigned face = _mesa_tex_target_to_face(target);
-
- st_teximage_flush_before_map(st, stImage->pt, face, level,
- PIPE_TRANSFER_READ);
-
texImage->Data = st_texture_image_map(st, stImage, 0,
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
* from uploading the buffer under us.
*/
if (stImage->pt) {
- unsigned face = _mesa_tex_target_to_face(target);
-
if (format == GL_DEPTH_COMPONENT &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
- st_teximage_flush_before_map(st, stImage->pt, face, level,
- transfer_usage);
texImage->Data = st_texture_image_map(st, stImage, zoffset,
transfer_usage,
xoffset, yoffset,
enum pipe_format pformat;
if (stImage->pt) {
- unsigned face = _mesa_tex_target_to_face(target);
pformat = stImage->pt->format;
- st_teximage_flush_before_map(st, stImage->pt, face, level,
- PIPE_TRANSFER_WRITE);
texImage->Data = st_texture_image_map(st, stImage, 0,
PIPE_TRANSFER_WRITE,
xoffset, yoffset,
srcY = strb->Base.Height - srcY - height;
}
- src_trans = st_cond_flush_get_tex_transfer( st_context(ctx),
+ src_trans = pipe_get_transfer(st_context(ctx)->pipe,
strb->texture,
0, 0, 0,
PIPE_TRANSFER_READ,
else
transfer_usage = PIPE_TRANSFER_WRITE;
- st_teximage_flush_before_map(st, stImage->pt, 0, 0,
- transfer_usage);
-
texDest = st_texture_image_map(st, stImage, 0, transfer_usage,
destX, destY, width, height);
struct pipe_surface *dest_surface = NULL;
GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
- /* any rendering in progress must flushed before we grab the fb image */
- st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
/* make sure finalize_textures has been called?
*/
if (0) st_validate_state(st);
*/
st_texture_image_copy(st->pipe,
stObj->pt, dstLevel, /* dest texture, level */
- stImage->pt, /* src texture */
+ stImage->pt, stImage->level, /* src texture, level */
stImage->face);
pipe_resource_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,
GLboolean
st_finalize_texture(GLcontext *ctx,
struct pipe_context *pipe,
- struct gl_texture_object *tObj,
- GLboolean *needFlush)
+ struct gl_texture_object *tObj)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(tObj);
struct st_texture_image *firstImage;
enum pipe_format firstImageFormat;
- *needFlush = GL_FALSE;
-
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
*/
for (face = 0; face < nr_faces; face++) {
GLuint level;
- for (level = 0; level <= stObj->lastLevel; level++) {
+ for (level = stObj->base.BaseLevel; level <= stObj->lastLevel; level++) {
struct st_texture_image *stImage =
st_texture_image(stObj->base.Image[face][level]);
*/
if (stImage && stObj->pt != stImage->pt) {
copy_image_data_to_texture(st, stObj, level, stImage);
- *needFlush = GL_TRUE;
}
}
}