Esempio n. 1
0
/* Work back from the specified level of the image to the baselevel and create a
 * miptree of that size.
 */
struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct brw_context *brw,
				  struct intel_texture_object *intelObj,
				  struct intel_texture_image *intelImage,
                                  uint32_t layout_flags)
{
   GLuint lastLevel;
   int width, height, depth;
   GLuint i;

   intel_miptree_get_dimensions_for_image(&intelImage->base.Base,
                                          &width, &height, &depth);

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

   /* Figure out image dimensions at start level. */
   for (i = intelImage->base.Base.Level; i > 0; i--) {
      width <<= 1;
      if (height != 1)
         height <<= 1;
      if (depth != 1)
         depth <<= 1;
   }

   /* 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.
    */
   if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
        intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
       intelImage->base.Base.Level == 0 &&
       !intelObj->base.GenerateMipmap) {
      lastLevel = 0;
   } else {
      lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target,
                                               width, height, depth) - 1;
   }

   return intel_miptree_create(brw,
			       intelObj->base.Target,
			       intelImage->base.Base.TexFormat,
			       0,
			       lastLevel,
			       width,
			       height,
			       depth,
                               intelImage->base.Base.NumSamples,
                               layout_flags | MIPTREE_LAYOUT_ALLOC_ANY_TILED);
}
Esempio n. 2
0
/**
 * Do error checking for calls to glTexStorage1/2/3D().
 * If an error is found, record it with _mesa_error(), unless the target
 * is a proxy texture.
 * \return GL_TRUE if any error, GL_FALSE otherwise.
 */
static GLboolean
tex_storage_error_check(struct gl_context *ctx,
                        struct gl_texture_object *texObj,
                        GLuint dims, GLenum target,
                        GLsizei levels, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth,
                        bool dsa)
{
   const char* suffix = dsa ? "ture" : "";

   /* Legal format checking has been moved to texstorage and texturestorage in
    * order to allow meta functions to use legacy formats. */

   /* size check */
   if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTex%sStorage%uD(width, height or depth < 1)",
                  suffix, dims);
      return GL_TRUE;
   }

   if (_mesa_is_compressed_format(ctx, internalformat)) {
      GLenum err;
      if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
         _mesa_error(ctx, err,
                  "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
                  _mesa_enum_to_string(internalformat));
         return GL_TRUE;
      }
   }

   /* levels check */
   if (levels < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* check levels against maximum (note different error than above) */
   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(levels too large)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* check levels against width/height/depth */
   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(too many levels"
                  " for max texture dimension)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* non-default texture object check */
   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(texture object 0)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* Check if texObj->Immutable is set */
   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* additional checks for depth textures */
   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
                  suffix, dims);
      return GL_TRUE;
   }

   return GL_FALSE;
}
Esempio n. 3
0
/* Work back from the specified level of the image to the baselevel and create a
 * miptree of that size.
 */
struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct intel_context *intel,
				  struct intel_texture_object *intelObj,
				  struct intel_texture_image *intelImage,
				  bool expect_accelerated_upload)
{
   GLuint firstLevel;
   GLuint lastLevel;
   int width, height, depth;
   GLuint i;

   intel_miptree_get_dimensions_for_image(&intelImage->base.Base,
                                          &width, &height, &depth);

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

   if (intelImage->base.Base.Level > intelObj->base.BaseLevel &&
       (width == 1 ||
        (intelObj->base.Target != GL_TEXTURE_1D && height == 1) ||
        (intelObj->base.Target == GL_TEXTURE_3D && depth == 1))) {
      /* For this combination, we're at some lower mipmap level and
       * some important dimension is 1.  We can't extrapolate up to a
       * likely base level width/height/depth for a full mipmap stack
       * from this info, so just allocate this one level.
       */
      firstLevel = intelImage->base.Base.Level;
      lastLevel = intelImage->base.Base.Level;
   } else {
      /* If this image disrespects BaseLevel, allocate from level zero.
       * Usually BaseLevel == 0, so it's unlikely to happen.
       */
      if (intelImage->base.Base.Level < intelObj->base.BaseLevel)
	 firstLevel = 0;
      else
	 firstLevel = intelObj->base.BaseLevel;

      /* Figure out image dimensions at start level. */
      for (i = intelImage->base.Base.Level; i > firstLevel; i--) {
	 width <<= 1;
	 if (height != 1)
	    height <<= 1;
	 if (depth != 1)
	    depth <<= 1;
      }

      /* 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.
       */
      if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
	   intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
	  intelImage->base.Base.Level == firstLevel) {
	 lastLevel = firstLevel;
      } else {
	 lastLevel = (firstLevel +
                      _mesa_get_tex_max_num_levels(intelObj->base.Target,
                                                   width, height, depth) - 1);
      }
   }

   return intel_miptree_create(intel,
			       intelObj->base.Target,
			       intelImage->base.Base.TexFormat,
			       firstLevel,
			       lastLevel,
			       width,
			       height,
			       depth,
			       expect_accelerated_upload,
                               INTEL_MIPTREE_TILING_ANY);
}
Esempio n. 4
0
/**
 * Try to allocate a pipe_resource object for the given st_texture_object.
 *
 * 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 GLboolean
guess_and_alloc_texture(struct st_context *st,
			struct st_texture_object *stObj,
			const struct st_texture_image *stImage)
{
   GLuint lastLevel, width, height, depth;
   GLuint bindings;
   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
   enum pipe_format fmt;

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

   assert(!stObj->pt);

   if (!guess_base_level_size(stObj->base.Target,
                              stImage->base.Width2,
                              stImage->base.Height2,
                              stImage->base.Depth2,
                              stImage->base.Level,
                              &width, &height, &depth)) {
      /* we can't determine the image size at level=0 */
      stObj->width0 = stObj->height0 = stObj->depth0 = 0;
      /* this is not an out of memory error */
      return GL_TRUE;
   }

   /* At this point, (width x height x depth) is the expected size of
    * the level=0 mipmap image.
    */

   /* 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.Sampler.MinFilter == GL_NEAREST ||
        stObj->base.Sampler.MinFilter == GL_LINEAR ||
        (stObj->base.BaseLevel == 0 &&
         stObj->base.MaxLevel == 0) ||
        stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||
        stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&
       !stObj->base.GenerateMipmap &&
       stImage->base.Level == 0) {
      /* only alloc space for a single mipmap level */
      lastLevel = 0;
   }
   else {
      /* alloc space for a full mipmap */
      lastLevel = _mesa_get_tex_max_num_levels(stObj->base.Target,
                                               width, height, depth) - 1;
   }

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

   fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);

   bindings = default_bindings(st, fmt);

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

   stObj->pt = st_texture_create(st,
                                 gl_target_to_pipe(stObj->base.Target),
                                 fmt,
                                 lastLevel,
                                 ptWidth,
                                 ptHeight,
                                 ptDepth,
                                 ptLayers,
                                 bindings);

   stObj->lastLevel = lastLevel;

   DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));

   return stObj->pt != NULL;
}
Esempio n. 5
0
/**
 * Do error checking for calls to glTexStorage1/2/3D().
 * If an error is found, record it with _mesa_error(), unless the target
 * is a proxy texture.
 * \return GL_TRUE if any error, GL_FALSE otherwise.
 */
static GLboolean
tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
                        GLsizei levels, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth)
{
   struct gl_texture_object *texObj;
   GLboolean legalFormat;

   /* check internal format - note that only sized formats are allowed */
   switch (internalformat) {
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RED:
   case GL_RG:
   case GL_RGB:
   case GL_RGBA:
   case GL_BGRA:
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_STENCIL:
   case GL_COMPRESSED_ALPHA:
   case GL_COMPRESSED_LUMINANCE_ALPHA:
   case GL_COMPRESSED_LUMINANCE:
   case GL_COMPRESSED_INTENSITY:
   case GL_COMPRESSED_RGB:
   case GL_COMPRESSED_RGBA:
   case GL_COMPRESSED_SRGB:
   case GL_COMPRESSED_SRGB_ALPHA:
   case GL_COMPRESSED_SLUMINANCE:
   case GL_COMPRESSED_SLUMINANCE_ALPHA:
   case GL_RED_INTEGER:
   case GL_GREEN_INTEGER:
   case GL_BLUE_INTEGER:
   case GL_ALPHA_INTEGER:
   case GL_RGB_INTEGER:
   case GL_RGBA_INTEGER:
   case GL_BGR_INTEGER:
   case GL_BGRA_INTEGER:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      /* these unsized formats are illegal */
      legalFormat = GL_FALSE;
      break;
   default:
      legalFormat = _mesa_base_tex_format(ctx, internalformat) > 0;
   }

   if (!legalFormat) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(internalformat = %s)", dims,
                  _mesa_lookup_enum_by_nr(internalformat));
      return GL_TRUE;
   }

   /* size check */
   if (width < 1 || height < 1 || depth < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTexStorage%uD(width, height or depth < 1)", dims);
      return GL_TRUE;
   }  

   /* target check */
   if (!legal_texobj_target(ctx, dims, target)) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(illegal target=%s)",
                  dims, _mesa_lookup_enum_by_nr(target));
      return GL_TRUE;
   }

   /* levels check */
   if (levels < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
                  dims);
      return GL_TRUE;
   }  

   /* check levels against maximum (note different error than above) */
   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(levels too large)", dims);
      return GL_TRUE;
   }

   /* check levels against width/height/depth */
   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(too many levels for max texture dimension)",
                  dims);
      return GL_TRUE;
   }

   /* non-default texture object check */
   texObj = _mesa_get_current_tex_object(ctx, target);
   if (!texObj || (texObj->Name == 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(texture object 0)", dims);
      return GL_TRUE;
   }

   /* Check if texObj->Immutable is set */
   if (texObj->Immutable) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)",
                  dims);
      return GL_TRUE;
   }

   return GL_FALSE;
}
Esempio n. 6
0
/**
 * Do error checking for calls to glTexStorage1/2/3D().
 * If an error is found, record it with _mesa_error(), unless the target
 * is a proxy texture.
 * \return GL_TRUE if any error, GL_FALSE otherwise.
 */
static GLboolean
tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
                        GLsizei levels, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth)
{
   struct gl_texture_object *texObj;

   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(internalformat = %s)", dims,
                  _mesa_lookup_enum_by_nr(internalformat));
      return GL_TRUE;
   }

   /* size check */
   if (width < 1 || height < 1 || depth < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTexStorage%uD(width, height or depth < 1)", dims);
      return GL_TRUE;
   }  

   /* target check */
   if (!legal_texobj_target(ctx, dims, target)) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(illegal target=%s)",
                  dims, _mesa_lookup_enum_by_nr(target));
      return GL_TRUE;
   }

   /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
    *
    *    "The ETC2/EAC texture compression algorithm supports only
    *     two-dimensional images. If internalformat is an ETC2/EAC format,
    *     CompressedTexImage3D will generate an INVALID_OPERATION error if
    *     target is not TEXTURE_2D_ARRAY."
    *
    * This should also be applicable for glTexStorage3D().
    */
   if (_mesa_is_compressed_format(ctx, internalformat)
       && !_mesa_target_can_be_compressed(ctx, target, internalformat)) {
      _mesa_error(ctx, _mesa_is_desktop_gl(ctx)?
                  GL_INVALID_ENUM : GL_INVALID_OPERATION,
                  "glTexStorage3D(internalformat = %s)",
                  _mesa_lookup_enum_by_nr(internalformat));
   }

   /* levels check */
   if (levels < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
                  dims);
      return GL_TRUE;
   }  

   /* check levels against maximum (note different error than above) */
   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(levels too large)", dims);
      return GL_TRUE;
   }

   /* check levels against width/height/depth */
   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(too many levels for max texture dimension)",
                  dims);
      return GL_TRUE;
   }

   /* non-default texture object check */
   texObj = _mesa_get_current_tex_object(ctx, target);
   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(texture object 0)", dims);
      return GL_TRUE;
   }

   /* Check if texObj->Immutable is set */
   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)",
                  dims);
      return GL_TRUE;
   }

   /* additional checks for depth textures */
   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat,
                                                   dims, "glTexStorage"))
      return GL_TRUE;

   return GL_FALSE;
}
Esempio n. 7
0
/* Work back from the specified level of the image to the baselevel and create a
 * miptree of that size.
 */
struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct brw_context *brw,
				  struct intel_texture_object *intelObj,
				  struct intel_texture_image *intelImage,
                                  uint32_t layout_flags)
{
   GLuint lastLevel;
   int width, height, depth;

   intel_get_image_dims(&intelImage->base.Base, &width, &height, &depth);

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

   /* Figure out image dimensions at start level. */
   switch(intelObj->base.Target) {
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_EXTERNAL_OES:
      assert(intelImage->base.Base.Level == 0);
      break;
   case GL_TEXTURE_3D:
      depth <<= intelImage->base.Base.Level;
      /* Fall through */
   case GL_TEXTURE_2D:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
      height <<= intelImage->base.Base.Level;
      /* Fall through */
   case GL_TEXTURE_1D:
   case GL_TEXTURE_1D_ARRAY:
      width <<= intelImage->base.Base.Level;
      break;
   default:
      unreachable("Unexpected target");
   }

   /* 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.
    */
   if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
        intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
       intelImage->base.Base.Level == 0 &&
       !intelObj->base.GenerateMipmap) {
      lastLevel = 0;
   } else {
      lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target,
                                               width, height, depth) - 1;
   }

   return intel_miptree_create(brw,
			       intelObj->base.Target,
			       intelImage->base.Base.TexFormat,
			       0,
			       lastLevel,
			       width,
			       height,
			       depth,
                               intelImage->base.Base.NumSamples,
                               layout_flags | MIPTREE_LAYOUT_TILING_ANY);
}