• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include "main/macros.h"
3 #include "main/mtypes.h"
4 #include "main/enums.h"
5 #include "main/bufferobj.h"
6 #include "main/context.h"
7 #include "main/formats.h"
8 #include "main/glformats.h"
9 #include "main/image.h"
10 #include "main/pbo.h"
11 #include "main/renderbuffer.h"
12 #include "main/texcompress.h"
13 #include "main/texgetimage.h"
14 #include "main/texobj.h"
15 #include "main/teximage.h"
16 #include "main/texstore.h"
17 
18 #include "drivers/common/meta.h"
19 
20 #include "intel_mipmap_tree.h"
21 #include "intel_buffer_objects.h"
22 #include "intel_batchbuffer.h"
23 #include "intel_tex.h"
24 #include "intel_blit.h"
25 #include "intel_fbo.h"
26 #include "intel_image.h"
27 #include "intel_tiled_memcpy.h"
28 #include "brw_context.h"
29 
30 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
31 
32 /* Make sure one doesn't end up shrinking base level zero unnecessarily.
33  * Determining the base level dimension by shifting higher level dimension
34  * ends up in off-by-one value in case base level has NPOT size (for example,
35  * 293 != 146 << 1).
36  * Choose the original base level dimension when shifted dimensions agree.
37  * Otherwise assume real resize is intended and use the new shifted value.
38  */
39 static unsigned
get_base_dim(unsigned old_base_dim,unsigned new_level_dim,unsigned level)40 get_base_dim(unsigned old_base_dim, unsigned new_level_dim, unsigned level)
41 {
42    const unsigned old_level_dim = old_base_dim >> level;
43    const unsigned new_base_dim = new_level_dim << level;
44 
45    return old_level_dim == new_level_dim ? old_base_dim : new_base_dim;
46 }
47 
48 /* Work back from the specified level of the image to the baselevel and create a
49  * miptree of that size.
50  */
51 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)52 intel_miptree_create_for_teximage(struct brw_context *brw,
53 				  struct intel_texture_object *intelObj,
54 				  struct intel_texture_image *intelImage,
55                                   uint32_t layout_flags)
56 {
57    GLuint lastLevel;
58    int width, height, depth;
59    const struct intel_mipmap_tree *old_mt = intelObj->mt;
60    const unsigned level = intelImage->base.Base.Level;
61 
62    intel_get_image_dims(&intelImage->base.Base, &width, &height, &depth);
63 
64    DBG("%s\n", __func__);
65 
66    /* Figure out image dimensions at start level. */
67    switch(intelObj->base.Target) {
68    case GL_TEXTURE_2D_MULTISAMPLE:
69    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
70    case GL_TEXTURE_RECTANGLE:
71    case GL_TEXTURE_EXTERNAL_OES:
72       assert(level == 0);
73       break;
74    case GL_TEXTURE_3D:
75       depth = old_mt ? get_base_dim(old_mt->logical_depth0, depth, level) :
76                        depth << level;
77       /* Fall through */
78    case GL_TEXTURE_2D:
79    case GL_TEXTURE_2D_ARRAY:
80    case GL_TEXTURE_CUBE_MAP:
81    case GL_TEXTURE_CUBE_MAP_ARRAY:
82       height = old_mt ? get_base_dim(old_mt->logical_height0, height, level) :
83                         height << level;
84       /* Fall through */
85    case GL_TEXTURE_1D:
86    case GL_TEXTURE_1D_ARRAY:
87       width = old_mt ? get_base_dim(old_mt->logical_width0, width, level) :
88                        width << level;
89       break;
90    default:
91       unreachable("Unexpected target");
92    }
93 
94    /* Guess a reasonable value for lastLevel.  This is probably going
95     * to be wrong fairly often and might mean that we have to look at
96     * resizable buffers, or require that buffers implement lazy
97     * pagetable arrangements.
98     */
99    if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
100         intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
101        intelImage->base.Base.Level == 0 &&
102        !intelObj->base.GenerateMipmap) {
103       lastLevel = 0;
104    } else {
105       lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target,
106                                                width, height, depth) - 1;
107    }
108 
109    return intel_miptree_create(brw,
110 			       intelObj->base.Target,
111 			       intelImage->base.Base.TexFormat,
112 			       0,
113 			       lastLevel,
114 			       width,
115 			       height,
116 			       depth,
117                                intelImage->base.Base.NumSamples,
118                                layout_flags | MIPTREE_LAYOUT_TILING_ANY);
119 }
120 
121 static void
intelTexImage(struct gl_context * ctx,GLuint dims,struct gl_texture_image * texImage,GLenum format,GLenum type,const void * pixels,const struct gl_pixelstore_attrib * unpack)122 intelTexImage(struct gl_context * ctx,
123               GLuint dims,
124               struct gl_texture_image *texImage,
125               GLenum format, GLenum type, const void *pixels,
126               const struct gl_pixelstore_attrib *unpack)
127 {
128    struct intel_texture_image *intelImage = intel_texture_image(texImage);
129    bool ok;
130 
131    bool tex_busy = intelImage->mt && drm_intel_bo_busy(intelImage->mt->bo);
132 
133    DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n",
134        __func__, _mesa_get_format_name(texImage->TexFormat),
135        _mesa_enum_to_string(texImage->TexObject->Target),
136        _mesa_enum_to_string(format), _mesa_enum_to_string(type),
137        texImage->Level, texImage->Width, texImage->Height, texImage->Depth);
138 
139    /* Allocate storage for texture data. */
140    if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
141       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
142       return;
143    }
144 
145    assert(intelImage->mt);
146 
147    if (intelImage->mt->format == MESA_FORMAT_S_UINT8)
148       intelImage->mt->r8stencil_needs_update = true;
149 
150    ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0,
151                                    texImage->Width, texImage->Height,
152                                    texImage->Depth,
153                                    format, type, pixels,
154                                    tex_busy, unpack);
155    if (ok)
156       return;
157 
158    ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
159                                        0, 0, 0, /*x,y,z offsets*/
160                                        texImage->Width,
161                                        texImage->Height,
162                                        texImage->Depth,
163                                        format, type, pixels, unpack,
164                                        false /*allocate_storage*/);
165    if (ok)
166       return;
167 
168    DBG("%s: upload image %dx%dx%d pixels %p\n",
169        __func__, texImage->Width, texImage->Height, texImage->Depth,
170        pixels);
171 
172    _mesa_store_teximage(ctx, dims, texImage,
173                         format, type, pixels, unpack);
174 }
175 
176 
177 static void
intel_set_texture_image_mt(struct brw_context * brw,struct gl_texture_image * image,GLenum internal_format,struct intel_mipmap_tree * mt)178 intel_set_texture_image_mt(struct brw_context *brw,
179                            struct gl_texture_image *image,
180                            GLenum internal_format,
181                            struct intel_mipmap_tree *mt)
182 
183 {
184    struct gl_texture_object *texobj = image->TexObject;
185    struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
186    struct intel_texture_image *intel_image = intel_texture_image(image);
187 
188    _mesa_init_teximage_fields(&brw->ctx, image,
189 			      mt->logical_width0, mt->logical_height0, 1,
190 			      0, internal_format, mt->format);
191 
192    brw->ctx.Driver.FreeTextureImageBuffer(&brw->ctx, image);
193 
194    intel_texobj->needs_validate = true;
195    intel_image->base.RowStride = mt->pitch / mt->cpp;
196    assert(mt->pitch % mt->cpp == 0);
197 
198    intel_miptree_reference(&intel_image->mt, mt);
199 
200    /* Immediately validate the image to the object. */
201    intel_miptree_reference(&intel_texobj->mt, mt);
202 }
203 
204 static struct intel_mipmap_tree *
create_mt_for_planar_dri_image(struct brw_context * brw,GLenum target,__DRIimage * image)205 create_mt_for_planar_dri_image(struct brw_context *brw,
206                                GLenum target, __DRIimage *image)
207 {
208    struct intel_image_format *f = image->planar_format;
209    struct intel_mipmap_tree *planar_mt;
210 
211    for (int i = 0; i < f->nplanes; i++) {
212       const int index = f->planes[i].buffer_index;
213       const uint32_t dri_format = f->planes[i].dri_format;
214       const mesa_format format = driImageFormatToGLFormat(dri_format);
215       const uint32_t width = image->width >> f->planes[i].width_shift;
216       const uint32_t height = image->height >> f->planes[i].height_shift;
217 
218       /* Disable creation of the texture's aux buffers because the driver
219        * exposes no EGL API to manage them. That is, there is no API for
220        * resolving the aux buffer's content to the main buffer nor for
221        * invalidating the aux buffer's content.
222        */
223       struct intel_mipmap_tree *mt =
224          intel_miptree_create_for_bo(brw, image->bo, format,
225                                      image->offsets[index],
226                                      width, height, 1,
227                                      image->strides[index],
228                                      MIPTREE_LAYOUT_DISABLE_AUX);
229       if (mt == NULL)
230          return NULL;
231 
232       mt->target = target;
233       mt->total_width = width;
234       mt->total_height = height;
235 
236       if (i == 0)
237          planar_mt = mt;
238       else
239          planar_mt->plane[i - 1] = mt;
240    }
241 
242    return planar_mt;
243 }
244 
245 /**
246  * Binds a BO to a texture image, as if it was uploaded by glTexImage2D().
247  *
248  * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
249  */
250 static struct intel_mipmap_tree *
create_mt_for_dri_image(struct brw_context * brw,GLenum target,__DRIimage * image)251 create_mt_for_dri_image(struct brw_context *brw,
252                         GLenum target, __DRIimage *image)
253 {
254    struct intel_mipmap_tree *mt;
255    uint32_t draw_x, draw_y;
256 
257    /* Disable creation of the texture's aux buffers because the driver exposes
258     * no EGL API to manage them. That is, there is no API for resolving the aux
259     * buffer's content to the main buffer nor for invalidating the aux buffer's
260     * content.
261     */
262    mt = intel_miptree_create_for_bo(brw, image->bo, image->format,
263                                     0, image->width, image->height, 1,
264                                     image->pitch,
265                                     MIPTREE_LAYOUT_DISABLE_AUX);
266    if (mt == NULL)
267       return NULL;
268 
269    mt->target = target;
270    mt->total_width = image->width;
271    mt->total_height = image->height;
272    mt->level[0].slice[0].x_offset = image->tile_x;
273    mt->level[0].slice[0].y_offset = image->tile_y;
274 
275    intel_miptree_get_tile_offsets(mt, 0, 0, &draw_x, &draw_y);
276 
277    /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
278     * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
279     * trouble resolving back to destination image due to alignment issues.
280     */
281    if (!brw->has_surface_tile_offset &&
282        (draw_x != 0 || draw_y != 0)) {
283       _mesa_error(&brw->ctx, GL_INVALID_OPERATION, __func__);
284       intel_miptree_release(&mt);
285       return NULL;
286    }
287 
288    mt->offset = image->offset;
289 
290    return mt;
291 }
292 
293 void
intelSetTexBuffer2(__DRIcontext * pDRICtx,GLint target,GLint texture_format,__DRIdrawable * dPriv)294 intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
295 		   GLint texture_format,
296 		   __DRIdrawable *dPriv)
297 {
298    struct gl_framebuffer *fb = dPriv->driverPrivate;
299    struct brw_context *brw = pDRICtx->driverPrivate;
300    struct gl_context *ctx = &brw->ctx;
301    struct intel_renderbuffer *rb;
302    struct gl_texture_object *texObj;
303    struct gl_texture_image *texImage;
304    mesa_format texFormat = MESA_FORMAT_NONE;
305    struct intel_mipmap_tree *mt;
306    GLenum internal_format = 0;
307 
308    texObj = _mesa_get_current_tex_object(ctx, target);
309 
310    if (!texObj)
311       return;
312 
313    if (dPriv->lastStamp != dPriv->dri2.stamp ||
314        !pDRICtx->driScreenPriv->dri2.useInvalidate)
315       intel_update_renderbuffers(pDRICtx, dPriv);
316 
317    rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
318    /* If the miptree isn't set, then intel_update_renderbuffers was unable
319     * to get the BO for the drawable from the window system.
320     */
321    if (!rb || !rb->mt)
322       return;
323 
324    if (rb->mt->cpp == 4) {
325       if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
326          internal_format = GL_RGB;
327          texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
328       }
329       else {
330          internal_format = GL_RGBA;
331          texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
332       }
333    } else if (rb->mt->cpp == 2) {
334       internal_format = GL_RGB;
335       texFormat = MESA_FORMAT_B5G6R5_UNORM;
336    }
337 
338    intel_miptree_make_shareable(brw, rb->mt);
339    mt = intel_miptree_create_for_bo(brw, rb->mt->bo, texFormat, 0,
340                                     rb->Base.Base.Width,
341                                     rb->Base.Base.Height,
342                                     1, rb->mt->pitch, 0);
343    if (mt == NULL)
344        return;
345    mt->target = target;
346    mt->total_width = rb->Base.Base.Width;
347    mt->total_height = rb->Base.Base.Height;
348 
349    _mesa_lock_texture(&brw->ctx, texObj);
350    texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
351    intel_set_texture_image_mt(brw, texImage, internal_format, mt);
352    intel_miptree_release(&mt);
353    _mesa_unlock_texture(&brw->ctx, texObj);
354 }
355 
356 static GLboolean
intel_bind_renderbuffer_tex_image(struct gl_context * ctx,struct gl_renderbuffer * rb,struct gl_texture_image * image)357 intel_bind_renderbuffer_tex_image(struct gl_context *ctx,
358                                   struct gl_renderbuffer *rb,
359                                   struct gl_texture_image *image)
360 {
361    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
362    struct intel_texture_image *intel_image = intel_texture_image(image);
363    struct gl_texture_object *texobj = image->TexObject;
364    struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
365 
366    /* We can only handle RB allocated with AllocRenderbufferStorage, or
367     * window-system renderbuffers.
368     */
369    assert(!rb->TexImage);
370 
371    if (!irb->mt)
372       return false;
373 
374    _mesa_lock_texture(ctx, texobj);
375    _mesa_init_teximage_fields(ctx, image,
376 			      rb->Width, rb->Height, 1,
377 			      0, rb->InternalFormat, rb->Format);
378    image->NumSamples = rb->NumSamples;
379 
380    intel_miptree_reference(&intel_image->mt, irb->mt);
381 
382    /* Immediately validate the image to the object. */
383    intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
384 
385    intel_texobj->needs_validate = true;
386    _mesa_unlock_texture(ctx, texobj);
387 
388    return true;
389 }
390 
391 void
intelSetTexBuffer(__DRIcontext * pDRICtx,GLint target,__DRIdrawable * dPriv)392 intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
393 {
394    /* The old interface didn't have the format argument, so copy our
395     * implementation's behavior at the time.
396     */
397    intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
398 }
399 
400 static void
intel_image_target_texture_2d(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,struct gl_texture_image * texImage,GLeglImageOES image_handle)401 intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
402 			      struct gl_texture_object *texObj,
403 			      struct gl_texture_image *texImage,
404 			      GLeglImageOES image_handle)
405 {
406    struct brw_context *brw = brw_context(ctx);
407    struct intel_mipmap_tree *mt;
408    __DRIscreen *dri_screen = brw->screen->driScrnPriv;
409    __DRIimage *image;
410 
411    image = dri_screen->dri2.image->lookupEGLImage(dri_screen, image_handle,
412                                                   dri_screen->loaderPrivate);
413    if (image == NULL)
414       return;
415 
416    /* We support external textures only for EGLImages created with
417     * EGL_EXT_image_dma_buf_import. We may lift that restriction in the future.
418     */
419    if (target == GL_TEXTURE_EXTERNAL_OES && !image->dma_buf_imported) {
420       _mesa_error(ctx, GL_INVALID_OPERATION,
421             "glEGLImageTargetTexture2DOES(external target is enabled only "
422                "for images created with EGL_EXT_image_dma_buf_import");
423       return;
424    }
425 
426    /* Disallow depth/stencil textures: we don't have a way to pass the
427     * separate stencil miptree of a GL_DEPTH_STENCIL texture through.
428     */
429    if (image->has_depthstencil) {
430       _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
431       return;
432    }
433 
434    if (image->planar_format && image->planar_format->nplanes > 0)
435       mt = create_mt_for_planar_dri_image(brw, target, image);
436    else
437       mt = create_mt_for_dri_image(brw, target, image);
438    if (mt == NULL)
439       return;
440 
441    struct intel_texture_object *intel_texobj = intel_texture_object(texObj);
442    intel_texobj->planar_format = image->planar_format;
443 
444    const GLenum internal_format =
445       image->internal_format != 0 ?
446       image->internal_format : _mesa_get_format_base_format(mt->format);
447    intel_set_texture_image_mt(brw, texImage, internal_format, mt);
448    intel_miptree_release(&mt);
449 }
450 
451 /**
452  * \brief A fast path for glGetTexImage.
453  *
454  * \see intel_readpixels_tiled_memcpy()
455  */
456 bool
intel_gettexsubimage_tiled_memcpy(struct gl_context * ctx,struct gl_texture_image * texImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)457 intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
458                                   struct gl_texture_image *texImage,
459                                   GLint xoffset, GLint yoffset,
460                                   GLsizei width, GLsizei height,
461                                   GLenum format, GLenum type,
462                                   GLvoid *pixels,
463                                   const struct gl_pixelstore_attrib *packing)
464 {
465    struct brw_context *brw = brw_context(ctx);
466    struct intel_texture_image *image = intel_texture_image(texImage);
467    int dst_pitch;
468 
469    /* The miptree's buffer. */
470    drm_intel_bo *bo;
471 
472    int error = 0;
473 
474    uint32_t cpp;
475    mem_copy_fn mem_copy = NULL;
476 
477    /* This fastpath is restricted to specific texture types:
478     * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
479     * more types.
480     *
481     * FINISHME: The restrictions below on packing alignment and packing row
482     * length are likely unneeded now because we calculate the destination stride
483     * with _mesa_image_row_stride. However, before removing the restrictions
484     * we need tests.
485     */
486    if (!brw->has_llc ||
487        !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
488        !(texImage->TexObject->Target == GL_TEXTURE_2D ||
489          texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
490        pixels == NULL ||
491        _mesa_is_bufferobj(packing->BufferObj) ||
492        packing->Alignment > 4 ||
493        packing->SkipPixels > 0 ||
494        packing->SkipRows > 0 ||
495        (packing->RowLength != 0 && packing->RowLength != width) ||
496        packing->SwapBytes ||
497        packing->LsbFirst ||
498        packing->Invert)
499       return false;
500 
501    /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
502     * function doesn't set the last channel to 1. Note this checks BaseFormat
503     * rather than TexFormat in case the RGBX format is being simulated with an
504     * RGBA format.
505     */
506    if (texImage->_BaseFormat == GL_RGB)
507       return false;
508 
509    if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp))
510       return false;
511 
512    /* If this is a nontrivial texture view, let another path handle it instead. */
513    if (texImage->TexObject->MinLayer)
514       return false;
515 
516    if (!image->mt ||
517        (image->mt->tiling != I915_TILING_X &&
518        image->mt->tiling != I915_TILING_Y)) {
519       /* The algorithm is written only for X- or Y-tiled memory. */
520       return false;
521    }
522 
523    /* Since we are going to write raw data to the miptree, we need to resolve
524     * any pending fast color clears before we start.
525     */
526    intel_miptree_all_slices_resolve_color(brw, image->mt, 0);
527 
528    bo = image->mt->bo;
529 
530    if (drm_intel_bo_references(brw->batch.bo, bo)) {
531       perf_debug("Flushing before mapping a referenced bo.\n");
532       intel_batchbuffer_flush(brw);
533    }
534 
535    error = brw_bo_map(brw, bo, false /* write enable */, "miptree");
536    if (error) {
537       DBG("%s: failed to map bo\n", __func__);
538       return false;
539    }
540 
541    dst_pitch = _mesa_image_row_stride(packing, width, format, type);
542 
543    DBG("%s: level=%d x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
544        "mesa_format=0x%x tiling=%d "
545        "packing=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
546        __func__, texImage->Level, xoffset, yoffset, width, height,
547        format, type, texImage->TexFormat, image->mt->tiling,
548        packing->Alignment, packing->RowLength, packing->SkipPixels,
549        packing->SkipRows);
550 
551    int level = texImage->Level + texImage->TexObject->MinLevel;
552 
553    /* Adjust x and y offset based on miplevel */
554    xoffset += image->mt->level[level].level_x;
555    yoffset += image->mt->level[level].level_y;
556 
557    tiled_to_linear(
558       xoffset * cpp, (xoffset + width) * cpp,
559       yoffset, yoffset + height,
560       pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
561       bo->virtual,
562       dst_pitch, image->mt->pitch,
563       brw->has_swizzling,
564       image->mt->tiling,
565       mem_copy
566    );
567 
568    drm_intel_bo_unmap(bo);
569    return true;
570 }
571 
572 static void
intel_get_tex_sub_image(struct gl_context * ctx,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLint depth,GLenum format,GLenum type,GLvoid * pixels,struct gl_texture_image * texImage)573 intel_get_tex_sub_image(struct gl_context *ctx,
574                         GLint xoffset, GLint yoffset, GLint zoffset,
575                         GLsizei width, GLsizei height, GLint depth,
576                         GLenum format, GLenum type, GLvoid *pixels,
577                         struct gl_texture_image *texImage)
578 {
579    struct brw_context *brw = brw_context(ctx);
580    bool ok;
581 
582    DBG("%s\n", __func__);
583 
584    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
585       if (_mesa_meta_pbo_GetTexSubImage(ctx, 3, texImage,
586                                         xoffset, yoffset, zoffset,
587                                         width, height, depth, format, type,
588                                         pixels, &ctx->Pack)) {
589          /* Flush to guarantee coherency between the render cache and other
590           * caches the PBO could potentially be bound to after this point.
591           * See the related comment in intelReadPixels() for a more detailed
592           * explanation.
593           */
594          brw_emit_mi_flush(brw);
595          return;
596       }
597 
598       perf_debug("%s: fallback to CPU mapping in PBO case\n", __func__);
599    }
600 
601    ok = intel_gettexsubimage_tiled_memcpy(ctx, texImage, xoffset, yoffset,
602                                           width, height,
603                                           format, type, pixels, &ctx->Pack);
604 
605    if(ok)
606       return;
607 
608    _mesa_meta_GetTexSubImage(ctx, xoffset, yoffset, zoffset,
609                              width, height, depth,
610                              format, type, pixels, texImage);
611 
612    DBG("%s - DONE\n", __func__);
613 }
614 
615 static void
flush_astc_denorms(struct gl_context * ctx,GLuint dims,struct gl_texture_image * texImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth)616 flush_astc_denorms(struct gl_context *ctx, GLuint dims,
617                    struct gl_texture_image *texImage,
618                    GLint xoffset, GLint yoffset, GLint zoffset,
619                    GLsizei width, GLsizei height, GLsizei depth)
620 {
621    struct compressed_pixelstore store;
622    _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat,
623                                        width, height, depth,
624                                        &ctx->Unpack, &store);
625 
626    for (int slice = 0; slice < store.CopySlices; slice++) {
627 
628       /* Map dest texture buffer */
629       GLubyte *dstMap;
630       GLint dstRowStride;
631       ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset,
632                                   xoffset, yoffset, width, height,
633                                   GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
634                                   &dstMap, &dstRowStride);
635       if (!dstMap)
636          continue;
637 
638       for (int i = 0; i < store.CopyRowsPerSlice; i++) {
639 
640          /* An ASTC block is stored in little endian mode. The byte that
641           * contains bits 0..7 is stored at the lower address in memory.
642           */
643          struct astc_void_extent {
644             uint16_t header : 12;
645             uint16_t dontcare[3];
646             uint16_t R;
647             uint16_t G;
648             uint16_t B;
649             uint16_t A;
650          } *blocks = (struct astc_void_extent*) dstMap;
651 
652          /* Iterate over every copied block in the row */
653          for (int j = 0; j < store.CopyBytesPerRow / 16; j++) {
654 
655             /* Check if the header matches that of an LDR void-extent block */
656             if (blocks[j].header == 0xDFC) {
657 
658                /* Flush UNORM16 values that would be denormalized */
659                if (blocks[j].A < 4) blocks[j].A = 0;
660                if (blocks[j].B < 4) blocks[j].B = 0;
661                if (blocks[j].G < 4) blocks[j].G = 0;
662                if (blocks[j].R < 4) blocks[j].R = 0;
663             }
664          }
665 
666          dstMap += dstRowStride;
667       }
668 
669       ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset);
670    }
671 }
672 
673 
674 static void
intelCompressedTexSubImage(struct gl_context * ctx,GLuint dims,struct gl_texture_image * texImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)675 intelCompressedTexSubImage(struct gl_context *ctx, GLuint dims,
676                         struct gl_texture_image *texImage,
677                         GLint xoffset, GLint yoffset, GLint zoffset,
678                         GLsizei width, GLsizei height, GLsizei depth,
679                         GLenum format,
680                         GLsizei imageSize, const GLvoid *data)
681 {
682    /* Upload the compressed data blocks */
683    _mesa_store_compressed_texsubimage(ctx, dims, texImage,
684                                       xoffset, yoffset, zoffset,
685                                       width, height, depth,
686                                       format, imageSize, data);
687 
688    /* Fix up copied ASTC blocks if necessary */
689    GLenum gl_format = _mesa_compressed_format_to_glenum(ctx,
690                                                         texImage->TexFormat);
691    bool is_linear_astc = _mesa_is_astc_format(gl_format) &&
692                         !_mesa_is_srgb_format(gl_format);
693    struct brw_context *brw = (struct brw_context*) ctx;
694    if (brw->gen == 9 && is_linear_astc)
695       flush_astc_denorms(ctx, dims, texImage,
696                          xoffset, yoffset, zoffset,
697                          width, height, depth);
698 }
699 
700 void
intelInitTextureImageFuncs(struct dd_function_table * functions)701 intelInitTextureImageFuncs(struct dd_function_table *functions)
702 {
703    functions->TexImage = intelTexImage;
704    functions->CompressedTexSubImage = intelCompressedTexSubImage;
705    functions->EGLImageTargetTexture2D = intel_image_target_texture_2d;
706    functions->BindRenderbufferTexImage = intel_bind_renderbuffer_tex_image;
707    functions->GetTexSubImage = intel_get_tex_sub_image;
708 }
709