Ejemplo n.º 1
0
/**
 * Clear all fields of texture object to zeros.  Used for proxy texture tests.
 * Used for proxy texture tests (and to clean up when a texture memory
 * allocation fails).
 */
static void
clear_texture_fields(struct gl_context *ctx,
                     struct gl_texture_object *texObj)
{
   const GLenum target = texObj->Target;
   const GLuint numFaces = _mesa_num_tex_faces(target);
   GLint level;
   GLuint face;

   for (level = 0; level < Elements(texObj->Image[0]); level++) {
      for (face = 0; face < numFaces; face++) {
         struct gl_texture_image *texImage =
            get_tex_image(ctx, texObj, face, level);

	 if (!texImage) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
            return;
	 }

         _mesa_init_teximage_fields(ctx, texImage,
                                    0, 0, 0, 0, /* w, h, d, border */
                                    GL_NONE, MESA_FORMAT_NONE);
      }
   }
}
Ejemplo n.º 2
0
static GLboolean
initialize_texture_fields(struct gl_context *ctx,
                          struct gl_texture_object *texObj,
                          GLint levels,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum internalFormat, mesa_format texFormat)
{
   const GLenum target = texObj->Target;
   const GLuint numFaces = _mesa_num_tex_faces(target);
   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
   GLuint face;

   /* Set up all the texture object's gl_texture_images */
   for (level = 0; level < levels; level++) {
      for (face = 0; face < numFaces; face++) {
         struct gl_texture_image *texImage =
            get_tex_image(ctx, texObj, face, level);

	 if (!texImage) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
            return GL_FALSE;
	 }

         _mesa_init_teximage_fields(ctx, texImage,
                                    levelWidth, levelHeight, levelDepth,
                                    0, internalFormat, texFormat);
      }

      _mesa_next_mipmap_level_size(target, 0,
                                   levelWidth, levelHeight, levelDepth,
                                   &levelWidth, &levelHeight, &levelDepth);
   }
   return GL_TRUE;
}
Ejemplo n.º 3
0
/**
 * Create a new mipmap tree, calculate its layout and allocate memory.
 */
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
					  GLenum target, mesa_format mesaFormat, GLuint baseLevel, GLuint numLevels,
					  GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
{
	radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);

	radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
		"%s(%p) new tree is %p.\n",
		__func__, rmesa, mt);

	mt->mesaFormat = mesaFormat;
	mt->refcount = 1;
	mt->target = target;
	mt->faces = _mesa_num_tex_faces(target);
	mt->baseLevel = baseLevel;
	mt->numLevels = numLevels;
	mt->width0 = width0;
	mt->height0 = height0;
	mt->depth0 = depth0;
	mt->tilebits = tilebits;

	calculate_miptree_layout(rmesa, mt);

	mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
                            0, mt->totalsize, 1024,
                            RADEON_GEM_DOMAIN_VRAM,
                            0);

	return mt;
}
Ejemplo n.º 4
0
/**
 * ctx->Driver.AllocTextureStorage() handler.
 *
 * Compare this to _mesa_alloc_texture_storage, which would call into
 * intel_alloc_texture_image_buffer() above.
 */
static GLboolean
intel_alloc_texture_storage(struct gl_context *ctx,
                            struct gl_texture_object *texobj,
                            GLsizei levels, GLsizei width,
                            GLsizei height, GLsizei depth)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   struct gl_texture_image *first_image = texobj->Image[0][0];
   int num_samples = intel_quantize_num_samples(brw->intelScreen,
                                                first_image->NumSamples);
   const int numFaces = _mesa_num_tex_faces(texobj->Target);
   int face;
   int level;

   /* If the object's current miptree doesn't match what we need, make a new
    * one.
    */
   if (!intel_texobj->mt ||
       !intel_miptree_match_image(intel_texobj->mt, first_image) ||
       intel_texobj->mt->last_level != levels - 1) {
      intel_miptree_release(&intel_texobj->mt);
      intel_texobj->mt = intel_miptree_create(brw, texobj->Target,
                                              first_image->TexFormat,
                                              0, levels - 1,
                                              width, height, depth,
                                              false, /* expect_accelerated */
                                              num_samples,
                                              INTEL_MIPTREE_TILING_ANY,
                                              false);

      if (intel_texobj->mt == NULL) {
         return false;
      }
   }

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < levels; level++) {
         struct gl_texture_image *image = texobj->Image[face][level];
         struct intel_texture_image *intel_image = intel_texture_image(image);

         image->NumSamples = num_samples;

         _swrast_free_texture_image_buffer(ctx, image);
         if (!_swrast_init_texture_image(image))
            return false;

         intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
      }
   }

   /* The miptree is in a validated state, so no need to check later. */
   intel_texobj->needs_validate = false;
   intel_texobj->validated_first_level = 0;
   intel_texobj->validated_last_level = levels - 1;
   intel_texobj->_Format = intel_texobj->mt->format;

   return true;
}
Ejemplo n.º 5
0
/**
 * Update/re-validate framebuffer object.
 */
static void
update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
{
   const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
   for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
      for (unsigned face = 0; face < numFaces; face++)
         _mesa_update_fbo_texture(ctx, texObj, face, level);
   }
}
Ejemplo n.º 6
0
/**
 * Called via ctx->Driver.AllocTextureStorage() to allocate texture memory
 * for a whole mipmap stack.
 */
static GLboolean
st_AllocTextureStorage(struct gl_context *ctx,
                       struct gl_texture_object *texObj,
                       GLsizei levels, GLsizei width,
                       GLsizei height, GLsizei depth)
{
   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   GLuint ptWidth, ptHeight, ptDepth, ptLayers, bindings;
   enum pipe_format fmt;
   GLint level;

   assert(levels > 0);

   /* Save the level=0 dimensions */
   stObj->width0 = width;
   stObj->height0 = height;
   stObj->depth0 = depth;
   stObj->lastLevel = levels - 1;

   fmt = st_mesa_format_to_pipe_format(texObj->Image[0][0]->TexFormat);

   bindings = default_bindings(st, fmt);

   st_gl_texture_dims_to_pipe_dims(texObj->Target,
                                   width, height, depth,
                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);

   stObj->pt = st_texture_create(st,
                                 gl_target_to_pipe(texObj->Target),
                                 fmt,
                                 levels,
                                 ptWidth,
                                 ptHeight,
                                 ptDepth,
                                 ptLayers,
                                 bindings);
   if (!stObj->pt)
      return GL_FALSE;

   /* Set image resource pointers */
   for (level = 0; level < levels; level++) {
      GLuint face;
      for (face = 0; face < numFaces; face++) {
         struct st_texture_image *stImage =
            st_texture_image(texObj->Image[face][level]);
         pipe_resource_reference(&stImage->pt, stObj->pt);
      }
   }

   return GL_TRUE;
}
Ejemplo n.º 7
0
void
radeon_swrast_map_texture_images(struct gl_context *ctx,
                                 struct gl_texture_object *texObj)
{
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    GLuint nr_faces = _mesa_num_tex_faces(texObj->Target);
    int i, face;

    for (i = texObj->BaseLevel; i <= texObj->_MaxLevel; i++) {
        for (face = 0; face < nr_faces; face++) {
            radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][i]);
            radeon_swrast_map_image(rmesa, image);
        }
    }
}
void
intel_tex_unmap_images(struct intel_context *intel,
		       struct intel_texture_object *intelObj)
{
   GLuint nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   int i, face;

   for (i = intelObj->base.BaseLevel; i <= intelObj->_MaxLevel; i++) {
      for (face = 0; face < nr_faces; face++) {
	 struct intel_texture_image *intel_image =
	    intel_texture_image(intelObj->base.Image[face][i]);

	 intel_tex_unmap_image_for_swrast(intel, intel_image);
      }
   }
}
Ejemplo n.º 9
0
static GLboolean
intel_texture_view(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   struct gl_texture_object *origTexObj)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_object *intel_tex = intel_texture_object(texObj);
   struct intel_texture_object *intel_orig_tex = intel_texture_object(origTexObj);

   assert(intel_orig_tex->mt);
   intel_miptree_reference(&intel_tex->mt, intel_orig_tex->mt);

   /* Since we can only make views of immutable-format textures,
    * we can assume that everything is in origTexObj's miptree.
    *
    * Mesa core has already made us a copy of all the teximage objects,
    * except it hasn't copied our mt pointers, etc.
    */
   const int numFaces = _mesa_num_tex_faces(texObj->Target);
   const int numLevels = texObj->NumLevels;

   int face;
   int level;

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < numLevels; level++) {
         struct gl_texture_image *image = texObj->Image[face][level];
         struct intel_texture_image *intel_image = intel_texture_image(image);

         intel_miptree_reference(&intel_image->mt, intel_orig_tex->mt);
      }
   }

   /* The miptree is in a validated state, so no need to check later. */
   intel_tex->needs_validate = false;
   intel_tex->validated_first_level = 0;
   intel_tex->validated_last_level = numLevels - 1;

   /* Set the validated texture format, with the same adjustments that
    * would have been applied to determine the underlying texture's
    * mt->format.
    */
   intel_tex->_Format = intel_depth_format_for_depthstencil_format(
         intel_lower_compressed_format(brw, texObj->Image[0][0]->TexFormat));

   return GL_TRUE;
}
Ejemplo n.º 10
0
/**
 * Initialize new texture's gl_texture_image structures. Will not call driver
 * to allocate new space, simply record relevant layer, face, format, etc.
 * \return GL_FALSE if any error, GL_TRUE otherwise.
 */
static GLboolean
initialize_texture_fields(struct gl_context *ctx,
                          GLenum target,
                          struct gl_texture_object *texObj,
                          GLint levels,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum internalFormat, mesa_format texFormat)
{
   const GLuint numFaces = _mesa_num_tex_faces(target);
   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
   GLuint face;

   /* Pretend we are bound to initialize the gl_texture_image structs */
   texObj->Target = target;

   /* Set up all the texture object's gl_texture_images */
   for (level = 0; level < levels; level++) {
      for (face = 0; face < numFaces; face++) {
         struct gl_texture_image *texImage;
         GLenum faceTarget = target;

         if (target == GL_TEXTURE_CUBE_MAP)
            faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;

         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level);

         if (!texImage) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
            return GL_FALSE;
         }

         _mesa_init_teximage_fields(ctx, texImage,
                                    levelWidth, levelHeight, levelDepth,
                                    0, internalFormat, texFormat);
      }

      _mesa_next_mipmap_level_size(target, 0,
                                   levelWidth, levelHeight, levelDepth,
                                   &levelWidth, &levelHeight, &levelDepth);
   }

   /* "unbind" */
   texObj->Target = 0;

   return GL_TRUE;
}
Ejemplo n.º 11
0
/**
 * Compute the size of the given texture object, in bytes.
 */
static GLuint
texture_size(const struct gl_texture_object *texObj)
{
   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
   GLuint face, level, size = 0;

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
         const struct gl_texture_image *img = texObj->Image[face][level];
         if (img) {
            GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
                                                img->Height, img->Depth);
            size += sz;
         }
      }
   }

   return size;
}
/**
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
 */
void
intel_tex_map_images(struct intel_context *intel,
		     struct intel_texture_object *intelObj,
		     GLbitfield mode)
{
   GLuint nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   int i, face;

   DBG("%s\n", __FUNCTION__);

   for (i = intelObj->base.BaseLevel; i <= intelObj->_MaxLevel; i++) {
      for (face = 0; face < nr_faces; face++) {
	 struct intel_texture_image *intel_image =
	    intel_texture_image(intelObj->base.Image[face][i]);

	 intel_tex_map_image_for_swrast(intel, intel_image, mode);
      }
   }
}
Ejemplo n.º 13
0
/**
 * Called via ctx->Driver.AllocTextureStorage()
 * Just have to allocate memory for the texture images.
 */
static GLboolean
intel_alloc_texture_storage(struct gl_context *ctx,
                            struct gl_texture_object *texObj,
                            GLsizei levels, GLsizei width,
                            GLsizei height, GLsizei depth)
{
   const int numFaces = _mesa_num_tex_faces(texObj->Target);
   int face;
   int level;

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < levels; level++) {
         struct gl_texture_image *const texImage = texObj->Image[face][level];
         if (!intel_alloc_texture_image_buffer(ctx, texImage))
            return false;
      }
   }

   return true;
}
Ejemplo n.º 14
0
/**
 * Clear all fields of texture object to zeros.  Used for proxy texture tests
 * and to clean up when a texture memory allocation fails.
 */
static void
clear_texture_fields(struct gl_context *ctx,
                     struct gl_texture_object *texObj)
{
   const GLenum target = texObj->Target;
   const GLuint numFaces = _mesa_num_tex_faces(target);
   GLint level;
   GLuint face;

   for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
      for (face = 0; face < numFaces; face++) {
         struct gl_texture_image *texImage =
            get_tex_image(ctx, texObj, face, level);

	 if (!texImage) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
            return;
	 }

         _mesa_clear_texture_image(ctx, texImage);
      }
   }
}
Ejemplo n.º 15
0
/**
 * Default ctx->Driver.AllocTextureStorage() handler.
 *
 * The driver can override this with a more specific implementation if it
 * desires, but this can be used to get the texture images allocated using the
 * usual texture image handling code.  The immutability of
 * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable
 * checks at glTexImage* time.
 */
GLboolean
_mesa_AllocTextureStorage_sw(struct gl_context *ctx,
                             struct gl_texture_object *texObj,
                             GLsizei levels, GLsizei width,
                             GLsizei height, GLsizei depth)
{
   const int numFaces = _mesa_num_tex_faces(texObj->Target);
   int face;
   int level;

   (void) width;
   (void) height;
   (void) depth;

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < levels; level++) {
         struct gl_texture_image *const texImage = texObj->Image[face][level];
         if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage))
            return GL_FALSE;
      }
   }

   return GL_TRUE;
}
Ejemplo n.º 16
0
/**
 * Examine a texture object to determine if it is complete.
 *
 * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
 * accordingly.
 *
 * \param ctx GL context.
 * \param t texture object.
 *
 * According to the texture target, verifies that each of the mipmaps is
 * present and has the expected size.
 */
void
_mesa_test_texobj_completeness( const struct gl_context *ctx,
                                struct gl_texture_object *t )
{
   const GLint baseLevel = t->BaseLevel;
   const struct gl_texture_image *baseImage;
   GLint maxLog2 = 0, maxLevels = 0;

   /* We'll set these to FALSE if tests fail below */
   t->_BaseComplete = GL_TRUE;
   t->_MipmapComplete = GL_TRUE;

   if (t->Target == GL_TEXTURE_BUFFER) {
      /* Buffer textures are always considered complete.  The obvious case where
       * they would be incomplete (no BO attached) is actually specced to be
       * undefined rendering results.
       */
      return;
   }

   /* Detect cases where the application set the base level to an invalid
    * value.
    */
   if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
      incomplete(t, BASE, "base level = %d is invalid", baseLevel);
      return;
   }

   if (t->MaxLevel < baseLevel) {
      incomplete(t, BASE, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
		 t->MaxLevel, baseLevel);
      return;
   }

   baseImage = t->Image[0][baseLevel];

   /* Always need the base level image */
   if (!baseImage) {
      incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
      return;
   }

   /* Check width/height/depth for zero */
   if (baseImage->Width == 0 ||
       baseImage->Height == 0 ||
       baseImage->Depth == 0) {
      incomplete(t, BASE, "texture width or height or depth = 0");
      return;
   }

   /* Check if the texture values are integer */
   {
      GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
      t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
   }

   /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the
    * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state).
    */
   switch (t->Target) {
   case GL_TEXTURE_1D:
   case GL_TEXTURE_1D_ARRAY_EXT:
      maxLog2 = baseImage->WidthLog2;
      maxLevels = ctx->Const.MaxTextureLevels;
      break;
   case GL_TEXTURE_2D:
   case GL_TEXTURE_2D_ARRAY_EXT:
      maxLog2 = MAX2(baseImage->WidthLog2,
                     baseImage->HeightLog2);
      maxLevels = ctx->Const.MaxTextureLevels;
      break;
   case GL_TEXTURE_3D:
      maxLog2 = MAX3(baseImage->WidthLog2,
                     baseImage->HeightLog2,
                     baseImage->DepthLog2);
      maxLevels = ctx->Const.Max3DTextureLevels;
      break;
   case GL_TEXTURE_CUBE_MAP_ARB:
      maxLog2 = MAX2(baseImage->WidthLog2,
                     baseImage->HeightLog2);
      maxLevels = ctx->Const.MaxCubeTextureLevels;
      break;
   case GL_TEXTURE_RECTANGLE_NV:
   case GL_TEXTURE_BUFFER:
   case GL_TEXTURE_EXTERNAL_OES:
      maxLog2 = 0;  /* not applicable */
      maxLevels = 1;  /* no mipmapping */
      break;
   default:
      _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
      return;
   }

   ASSERT(maxLevels > 0);

   t->_MaxLevel = baseLevel + maxLog2;  /* 'p' in the GL spec */
   t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
   t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* 'q' in the GL spec */

   /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
   t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);

   if (t->Immutable) {
      /* This texture object was created with glTexStorage1/2/3D() so we
       * know that all the mipmap levels are the right size and all cube
       * map faces are the same size.
       * We don't need to do any of the additional checks below.
       */
      return;
   }

   if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
      /* Make sure that all six cube map level 0 images are the same size.
       * Note:  we know that the image's width==height (we enforce that
       * at glTexImage time) so we only need to test the width here.
       */
      GLuint face;
      assert(baseImage->Width2 == baseImage->Height);
      for (face = 1; face < 6; face++) {
         assert(t->Image[face][baseLevel] == NULL ||
                t->Image[face][baseLevel]->Width2 ==
                t->Image[face][baseLevel]->Height2);
         if (t->Image[face][baseLevel] == NULL ||
             t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
            incomplete(t, BASE, "Cube face missing or mismatched size");
            return;
         }
      }
   }

   /*
    * Do mipmap consistency checking.
    * Note: we don't care about the current texture sampler state here.
    * To determine texture completeness we'll either look at _BaseComplete
    * or _MipmapComplete depending on the current minification filter mode.
    */
   {
      GLint i;
      const GLint minLevel = baseLevel;
      const GLint maxLevel = t->_MaxLevel;
      const GLuint numFaces = _mesa_num_tex_faces(t->Target);
      GLuint width, height, depth, face;

      if (minLevel > maxLevel) {
         incomplete(t, BASE, "minLevel > maxLevel");
         return;
      }

      /* Get the base image's dimensions */
      width = baseImage->Width2;
      height = baseImage->Height2;
      depth = baseImage->Depth2;

      /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL textures */
      for (i = baseLevel + 1; i < maxLevels; i++) {
         /* Compute the expected size of image at level[i] */
         if (width > 1) {
            width /= 2;
         }
         if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
            height /= 2;
         }
         if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY) {
            depth /= 2;
         }

         /* loop over cube faces (or single face otherwise) */
         for (face = 0; face < numFaces; face++) {
            if (i >= minLevel && i <= maxLevel) {
               const struct gl_texture_image *img = t->Image[face][i];

               if (!img) {
                  incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
                  return;
               }
               if (img->TexFormat != baseImage->TexFormat) {
                  incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
                  return;
               }
               if (img->Border != baseImage->Border) {
                  incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
                  return;
               }
               if (img->Width2 != width) {
                  incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, img->Width2);
                  return;
               }
               if (img->Height2 != height) {
                  incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, img->Height2);
                  return;
               }
               if (img->Depth2 != depth) {
                  incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, img->Depth2);
                  return;
               }

               /* Extra checks for cube textures */
               if (face > 0) {
                  /* check that cube faces are the same size */
                  if (img->Width2 != t->Image[0][i]->Width2 || 
                      img->Height2 != t->Image[0][i]->Height2) {
		     incomplete(t, MIPMAP, "CubeMap Image[n][i] bad size");
		     return;
		  }
               }
            }
         }
         
         if (width == 1 && height == 1 && depth == 1) {
            return;  /* found smallest needed mipmap, all done! */
         }
      }
   }
}
Ejemplo n.º 17
0
/**
 * Validate texture mipmap tree.
 * If individual images are stored in different mipmap trees
 * use the mipmap tree that has the most of the correct data.
 */
int radeon_validate_texture_miptree(struct gl_context * ctx,
				    struct gl_sampler_object *samp,
				    struct gl_texture_object *texObj)
{
	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
	radeonTexObj *t = radeon_tex_obj(texObj);
	radeon_mipmap_tree *dst_miptree;

	if (samp == &texObj->Sampler && (t->validated || t->image_override)) {
		return GL_TRUE;
	}

	calculate_min_max_lod(samp, &t->base, &t->minLod, &t->maxLod);

	radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
			"%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
			__func__, texObj ,t->minLod, t->maxLod);

	dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base._MaxLevel);

	radeon_miptree_unreference(&t->mt);
	if (!dst_miptree) {
		radeon_try_alloc_miptree(rmesa, t);
		radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
			"%s: No matching miptree found, allocated new one %p\n",
			__func__, t->mt);

	} else {
		radeon_miptree_reference(dst_miptree, &t->mt);
		radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
			"%s: Using miptree %p\n", __func__, t->mt);
	}

	const unsigned faces = _mesa_num_tex_faces(texObj->Target);
	unsigned face, level;
	radeon_texture_image *img;
	/* Validate only the levels that will actually be used during rendering */
	for (face = 0; face < faces; ++face) {
		for (level = t->minLod; level <= t->maxLod; ++level) {
			img = get_radeon_texture_image(texObj->Image[face][level]);

			radeon_print(RADEON_TEXTURE, RADEON_TRACE,
				"Checking image level %d, face %d, mt %p ... ",
				level, face, img->mt);
			
			if (img->mt != t->mt && !img->used_as_render_target) {
				radeon_print(RADEON_TEXTURE, RADEON_TRACE,
					"MIGRATING\n");

				struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo;
				if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) {
					radeon_firevertices(rmesa);
				}
				migrate_image_to_miptree(t->mt, img, face, level);
			} else
				radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n");
		}
	}

	t->validated = GL_TRUE;

	return GL_TRUE;
}
Ejemplo n.º 18
0
/**
 * At rendering-from-a-texture time, make sure that the texture object has a
 * miptree that can hold the entire texture based on
 * BaseLevel/MaxLevel/filtering, and copy in any texture images that are
 * stored in other miptrees.
 */
GLuint
intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;
   int width, height, depth;

   /* TBOs require no validation -- they always just point to their BO. */
   if (tObj->Target == GL_TEXTURE_BUFFER)
      return true;

   /* We know that this is true by now, and if it wasn't, we might have
    * mismatched level sizes and the copies would fail.
    */
   assert(intelObj->base._BaseComplete);

   intel_update_max_level(intelObj, sampler);

   /* What levels does this validated texture image require? */
   int validate_first_level = tObj->BaseLevel;
   int validate_last_level = intelObj->_MaxLevel;

   /* Skip the loop over images in the common case of no images having
    * changed.  But if the GL_BASE_LEVEL or GL_MAX_LEVEL change to something we
    * haven't looked at, then we do need to look at those new images.
    */
   if (!intelObj->needs_validate &&
       validate_first_level >= intelObj->validated_first_level &&
       validate_last_level <= intelObj->validated_last_level) {
      return true;
   }

   /* Immutable textures should not get this far -- they should have been
    * created in a validated state, and nothing can invalidate them.
    */
   assert(!tObj->Immutable);

   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
	validate_first_level < intelObj->mt->first_level ||
	validate_last_level > intelObj->mt->last_level)) {
      intel_miptree_release(&intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
					     &width, &height, &depth);

      perf_debug("Creating new %s %dx%dx%d %d-level miptree to handle "
                 "finalized texture miptree.\n",
                 _mesa_get_format_name(firstImage->base.Base.TexFormat),
                 width, height, depth, validate_last_level + 1);

      intelObj->mt = intel_miptree_create(brw,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          0, /* first_level */
                                          validate_last_level,
                                          width,
                                          height,
                                          depth,
					  true,
                                          0 /* num_samples */,
                                          INTEL_MIPTREE_TILING_ANY);
      if (!intelObj->mt)
         return false;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   for (face = 0; face < nr_faces; face++) {
      for (i = validate_first_level; i <= validate_last_level; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;

         if (intelObj->mt != intelImage->mt) {
            intel_miptree_copy_teximage(brw, intelImage, intelObj->mt,
                                        false /* invalidate */);
         }

         /* After we're done, we'd better agree that our layout is
          * appropriate, or we'll end up hitting this function again on the
          * next draw
          */
         assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base));
      }
   }

   intelObj->validated_first_level = validate_first_level;
   intelObj->validated_last_level = validate_last_level;
   intelObj->_Format = intelObj->mt->format;
   intelObj->needs_validate = false;

   return true;
}
GLuint
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
{
   struct gl_context *ctx = &intel->ctx;
   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;
   int width, height, depth;

   /* TBOs require no validation -- they always just point to their BO. */
   if (tObj->Target == GL_TEXTURE_BUFFER)
      return true;

   /* We know/require this is true by now: 
    */
   assert(intelObj->base._BaseComplete);

   /* What levels must the tree include at a minimum?
    */
   intel_update_max_level(intelObj, sampler);
   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
	intelObj->mt->first_level != tObj->BaseLevel ||
	intelObj->mt->last_level < intelObj->_MaxLevel)) {
      intel_miptree_release(&intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
					     &width, &height, &depth);

      intelObj->mt = intel_miptree_create(intel,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          tObj->BaseLevel,
                                          intelObj->_MaxLevel,
                                          width,
                                          height,
                                          depth,
					  true,
                                          0 /* num_samples */,
                                          INTEL_MSAA_LAYOUT_NONE);
      if (!intelObj->mt)
         return false;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   for (face = 0; face < nr_faces; face++) {
      for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;

         if (intelObj->mt != intelImage->mt) {
            intel_miptree_copy_teximage(intel, intelImage, intelObj->mt);
         }
      }
   }

   return true;
}