linux/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c

// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
 *
 * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include "vmwgfx_bo.h"
#include "vmwgfx_drv.h"
#include "vmwgfx_resource_priv.h"
#include "vmwgfx_so.h"
#include "vmwgfx_binding.h"
#include "vmw_surface_cache.h"
#include "device_include/svga3d_surfacedefs.h"

#include <drm/ttm/ttm_placement.h>

#define SVGA3D_FLAGS_64(upper32, lower32)

/**
 * struct vmw_user_surface - User-space visible surface resource
 *
 * @prime:          The TTM prime object.
 * @srf:            The surface metadata.
 * @master:         Master of the creating client. Used for security check.
 */
struct vmw_user_surface {};

/**
 * struct vmw_surface_offset - Backing store mip level offset info
 *
 * @face:           Surface face.
 * @mip:            Mip level.
 * @bo_offset:      Offset into backing store of this mip level.
 *
 */
struct vmw_surface_offset {};

/**
 * struct vmw_surface_dirty - Surface dirty-tracker
 * @cache: Cached layout information of the surface.
 * @num_subres: Number of subresources.
 * @boxes: Array of SVGA3dBoxes indicating dirty regions. One per subresource.
 */
struct vmw_surface_dirty {};

static void vmw_user_surface_free(struct vmw_resource *res);
static struct vmw_resource *
vmw_user_surface_base_to_res(struct ttm_base_object *base);
static int vmw_legacy_srf_bind(struct vmw_resource *res,
			       struct ttm_validate_buffer *val_buf);
static int vmw_legacy_srf_unbind(struct vmw_resource *res,
				 bool readback,
				 struct ttm_validate_buffer *val_buf);
static int vmw_legacy_srf_create(struct vmw_resource *res);
static int vmw_legacy_srf_destroy(struct vmw_resource *res);
static int vmw_gb_surface_create(struct vmw_resource *res);
static int vmw_gb_surface_bind(struct vmw_resource *res,
			       struct ttm_validate_buffer *val_buf);
static int vmw_gb_surface_unbind(struct vmw_resource *res,
				 bool readback,
				 struct ttm_validate_buffer *val_buf);
static int vmw_gb_surface_destroy(struct vmw_resource *res);
static int
vmw_gb_surface_define_internal(struct drm_device *dev,
			       struct drm_vmw_gb_surface_create_ext_req *req,
			       struct drm_vmw_gb_surface_create_rep *rep,
			       struct drm_file *file_priv);
static int
vmw_gb_surface_reference_internal(struct drm_device *dev,
				  struct drm_vmw_surface_arg *req,
				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
				  struct drm_file *file_priv);

static void vmw_surface_dirty_free(struct vmw_resource *res);
static int vmw_surface_dirty_alloc(struct vmw_resource *res);
static int vmw_surface_dirty_sync(struct vmw_resource *res);
static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
					size_t end);
static int vmw_surface_clean(struct vmw_resource *res);

static const struct vmw_user_resource_conv user_surface_conv =;

const struct vmw_user_resource_conv *user_surface_converter =;

static const struct vmw_res_func vmw_legacy_surface_func =;

static const struct vmw_res_func vmw_gb_surface_func =;

/*
 * struct vmw_surface_dma - SVGA3D DMA command
 */
struct vmw_surface_dma {};

/*
 * struct vmw_surface_define - SVGA3D Surface Define command
 */
struct vmw_surface_define {};

/*
 * struct vmw_surface_destroy - SVGA3D Surface Destroy command
 */
struct vmw_surface_destroy {};


/**
 * vmw_surface_dma_size - Compute fifo size for a dma command.
 *
 * @srf: Pointer to a struct vmw_surface
 *
 * Computes the required size for a surface dma command for backup or
 * restoration of the surface represented by @srf.
 */
static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
{}


/**
 * vmw_surface_define_size - Compute fifo size for a surface define command.
 *
 * @srf: Pointer to a struct vmw_surface
 *
 * Computes the required size for a surface define command for the definition
 * of the surface represented by @srf.
 */
static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
{}


/**
 * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
 *
 * Computes the required size for a surface destroy command for the destruction
 * of a hw surface.
 */
static inline uint32_t vmw_surface_destroy_size(void)
{}

/**
 * vmw_surface_destroy_encode - Encode a surface_destroy command.
 *
 * @id: The surface id
 * @cmd_space: Pointer to memory area in which the commands should be encoded.
 */
static void vmw_surface_destroy_encode(uint32_t id,
				       void *cmd_space)
{}

/**
 * vmw_surface_define_encode - Encode a surface_define command.
 *
 * @srf: Pointer to a struct vmw_surface object.
 * @cmd_space: Pointer to memory area in which the commands should be encoded.
 */
static void vmw_surface_define_encode(const struct vmw_surface *srf,
				      void *cmd_space)
{}

/**
 * vmw_surface_dma_encode - Encode a surface_dma command.
 *
 * @srf: Pointer to a struct vmw_surface object.
 * @cmd_space: Pointer to memory area in which the commands should be encoded.
 * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
 * should be placed or read from.
 * @to_surface: Boolean whether to DMA to the surface or from the surface.
 */
static void vmw_surface_dma_encode(struct vmw_surface *srf,
				   void *cmd_space,
				   const SVGAGuestPtr *ptr,
				   bool to_surface)
{
	uint32_t i;
	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
	const struct SVGA3dSurfaceDesc *desc =
		vmw_surface_get_desc(srf->metadata.format);

	for (i = 0; i < srf->metadata.num_sizes; ++i) {
		SVGA3dCmdHeader *header = &cmd->header;
		SVGA3dCmdSurfaceDMA *body = &cmd->body;
		SVGA3dCopyBox *cb = &cmd->cb;
		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
		const struct drm_vmw_size *cur_size = &srf->metadata.sizes[i];

		header->id = SVGA_3D_CMD_SURFACE_DMA;
		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);

		body->guest.ptr = *ptr;
		body->guest.ptr.offset += cur_offset->bo_offset;
		body->guest.pitch = vmw_surface_calculate_pitch(desc, cur_size);
		body->host.sid = srf->res.id;
		body->host.face = cur_offset->face;
		body->host.mipmap = cur_offset->mip;
		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
				  SVGA3D_READ_HOST_VRAM);
		cb->x = 0;
		cb->y = 0;
		cb->z = 0;
		cb->srcx = 0;
		cb->srcy = 0;
		cb->srcz = 0;
		cb->w = cur_size->width;
		cb->h = cur_size->height;
		cb->d = cur_size->depth;

		suffix->suffixSize = sizeof(*suffix);
		suffix->maximumOffset =
			vmw_surface_get_image_buffer_size(desc, cur_size,
							    body->guest.pitch);
		suffix->flags.discard = 0;
		suffix->flags.unsynchronized = 0;
		suffix->flags.reserved = 0;
		++cmd;
	}
};


/**
 * vmw_hw_surface_destroy - destroy a Device surface
 *
 * @res:        Pointer to a struct vmw_resource embedded in a struct
 *              vmw_surface.
 *
 * Destroys a the device surface associated with a struct vmw_surface if
 * any, and adjusts resource count accordingly.
 */
static void vmw_hw_surface_destroy(struct vmw_resource *res)
{}

/**
 * vmw_legacy_srf_create - Create a device surface as part of the
 * resource validation process.
 *
 * @res: Pointer to a struct vmw_surface.
 *
 * If the surface doesn't have a hw id.
 *
 * Returns -EBUSY if there wasn't sufficient device resources to
 * complete the validation. Retry after freeing up resources.
 *
 * May return other errors if the kernel is out of guest resources.
 */
static int vmw_legacy_srf_create(struct vmw_resource *res)
{}

/**
 * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
 *
 * @res:            Pointer to a struct vmw_res embedded in a struct
 *                  vmw_surface.
 * @val_buf:        Pointer to a struct ttm_validate_buffer containing
 *                  information about the backup buffer.
 * @bind:           Boolean wether to DMA to the surface.
 *
 * Transfer backup data to or from a legacy surface as part of the
 * validation process.
 * May return other errors if the kernel is out of guest resources.
 * The backup buffer will be fenced or idle upon successful completion,
 * and if the surface needs persistent backup storage, the backup buffer
 * will also be returned reserved iff @bind is true.
 */
static int vmw_legacy_srf_dma(struct vmw_resource *res,
			      struct ttm_validate_buffer *val_buf,
			      bool bind)
{}

/**
 * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
 *                       surface validation process.
 *
 * @res:            Pointer to a struct vmw_res embedded in a struct
 *                  vmw_surface.
 * @val_buf:        Pointer to a struct ttm_validate_buffer containing
 *                  information about the backup buffer.
 *
 * This function will copy backup data to the surface if the
 * backup buffer is dirty.
 */
static int vmw_legacy_srf_bind(struct vmw_resource *res,
			       struct ttm_validate_buffer *val_buf)
{}


/**
 * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
 *                         surface eviction process.
 *
 * @res:            Pointer to a struct vmw_res embedded in a struct
 *                  vmw_surface.
 * @readback:       Readback - only true if dirty
 * @val_buf:        Pointer to a struct ttm_validate_buffer containing
 *                  information about the backup buffer.
 *
 * This function will copy backup data from the surface.
 */
static int vmw_legacy_srf_unbind(struct vmw_resource *res,
				 bool readback,
				 struct ttm_validate_buffer *val_buf)
{}

/**
 * vmw_legacy_srf_destroy - Destroy a device surface as part of a
 *                          resource eviction process.
 *
 * @res:            Pointer to a struct vmw_res embedded in a struct
 *                  vmw_surface.
 */
static int vmw_legacy_srf_destroy(struct vmw_resource *res)
{}


/**
 * vmw_surface_init - initialize a struct vmw_surface
 *
 * @dev_priv:       Pointer to a device private struct.
 * @srf:            Pointer to the struct vmw_surface to initialize.
 * @res_free:       Pointer to a resource destructor used to free
 *                  the object.
 */
static int vmw_surface_init(struct vmw_private *dev_priv,
			    struct vmw_surface *srf,
			    void (*res_free) (struct vmw_resource *res))
{}

/**
 * vmw_user_surface_base_to_res - TTM base object to resource converter for
 *                                user visible surfaces
 *
 * @base:           Pointer to a TTM base object
 *
 * Returns the struct vmw_resource embedded in a struct vmw_surface
 * for the user-visible object identified by the TTM base object @base.
 */
static struct vmw_resource *
vmw_user_surface_base_to_res(struct ttm_base_object *base)
{}

/**
 * vmw_user_surface_free - User visible surface resource destructor
 *
 * @res:            A struct vmw_resource embedded in a struct vmw_surface.
 */
static void vmw_user_surface_free(struct vmw_resource *res)
{}

/**
 * vmw_user_surface_base_release - User visible surface TTM base object destructor
 *
 * @p_base:         Pointer to a pointer to a TTM base object
 *                  embedded in a struct vmw_user_surface.
 *
 * Drops the base object's reference on its resource, and the
 * pointer pointed to by *p_base is set to NULL.
 */
static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
{}

/**
 * vmw_surface_destroy_ioctl - Ioctl function implementing
 *                                  the user surface destroy functionality.
 *
 * @dev:            Pointer to a struct drm_device.
 * @data:           Pointer to data copied from / to user-space.
 * @file_priv:      Pointer to a drm file private structure.
 */
int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{}

/**
 * vmw_surface_define_ioctl - Ioctl function implementing
 *                                  the user surface define functionality.
 *
 * @dev:            Pointer to a struct drm_device.
 * @data:           Pointer to data copied from / to user-space.
 * @file_priv:      Pointer to a drm file private structure.
 */
int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
			     struct drm_file *file_priv)
{}

static struct vmw_user_surface *
vmw_lookup_user_surface_for_buffer(struct vmw_private *vmw, struct vmw_bo *bo,
				   u32 handle)
{}

struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw,
						  struct vmw_bo *bo,
						  u32 handle)
{}

u32 vmw_lookup_surface_handle_for_buffer(struct vmw_private *vmw,
					 struct vmw_bo *bo,
					 u32 handle)
{}

static int vmw_buffer_prime_to_surface_base(struct vmw_private *dev_priv,
					    struct drm_file *file_priv,
					    u32 fd, u32 *handle,
					    struct ttm_base_object **base_p)
{}

static int
vmw_surface_handle_reference(struct vmw_private *dev_priv,
			     struct drm_file *file_priv,
			     uint32_t u_handle,
			     enum drm_vmw_handle_type handle_type,
			     struct ttm_base_object **base_p)
{}

/**
 * vmw_surface_reference_ioctl - Ioctl function implementing
 *                                  the user surface reference functionality.
 *
 * @dev:            Pointer to a struct drm_device.
 * @data:           Pointer to data copied from / to user-space.
 * @file_priv:      Pointer to a drm file private structure.
 */
int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
				struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_create - Encode a surface_define command.
 *
 * @res:        Pointer to a struct vmw_resource embedded in a struct
 *              vmw_surface.
 */
static int vmw_gb_surface_create(struct vmw_resource *res)
{}


static int vmw_gb_surface_bind(struct vmw_resource *res,
			       struct ttm_validate_buffer *val_buf)
{}

static int vmw_gb_surface_unbind(struct vmw_resource *res,
				 bool readback,
				 struct ttm_validate_buffer *val_buf)
{}

static int vmw_gb_surface_destroy(struct vmw_resource *res)
{}

/**
 * vmw_gb_surface_define_ioctl - Ioctl function implementing
 * the user surface define functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @data: Pointer to data copied from / to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
				struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_reference_ioctl - Ioctl function implementing
 * the user surface reference functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @data: Pointer to data copied from / to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
 * the user surface define functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @data: Pointer to data copied from / to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
				struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
 * the user surface reference functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @data: Pointer to data copied from / to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_define_internal - Ioctl function implementing
 * the user surface define functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @req: Request argument from user-space.
 * @rep: Response argument to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
static int
vmw_gb_surface_define_internal(struct drm_device *dev,
			       struct drm_vmw_gb_surface_create_ext_req *req,
			       struct drm_vmw_gb_surface_create_rep *rep,
			       struct drm_file *file_priv)
{}

/**
 * vmw_gb_surface_reference_internal - Ioctl function implementing
 * the user surface reference functionality.
 *
 * @dev: Pointer to a struct drm_device.
 * @req: Pointer to user-space request surface arg.
 * @rep: Pointer to response to user-space.
 * @file_priv: Pointer to a drm file private structure.
 */
static int
vmw_gb_surface_reference_internal(struct drm_device *dev,
				  struct drm_vmw_surface_arg *req,
				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
				  struct drm_file *file_priv)
{}

/**
 * vmw_subres_dirty_add - Add a dirty region to a subresource
 * @dirty: The surfaces's dirty tracker.
 * @loc_start: The location corresponding to the start of the region.
 * @loc_end: The location corresponding to the end of the region.
 *
 * As we are assuming that @loc_start and @loc_end represent a sequential
 * range of backing store memory, if the region spans multiple lines then
 * regardless of the x coordinate, the full lines are dirtied.
 * Correspondingly if the region spans multiple z slices, then full rather
 * than partial z slices are dirtied.
 */
static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty,
				 const struct vmw_surface_loc *loc_start,
				 const struct vmw_surface_loc *loc_end)
{}

/**
 * vmw_subres_dirty_full - Mark a full subresource as dirty
 * @dirty: The surface's dirty tracker.
 * @subres: The subresource
 */
static void vmw_subres_dirty_full(struct vmw_surface_dirty *dirty, u32 subres)
{}

/*
 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for texture
 * surfaces.
 */
static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
					    size_t start, size_t end)
{}

/*
 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for buffer
 * surfaces.
 */
static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res,
					    size_t start, size_t end)
{}

/*
 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for surfaces
 */
static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
					size_t end)
{}

/*
 * vmw_surface_dirty_sync - The surface's dirty_sync callback.
 */
static int vmw_surface_dirty_sync(struct vmw_resource *res)
{}

/*
 * vmw_surface_dirty_alloc - The surface's dirty_alloc callback.
 */
static int vmw_surface_dirty_alloc(struct vmw_resource *res)
{}

/*
 * vmw_surface_dirty_free - The surface's dirty_free callback
 */
static void vmw_surface_dirty_free(struct vmw_resource *res)
{}

/*
 * vmw_surface_clean - The surface's clean callback
 */
static int vmw_surface_clean(struct vmw_resource *res)
{}

/*
 * vmw_gb_surface_define - Define a private GB surface
 *
 * @dev_priv: Pointer to a device private.
 * @metadata: Metadata representing the surface to create.
 * @user_srf_out: allocated user_srf. Set to NULL on failure.
 *
 * GB surfaces allocated by this function will not have a user mode handle, and
 * thus will only be visible to vmwgfx.  For optimization reasons the
 * surface may later be given a user mode handle by another function to make
 * it available to user mode drivers.
 */
int vmw_gb_surface_define(struct vmw_private *dev_priv,
			  const struct vmw_surface_metadata *req,
			  struct vmw_surface **srf_out)
{}

static SVGA3dSurfaceFormat vmw_format_bpp_to_svga(struct vmw_private *vmw,
						  int bpp)
{}

/**
 * vmw_dumb_create - Create a dumb kms buffer
 *
 * @file_priv: Pointer to a struct drm_file identifying the caller.
 * @dev: Pointer to the drm device.
 * @args: Pointer to a struct drm_mode_create_dumb structure
 * Return: Zero on success, negative error code on failure.
 *
 * This is a driver callback for the core drm create_dumb functionality.
 * Note that this is very similar to the vmw_bo_alloc ioctl, except
 * that the arguments have a different format.
 */
int vmw_dumb_create(struct drm_file *file_priv,
		    struct drm_device *dev,
		    struct drm_mode_create_dumb *args)
{}