Home | History | Annotate | Download | only in i965
      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
     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 *
     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
    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
    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 *
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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