st/mesa: Make st_cb_drawtex.h FEATURE_OES_draw_texture aware.
[mesa.git] / src / mesa / state_tracker / st_cb_texture.c
index fd801a354b15ba055bec666f8416040e26d54053..e34fd09dcb753f468310695d74e11f2668d30e6d 100644 (file)
@@ -27,9 +27,6 @@
 
 #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"
@@ -259,8 +256,9 @@ get_texture_dims(GLenum target)
  * 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)
@@ -291,7 +289,8 @@ guess_and_alloc_texture(struct st_context *st,
            (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;
       }
    }
 
@@ -312,10 +311,11 @@ guess_and_alloc_texture(struct st_context *st,
     * 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 ||
@@ -352,7 +352,9 @@ guess_and_alloc_texture(struct st_context *st,
                                  depth,
                                  bindings);
 
-   DBG("%s - success\n", __FUNCTION__);
+   DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
+
+   return stObj->pt != NULL;
 }
 
 
@@ -462,7 +464,7 @@ compress_with_blit(GLcontext * ctx,
 
    /* 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 */
@@ -528,8 +530,6 @@ st_TexImage(GLcontext * ctx,
    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;
@@ -537,6 +537,12 @@ st_TexImage(GLcontext * ctx,
    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);
@@ -553,39 +559,17 @@ st_TexImage(GLcontext * ctx,
       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.
     */
@@ -618,14 +602,12 @@ st_TexImage(GLcontext * ctx,
    }
 
    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;
          }
@@ -634,9 +616,13 @@ st_TexImage(GLcontext * ctx,
 
    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);
@@ -645,9 +631,11 @@ st_TexImage(GLcontext * ctx,
    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,
@@ -660,10 +648,6 @@ st_TexImage(GLcontext * ctx,
                                           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 &&
@@ -682,7 +666,12 @@ st_TexImage(GLcontext * ctx,
       }
    }
 
+   /*
+    * 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;
@@ -690,28 +679,17 @@ st_TexImage(GLcontext * ctx,
          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) {
@@ -719,33 +697,33 @@ st_TexImage(GLcontext * ctx,
       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;
          }
       }
    }
@@ -774,8 +752,7 @@ st_TexImage(GLcontext * ctx,
             /* 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;
         }
       }
@@ -898,7 +875,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
                         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);
@@ -984,11 +961,6 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
       /* 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,
@@ -1120,16 +1092,12 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
     * 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,
@@ -1252,11 +1220,8 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
    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,
@@ -1340,7 +1305,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
       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,
@@ -1354,9 +1319,6 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
    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);
 
@@ -1538,9 +1500,6 @@ st_copy_texsubimage(GLcontext *ctx,
    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);
@@ -1801,17 +1760,12 @@ copy_image_data_to_texture(struct st_context *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,
@@ -1838,8 +1792,7 @@ copy_image_data_to_texture(struct st_context *st,
 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);
@@ -1848,8 +1801,6 @@ st_finalize_texture(GLcontext *ctx,
    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
@@ -1926,7 +1877,7 @@ st_finalize_texture(GLcontext *ctx,
     */
    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]);
 
@@ -1934,7 +1885,6 @@ st_finalize_texture(GLcontext *ctx,
           */
          if (stImage && stObj->pt != stImage->pt) {
             copy_image_data_to_texture(st, stObj, level, stImage);
-           *needFlush = GL_TRUE;
          }
       }
    }