/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "main/mtypes.h"
#include "main/macros.h"
#include "main/samplerobj.h"
#include "main/teximage.h"
#include "main/texobj.h"

#include "brw_context.h"
#include "intel_mipmap_tree.h"
#include "intel_blit.h"
#include "intel_tex.h"

#define FILE_DEBUG_FLAG DEBUG_TEXTURE

/**
 * Sets our driver-specific variant of tObj->_MaxLevel for later surface state
 * upload.
 *
 * If we're only ensuring that there is storage for the first miplevel of a
 * texture, then in texture setup we're going to have to make sure we don't
 * allow sampling beyond level 0.
 */
static void
intel_update_max_level(struct intel_texture_object *intelObj,
		       struct gl_sampler_object *sampler)
{
   struct gl_texture_object *tObj = &intelObj->base;

   if (!tObj->_MipmapComplete ||
       (tObj->_RenderToTexture &&
        (sampler->MinFilter == GL_NEAREST ||
         sampler->MinFilter == GL_LINEAR))) {
      intelObj->_MaxLevel = tObj->BaseLevel;
   } else {
      intelObj->_MaxLevel = tObj->_MaxLevel;
   }
}

/**
 * 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.
 */
void
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;

   /* 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;
   }

   /* On recent generations, immutable textures should not get this far
    * -- they should have been created in a validated state, and nothing
    * can invalidate them.
    *
    * Unfortunately, this is not true on pre-Sandybridge hardware -- when
    * rendering into an immutable-format depth texture we may have to rebase
    * the rendered levels to meet alignment requirements.
    *
    * FINISHME: Avoid doing this.
    */
   assert(!tObj->Immutable || brw->gen < 6);

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

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    */
   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_get_image_dims(&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,
                                          1 /* num_samples */,
                                          MIPTREE_CREATE_BUSY);
      if (!intelObj->mt)
         return;
   }

   /* 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;
}

/**
 * Finalizes all textures, completing any rendering that needs to be done
 * to prepare them.
 */
void
brw_validate_textures(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   const int max_enabled_unit = ctx->Texture._MaxEnabledTexImageUnit;

   for (int unit = 0; unit <= max_enabled_unit; unit++) {
      struct gl_texture_unit *tex_unit = &ctx->Texture.Unit[unit];

      if (tex_unit->_Current) {
         intel_finalize_mipmap_tree(brw, unit);
      }
   }
}
