Beispiel #1
0
/**
 * Binds a region to a texture image, like it was uploaded by glTexImage2D().
 *
 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
 */
static void
intel_set_texture_image_region(struct gl_context *ctx,
			       struct gl_texture_image *image,
			       struct intel_region *region,
			       GLenum target,
			       GLenum internalFormat,
			       gl_format format,
                               uint32_t offset,
                               GLuint width,
                               GLuint height,
                               GLuint tile_x,
                               GLuint tile_y)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   bool has_surface_tile_offset = false;
   uint32_t draw_x, draw_y;

   _mesa_init_teximage_fields(&intel->ctx, image,
			      width, height, 1,
			      0, internalFormat, format);

   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat,
                                                 0, 0,
                                                 width, height, 1,
                                                 true);
   if (intel_image->mt == NULL)
       return;
   intel_region_reference(&intel_image->mt->region, region);
   intel_image->mt->total_width = width;
   intel_image->mt->total_height = height;
   intel_image->mt->level[0].slice[0].x_offset = tile_x;
   intel_image->mt->level[0].slice[0].y_offset = tile_y;

   intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y);

   /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
    * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
    * trouble resolving back to destination image due to alignment issues.
    */
   if (!has_surface_tile_offset &&
       (draw_x != 0 || draw_y != 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
      intel_miptree_release(&intel_image->mt);
      return;
   }

   intel_texobj->needs_validate = true;

   intel_image->mt->offset = offset;
   assert(region->pitch % region->cpp == 0);
   intel_image->base.RowStride = region->pitch / region->cpp;

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
}
struct intel_mipmap_tree *
intel_miptree_create_for_bo(struct intel_context *intel,
                            drm_intel_bo *bo,
                            mesa_format format,
                            uint32_t offset,
                            uint32_t width,
                            uint32_t height,
                            int pitch,
                            uint32_t tiling)
{
    struct intel_mipmap_tree *mt;

    struct intel_region *region = calloc(1, sizeof(*region));
    if (!region)
        return NULL;

    /* Nothing will be able to use this miptree with the BO if the offset isn't
     * aligned.
     */
    if (tiling != I915_TILING_NONE)
        assert(offset % 4096 == 0);

    /* miptrees can't handle negative pitch.  If you need flipping of images,
     * that's outside of the scope of the mt.
     */
    assert(pitch >= 0);

    mt = intel_miptree_create_layout(intel, GL_TEXTURE_2D, format,
                                     0, 0,
                                     width, height, 1,
                                     true);
    if (!mt) {
        free(region);
        return mt;
    }

    region->cpp = mt->cpp;
    region->width = width;
    region->height = height;
    region->pitch = pitch;
    region->refcount = 1;
    drm_intel_bo_reference(bo);
    region->bo = bo;
    region->tiling = tiling;

    mt->region = region;
    mt->offset = offset;

    return mt;
}
struct intel_mipmap_tree *
intel_miptree_create(struct intel_context *intel,
                     GLenum target,
                     mesa_format format,
                     GLuint first_level,
                     GLuint last_level,
                     GLuint width0,
                     GLuint height0,
                     GLuint depth0,
                     bool expect_accelerated_upload,
                     enum intel_miptree_tiling_mode requested_tiling)
{
    struct intel_mipmap_tree *mt;
    GLuint total_width, total_height;


    mt = intel_miptree_create_layout(intel, target, format,
                                     first_level, last_level, width0,
                                     height0, depth0,
                                     false);
    /*
     * pitch == 0 || height == 0  indicates the null texture
     */
    if (!mt || !mt->total_width || !mt->total_height) {
        intel_miptree_release(&mt);
        return NULL;
    }

    total_width = mt->total_width;
    total_height = mt->total_height;

    uint32_t tiling = intel_miptree_choose_tiling(intel, format, width0,
                      requested_tiling,
                      mt);
    bool y_or_x = tiling == (I915_TILING_Y | I915_TILING_X);

    mt->region = intel_region_alloc(intel->intelScreen,
                                    y_or_x ? I915_TILING_Y : tiling,
                                    mt->cpp,
                                    total_width,
                                    total_height,
                                    expect_accelerated_upload);

    /* If the region is too large to fit in the aperture, we need to use the
     * BLT engine to support it.  The BLT paths can't currently handle Y-tiling,
     * so we need to fall back to X.
     */
    if (y_or_x && mt->region->bo->size >= intel->max_gtt_map_object_size) {
        perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n",
                   mt->total_width, mt->total_height);
        intel_region_release(&mt->region);

        mt->region = intel_region_alloc(intel->intelScreen,
                                        I915_TILING_X,
                                        mt->cpp,
                                        total_width,
                                        total_height,
                                        expect_accelerated_upload);
    }

    mt->offset = 0;

    if (!mt->region) {
        intel_miptree_release(&mt);
        return NULL;
    }

    return mt;
}