1 #include "swrast/swrast.h"
2 #include "main/renderbuffer.h"
3 #include "main/texobj.h"
4 #include "main/teximage.h"
5 #include "main/mipmap.h"
6 #include "drivers/common/meta.h"
7 #include "brw_context.h"
8 #include "brw_defines.h"
9 #include "intel_buffer_objects.h"
10 #include "intel_mipmap_tree.h"
11 #include "intel_tex.h"
12 #include "intel_fbo.h"
13 
14 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
15 
16 static struct gl_texture_image *
intelNewTextureImage(struct gl_context * ctx)17 intelNewTextureImage(struct gl_context * ctx)
18 {
19    DBG("%s\n", __func__);
20    (void) ctx;
21    return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image);
22 }
23 
24 static void
intelDeleteTextureImage(struct gl_context * ctx,struct gl_texture_image * img)25 intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img)
26 {
27    /* nothing special (yet) for intel_texture_image */
28    _mesa_delete_texture_image(ctx, img);
29 }
30 
31 
32 static struct gl_texture_object *
intelNewTextureObject(struct gl_context * ctx,GLuint name,GLenum target)33 intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target)
34 {
35    struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
36 
37    (void) ctx;
38 
39    DBG("%s\n", __func__);
40 
41    if (obj == NULL)
42       return NULL;
43 
44    _mesa_initialize_texture_object(ctx, &obj->base, name, target);
45 
46    obj->needs_validate = true;
47 
48    return &obj->base;
49 }
50 
51 static void
intelDeleteTextureObject(struct gl_context * ctx,struct gl_texture_object * texObj)52 intelDeleteTextureObject(struct gl_context *ctx,
53 			 struct gl_texture_object *texObj)
54 {
55    struct intel_texture_object *intelObj = intel_texture_object(texObj);
56 
57    intel_miptree_release(&intelObj->mt);
58    _mesa_delete_texture_object(ctx, texObj);
59 }
60 
61 static GLboolean
intel_alloc_texture_image_buffer(struct gl_context * ctx,struct gl_texture_image * image)62 intel_alloc_texture_image_buffer(struct gl_context *ctx,
63 				 struct gl_texture_image *image)
64 {
65    struct brw_context *brw = brw_context(ctx);
66    struct intel_texture_image *intel_image = intel_texture_image(image);
67    struct gl_texture_object *texobj = image->TexObject;
68    struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
69 
70    assert(image->Border == 0);
71 
72    /* Quantize sample count */
73    if (image->NumSamples) {
74       image->NumSamples = intel_quantize_num_samples(brw->screen, image->NumSamples);
75       if (!image->NumSamples)
76          return false;
77    }
78 
79    /* Because the driver uses AllocTextureImageBuffer() internally, it may end
80     * up mismatched with FreeTextureImageBuffer(), but that is safe to call
81     * multiple times.
82     */
83    ctx->Driver.FreeTextureImageBuffer(ctx, image);
84 
85    if (!_swrast_init_texture_image(image))
86       return false;
87 
88    if (intel_texobj->mt &&
89        intel_miptree_match_image(intel_texobj->mt, image)) {
90       intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
91       DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
92           __func__, texobj, image->Level,
93           image->Width, image->Height, image->Depth, intel_texobj->mt);
94    } else {
95       intel_image->mt = intel_miptree_create_for_teximage(brw, intel_texobj,
96                                                           intel_image,
97                                                           0);
98 
99       /* Even if the object currently has a mipmap tree associated
100        * with it, this one is a more likely candidate to represent the
101        * whole object since our level didn't fit what was there
102        * before, and any lower levels would fit into our miptree.
103        */
104       intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
105 
106       DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
107           __func__, texobj, image->Level,
108           image->Width, image->Height, image->Depth, intel_image->mt);
109    }
110 
111    intel_texobj->needs_validate = true;
112 
113    return true;
114 }
115 
116 /**
117  * ctx->Driver.AllocTextureStorage() handler.
118  *
119  * Compare this to _mesa_AllocTextureStorage_sw, which would call into
120  * intel_alloc_texture_image_buffer() above.
121  */
122 static GLboolean
intel_alloc_texture_storage(struct gl_context * ctx,struct gl_texture_object * texobj,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth)123 intel_alloc_texture_storage(struct gl_context *ctx,
124                             struct gl_texture_object *texobj,
125                             GLsizei levels, GLsizei width,
126                             GLsizei height, GLsizei depth)
127 {
128    struct brw_context *brw = brw_context(ctx);
129    struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
130    struct gl_texture_image *first_image = texobj->Image[0][0];
131    int num_samples = intel_quantize_num_samples(brw->screen,
132                                                 first_image->NumSamples);
133    const int numFaces = _mesa_num_tex_faces(texobj->Target);
134    int face;
135    int level;
136 
137    /* If the object's current miptree doesn't match what we need, make a new
138     * one.
139     */
140    if (!intel_texobj->mt ||
141        !intel_miptree_match_image(intel_texobj->mt, first_image) ||
142        intel_texobj->mt->last_level != levels - 1) {
143       intel_miptree_release(&intel_texobj->mt);
144 
145       intel_get_image_dims(first_image, &width, &height, &depth);
146       intel_texobj->mt = intel_miptree_create(brw, texobj->Target,
147                                               first_image->TexFormat,
148                                               0, levels - 1,
149                                               width, height, depth,
150                                               num_samples,
151                                               MIPTREE_LAYOUT_TILING_ANY);
152 
153       if (intel_texobj->mt == NULL) {
154          return false;
155       }
156    }
157 
158    for (face = 0; face < numFaces; face++) {
159       for (level = 0; level < levels; level++) {
160          struct gl_texture_image *image = texobj->Image[face][level];
161          struct intel_texture_image *intel_image = intel_texture_image(image);
162 
163          image->NumSamples = num_samples;
164 
165          _swrast_free_texture_image_buffer(ctx, image);
166          if (!_swrast_init_texture_image(image))
167             return false;
168 
169          intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
170       }
171    }
172 
173    /* The miptree is in a validated state, so no need to check later. */
174    intel_texobj->needs_validate = false;
175    intel_texobj->validated_first_level = 0;
176    intel_texobj->validated_last_level = levels - 1;
177    intel_texobj->_Format = intel_texobj->mt->format;
178 
179    return true;
180 }
181 
182 
183 static void
intel_free_texture_image_buffer(struct gl_context * ctx,struct gl_texture_image * texImage)184 intel_free_texture_image_buffer(struct gl_context * ctx,
185 				struct gl_texture_image *texImage)
186 {
187    struct intel_texture_image *intelImage = intel_texture_image(texImage);
188 
189    DBG("%s\n", __func__);
190 
191    intel_miptree_release(&intelImage->mt);
192 
193    _swrast_free_texture_image_buffer(ctx, texImage);
194 }
195 
196 /**
197  * Map texture memory/buffer into user space.
198  * Note: the region of interest parameters are ignored here.
199  * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
200  * \param mapOut  returns start of mapping of region of interest
201  * \param rowStrideOut  returns row stride in bytes
202  */
203 static void
intel_map_texture_image(struct gl_context * ctx,struct gl_texture_image * tex_image,GLuint slice,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** map,GLint * out_stride)204 intel_map_texture_image(struct gl_context *ctx,
205 			struct gl_texture_image *tex_image,
206 			GLuint slice,
207 			GLuint x, GLuint y, GLuint w, GLuint h,
208 			GLbitfield mode,
209 			GLubyte **map,
210 			GLint *out_stride)
211 {
212    struct brw_context *brw = brw_context(ctx);
213    struct intel_texture_image *intel_image = intel_texture_image(tex_image);
214    struct intel_mipmap_tree *mt = intel_image->mt;
215    ptrdiff_t stride;
216 
217    /* Our texture data is always stored in a miptree. */
218    assert(mt);
219 
220    /* Check that our caller wasn't confused about how to map a 1D texture. */
221    assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
222 	  h == 1);
223 
224    /* intel_miptree_map operates on a unified "slice" number that references the
225     * cube face, since it's all just slices to the miptree code.
226     */
227    if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
228       slice = tex_image->Face;
229 
230    intel_miptree_map(brw, mt,
231                      tex_image->Level + tex_image->TexObject->MinLevel,
232                      slice + tex_image->TexObject->MinLayer,
233                      x, y, w, h, mode,
234                      (void **)map, &stride);
235 
236    *out_stride = stride;
237 }
238 
239 static void
intel_unmap_texture_image(struct gl_context * ctx,struct gl_texture_image * tex_image,GLuint slice)240 intel_unmap_texture_image(struct gl_context *ctx,
241 			  struct gl_texture_image *tex_image, GLuint slice)
242 {
243    struct brw_context *brw = brw_context(ctx);
244    struct intel_texture_image *intel_image = intel_texture_image(tex_image);
245    struct intel_mipmap_tree *mt = intel_image->mt;
246 
247    if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
248       slice = tex_image->Face;
249 
250    intel_miptree_unmap(brw, mt,
251          tex_image->Level + tex_image->TexObject->MinLevel,
252          slice + tex_image->TexObject->MinLayer);
253 }
254 
255 static GLboolean
intel_texture_view(struct gl_context * ctx,struct gl_texture_object * texObj,struct gl_texture_object * origTexObj)256 intel_texture_view(struct gl_context *ctx,
257                    struct gl_texture_object *texObj,
258                    struct gl_texture_object *origTexObj)
259 {
260    struct brw_context *brw = brw_context(ctx);
261    struct intel_texture_object *intel_tex = intel_texture_object(texObj);
262    struct intel_texture_object *intel_orig_tex = intel_texture_object(origTexObj);
263 
264    assert(intel_orig_tex->mt);
265    intel_miptree_reference(&intel_tex->mt, intel_orig_tex->mt);
266 
267    /* Since we can only make views of immutable-format textures,
268     * we can assume that everything is in origTexObj's miptree.
269     *
270     * Mesa core has already made us a copy of all the teximage objects,
271     * except it hasn't copied our mt pointers, etc.
272     */
273    const int numFaces = _mesa_num_tex_faces(texObj->Target);
274    const int numLevels = texObj->NumLevels;
275 
276    int face;
277    int level;
278 
279    for (face = 0; face < numFaces; face++) {
280       for (level = 0; level < numLevels; level++) {
281          struct gl_texture_image *image = texObj->Image[face][level];
282          struct intel_texture_image *intel_image = intel_texture_image(image);
283 
284          intel_miptree_reference(&intel_image->mt, intel_orig_tex->mt);
285       }
286    }
287 
288    /* The miptree is in a validated state, so no need to check later. */
289    intel_tex->needs_validate = false;
290    intel_tex->validated_first_level = 0;
291    intel_tex->validated_last_level = numLevels - 1;
292 
293    /* Set the validated texture format, with the same adjustments that
294     * would have been applied to determine the underlying texture's
295     * mt->format.
296     */
297    intel_tex->_Format = intel_depth_format_for_depthstencil_format(
298          intel_lower_compressed_format(brw, texObj->Image[0][0]->TexFormat));
299 
300    return GL_TRUE;
301 }
302 
303 static bool
intel_set_texture_storage_for_buffer_object(struct gl_context * ctx,struct gl_texture_object * tex_obj,struct gl_buffer_object * buffer_obj,uint32_t buffer_offset,uint32_t row_stride,bool read_only)304 intel_set_texture_storage_for_buffer_object(struct gl_context *ctx,
305                                             struct gl_texture_object *tex_obj,
306                                             struct gl_buffer_object *buffer_obj,
307                                             uint32_t buffer_offset,
308                                             uint32_t row_stride,
309                                             bool read_only)
310 {
311    struct brw_context *brw = brw_context(ctx);
312    struct intel_texture_object *intel_texobj = intel_texture_object(tex_obj);
313    struct gl_texture_image *image = tex_obj->Image[0][0];
314    struct intel_texture_image *intel_image = intel_texture_image(image);
315    struct intel_buffer_object *intel_buffer_obj = intel_buffer_object(buffer_obj);
316 
317    if (!read_only) {
318       /* Renderbuffers have the restriction that the buffer offset and
319        * surface pitch must be a multiple of the element size.  If it's
320        * not, we have to fail and fall back to software.
321        */
322       int cpp = _mesa_get_format_bytes(image->TexFormat);
323       if (buffer_offset % cpp || row_stride % cpp) {
324          perf_debug("Bad PBO alignment; fallback to CPU mapping\n");
325          return false;
326       }
327 
328       if (!brw->format_supported_as_render_target[image->TexFormat]) {
329          perf_debug("Non-renderable PBO format; fallback to CPU mapping\n");
330          return false;
331       }
332    }
333 
334    assert(intel_texobj->mt == NULL);
335 
336    drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_buffer_obj,
337                                              buffer_offset,
338                                              row_stride * image->Height);
339    intel_texobj->mt =
340       intel_miptree_create_for_bo(brw, bo,
341                                   image->TexFormat,
342                                   buffer_offset,
343                                   image->Width, image->Height, image->Depth,
344                                   row_stride,
345                                   0);
346    if (!intel_texobj->mt)
347       return false;
348 
349    if (!_swrast_init_texture_image(image))
350       return false;
351 
352    intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
353 
354    /* The miptree is in a validated state, so no need to check later. */
355    intel_texobj->needs_validate = false;
356    intel_texobj->validated_first_level = 0;
357    intel_texobj->validated_last_level = 0;
358    intel_texobj->_Format = intel_texobj->mt->format;
359 
360    return true;
361 }
362 
363 static void
intel_texture_barrier(struct gl_context * ctx)364 intel_texture_barrier(struct gl_context *ctx)
365 {
366    struct brw_context *brw = brw_context(ctx);
367 
368    if (brw->gen >= 6) {
369       brw_emit_pipe_control_flush(brw,
370                                   PIPE_CONTROL_DEPTH_CACHE_FLUSH |
371                                   PIPE_CONTROL_RENDER_TARGET_FLUSH |
372                                   PIPE_CONTROL_CS_STALL);
373 
374       brw_emit_pipe_control_flush(brw,
375                                   PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
376    } else {
377       brw_emit_mi_flush(brw);
378    }
379 }
380 
381 void
intelInitTextureFuncs(struct dd_function_table * functions)382 intelInitTextureFuncs(struct dd_function_table *functions)
383 {
384    functions->NewTextureObject = intelNewTextureObject;
385    functions->NewTextureImage = intelNewTextureImage;
386    functions->DeleteTextureImage = intelDeleteTextureImage;
387    functions->DeleteTexture = intelDeleteTextureObject;
388    functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer;
389    functions->FreeTextureImageBuffer = intel_free_texture_image_buffer;
390    functions->AllocTextureStorage = intel_alloc_texture_storage;
391    functions->MapTextureImage = intel_map_texture_image;
392    functions->UnmapTextureImage = intel_unmap_texture_image;
393    functions->TextureView = intel_texture_view;
394    functions->SetTextureStorageForBufferObject =
395       intel_set_texture_storage_for_buffer_object;
396    functions->TextureBarrier = intel_texture_barrier;
397 }
398