aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/intel_tex_validate.c
blob: 42533bbac73e9a56f64e7fa318df1b9a5f6e3031 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/samplerobj.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 (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.
 */
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 / 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;
   }

   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..%d miptree to handle finalized "
                 "texture miptree.\n",
                 _mesa_get_format_name(firstImage->base.Base.TexFormat),
                 width, height, depth,
                 validate_first_level, validate_last_level);

      intelObj->mt = intel_miptree_create(brw,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          validate_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->needs_validate = false;

   return true;
}