Home | History | Annotate | Line # | Download | only in vmwgfx
      1  1.1  riastrad /*	$NetBSD: vmwgfx_binding.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.3  riastrad // SPDX-License-Identifier: GPL-2.0 OR MIT
      4  1.1  riastrad /**************************************************************************
      5  1.1  riastrad  *
      6  1.3  riastrad  * Copyright 2015 VMware, Inc., Palo Alto, CA., USA
      7  1.1  riastrad  *
      8  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      9  1.1  riastrad  * copy of this software and associated documentation files (the
     10  1.1  riastrad  * "Software"), to deal in the Software without restriction, including
     11  1.1  riastrad  * without limitation the rights to use, copy, modify, merge, publish,
     12  1.1  riastrad  * distribute, sub license, and/or sell copies of the Software, and to
     13  1.1  riastrad  * permit persons to whom the Software is furnished to do so, subject to
     14  1.1  riastrad  * the following conditions:
     15  1.1  riastrad  *
     16  1.1  riastrad  * The above copyright notice and this permission notice (including the
     17  1.1  riastrad  * next paragraph) shall be included in all copies or substantial portions
     18  1.1  riastrad  * of the Software.
     19  1.1  riastrad  *
     20  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     23  1.1  riastrad  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     24  1.1  riastrad  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     25  1.1  riastrad  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     26  1.1  riastrad  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  1.1  riastrad  *
     28  1.1  riastrad  **************************************************************************/
     29  1.1  riastrad /*
     30  1.1  riastrad  * This file implements the vmwgfx context binding manager,
     31  1.1  riastrad  * The sole reason for having to use this code is that vmware guest
     32  1.1  riastrad  * backed contexts can be swapped out to their backing mobs by the device
     33  1.1  riastrad  * at any time, also swapped in at any time. At swapin time, the device
     34  1.1  riastrad  * validates the context bindings to make sure they point to valid resources.
     35  1.1  riastrad  * It's this outside-of-drawcall validation (that can happen at any time),
     36  1.1  riastrad  * that makes this code necessary.
     37  1.1  riastrad  *
     38  1.1  riastrad  * We therefore need to kill any context bindings pointing to a resource
     39  1.1  riastrad  * when the resource is swapped out. Furthermore, if the vmwgfx driver has
     40  1.1  riastrad  * swapped out the context we can't swap it in again to kill bindings because
     41  1.1  riastrad  * of backing mob reservation lockdep violations, so as part of
     42  1.1  riastrad  * context swapout, also kill all bindings of a context, so that they are
     43  1.1  riastrad  * already killed if a resource to which a binding points
     44  1.1  riastrad  * needs to be swapped out.
     45  1.1  riastrad  *
     46  1.1  riastrad  * Note that a resource can be pointed to by bindings from multiple contexts,
     47  1.1  riastrad  * Therefore we can't easily protect this data by a per context mutex
     48  1.1  riastrad  * (unless we use deadlock-safe WW mutexes). So we use a global binding_mutex
     49  1.1  riastrad  * to protect all binding manager data.
     50  1.1  riastrad  *
     51  1.1  riastrad  * Finally, any association between a context and a global resource
     52  1.1  riastrad  * (surface, shader or even DX query) is conceptually a context binding that
     53  1.1  riastrad  * needs to be tracked by this code.
     54  1.1  riastrad  */
     55  1.1  riastrad 
     56  1.1  riastrad #include <sys/cdefs.h>
     57  1.1  riastrad __KERNEL_RCSID(0, "$NetBSD: vmwgfx_binding.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
     58  1.1  riastrad 
     59  1.1  riastrad #include "vmwgfx_drv.h"
     60  1.1  riastrad #include "vmwgfx_binding.h"
     61  1.1  riastrad #include "device_include/svga3d_reg.h"
     62  1.1  riastrad 
     63  1.1  riastrad #define VMW_BINDING_RT_BIT     0
     64  1.1  riastrad #define VMW_BINDING_PS_BIT     1
     65  1.1  riastrad #define VMW_BINDING_SO_BIT     2
     66  1.1  riastrad #define VMW_BINDING_VB_BIT     3
     67  1.1  riastrad #define VMW_BINDING_NUM_BITS   4
     68  1.1  riastrad 
     69  1.1  riastrad #define VMW_BINDING_PS_SR_BIT  0
     70  1.1  riastrad 
     71  1.1  riastrad /**
     72  1.1  riastrad  * struct vmw_ctx_binding_state - per context binding state
     73  1.1  riastrad  *
     74  1.1  riastrad  * @dev_priv: Pointer to device private structure.
     75  1.1  riastrad  * @list: linked list of individual active bindings.
     76  1.1  riastrad  * @render_targets: Render target bindings.
     77  1.1  riastrad  * @texture_units: Texture units bindings.
     78  1.1  riastrad  * @ds_view: Depth-stencil view binding.
     79  1.1  riastrad  * @so_targets: StreamOutput target bindings.
     80  1.1  riastrad  * @vertex_buffers: Vertex buffer bindings.
     81  1.1  riastrad  * @index_buffer: Index buffer binding.
     82  1.1  riastrad  * @per_shader: Per shader-type bindings.
     83  1.1  riastrad  * @dirty: Bitmap tracking per binding-type changes that have not yet
     84  1.1  riastrad  * been emitted to the device.
     85  1.1  riastrad  * @dirty_vb: Bitmap tracking individual vertex buffer binding changes that
     86  1.1  riastrad  * have not yet been emitted to the device.
     87  1.1  riastrad  * @bind_cmd_buffer: Scratch space used to construct binding commands.
     88  1.1  riastrad  * @bind_cmd_count: Number of binding command data entries in @bind_cmd_buffer
     89  1.1  riastrad  * @bind_first_slot: Used together with @bind_cmd_buffer to indicate the
     90  1.1  riastrad  * device binding slot of the first command data entry in @bind_cmd_buffer.
     91  1.1  riastrad  *
     92  1.1  riastrad  * Note that this structure also provides storage space for the individual
     93  1.1  riastrad  * struct vmw_ctx_binding objects, so that no dynamic allocation is needed
     94  1.1  riastrad  * for individual bindings.
     95  1.1  riastrad  *
     96  1.1  riastrad  */
     97  1.1  riastrad struct vmw_ctx_binding_state {
     98  1.1  riastrad 	struct vmw_private *dev_priv;
     99  1.1  riastrad 	struct list_head list;
    100  1.1  riastrad 	struct vmw_ctx_bindinfo_view render_targets[SVGA3D_RT_MAX];
    101  1.1  riastrad 	struct vmw_ctx_bindinfo_tex texture_units[SVGA3D_NUM_TEXTURE_UNITS];
    102  1.1  riastrad 	struct vmw_ctx_bindinfo_view ds_view;
    103  1.1  riastrad 	struct vmw_ctx_bindinfo_so so_targets[SVGA3D_DX_MAX_SOTARGETS];
    104  1.1  riastrad 	struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
    105  1.1  riastrad 	struct vmw_ctx_bindinfo_ib index_buffer;
    106  1.1  riastrad 	struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE_DX10];
    107  1.1  riastrad 
    108  1.1  riastrad 	unsigned long dirty;
    109  1.1  riastrad 	DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS);
    110  1.1  riastrad 
    111  1.1  riastrad 	u32 bind_cmd_buffer[VMW_MAX_VIEW_BINDINGS];
    112  1.1  riastrad 	u32 bind_cmd_count;
    113  1.1  riastrad 	u32 bind_first_slot;
    114  1.1  riastrad };
    115  1.1  riastrad 
    116  1.1  riastrad static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
    117  1.1  riastrad static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
    118  1.1  riastrad 					   bool rebind);
    119  1.1  riastrad static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
    120  1.1  riastrad static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind);
    121  1.1  riastrad static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind);
    122  1.1  riastrad static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind);
    123  1.1  riastrad static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind);
    124  1.1  riastrad static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs);
    125  1.1  riastrad static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi,
    126  1.1  riastrad 				       bool rebind);
    127  1.1  riastrad static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind);
    128  1.1  riastrad static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind);
    129  1.1  riastrad static void vmw_binding_build_asserts(void) __attribute__ ((unused));
    130  1.1  riastrad 
    131  1.1  riastrad typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
    132  1.1  riastrad 
    133  1.1  riastrad /**
    134  1.1  riastrad  * struct vmw_binding_info - Per binding type information for the binding
    135  1.1  riastrad  * manager
    136  1.1  riastrad  *
    137  1.1  riastrad  * @size: The size of the struct binding derived from a struct vmw_ctx_bindinfo.
    138  1.1  riastrad  * @offsets: array[shader_slot] of offsets to the array[slot]
    139  1.1  riastrad  * of struct bindings for the binding type.
    140  1.1  riastrad  * @scrub_func: Pointer to the scrub function for this binding type.
    141  1.1  riastrad  *
    142  1.1  riastrad  * Holds static information to help optimize the binding manager and avoid
    143  1.1  riastrad  * an excessive amount of switch statements.
    144  1.1  riastrad  */
    145  1.1  riastrad struct vmw_binding_info {
    146  1.1  riastrad 	size_t size;
    147  1.1  riastrad 	const size_t *offsets;
    148  1.1  riastrad 	vmw_scrub_func scrub_func;
    149  1.1  riastrad };
    150  1.1  riastrad 
    151  1.1  riastrad /*
    152  1.1  riastrad  * A number of static variables that help determine the scrub func and the
    153  1.1  riastrad  * location of the struct vmw_ctx_bindinfo slots for each binding type.
    154  1.1  riastrad  */
    155  1.1  riastrad static const size_t vmw_binding_shader_offsets[] = {
    156  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[0].shader),
    157  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[1].shader),
    158  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[2].shader),
    159  1.1  riastrad };
    160  1.1  riastrad static const size_t vmw_binding_rt_offsets[] = {
    161  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, render_targets),
    162  1.1  riastrad };
    163  1.1  riastrad static const size_t vmw_binding_tex_offsets[] = {
    164  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, texture_units),
    165  1.1  riastrad };
    166  1.1  riastrad static const size_t vmw_binding_cb_offsets[] = {
    167  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers),
    168  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers),
    169  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers),
    170  1.1  riastrad };
    171  1.1  riastrad static const size_t vmw_binding_dx_ds_offsets[] = {
    172  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, ds_view),
    173  1.1  riastrad };
    174  1.1  riastrad static const size_t vmw_binding_sr_offsets[] = {
    175  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res),
    176  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res),
    177  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res),
    178  1.1  riastrad };
    179  1.1  riastrad static const size_t vmw_binding_so_offsets[] = {
    180  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, so_targets),
    181  1.1  riastrad };
    182  1.1  riastrad static const size_t vmw_binding_vb_offsets[] = {
    183  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, vertex_buffers),
    184  1.1  riastrad };
    185  1.1  riastrad static const size_t vmw_binding_ib_offsets[] = {
    186  1.1  riastrad 	offsetof(struct vmw_ctx_binding_state, index_buffer),
    187  1.1  riastrad };
    188  1.1  riastrad 
    189  1.1  riastrad static const struct vmw_binding_info vmw_binding_infos[] = {
    190  1.1  riastrad 	[vmw_ctx_binding_shader] = {
    191  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_shader),
    192  1.1  riastrad 		.offsets = vmw_binding_shader_offsets,
    193  1.1  riastrad 		.scrub_func = vmw_binding_scrub_shader},
    194  1.1  riastrad 	[vmw_ctx_binding_rt] = {
    195  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_view),
    196  1.1  riastrad 		.offsets = vmw_binding_rt_offsets,
    197  1.1  riastrad 		.scrub_func = vmw_binding_scrub_render_target},
    198  1.1  riastrad 	[vmw_ctx_binding_tex] = {
    199  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_tex),
    200  1.1  riastrad 		.offsets = vmw_binding_tex_offsets,
    201  1.1  riastrad 		.scrub_func = vmw_binding_scrub_texture},
    202  1.1  riastrad 	[vmw_ctx_binding_cb] = {
    203  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_cb),
    204  1.1  riastrad 		.offsets = vmw_binding_cb_offsets,
    205  1.1  riastrad 		.scrub_func = vmw_binding_scrub_cb},
    206  1.1  riastrad 	[vmw_ctx_binding_dx_shader] = {
    207  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_shader),
    208  1.1  riastrad 		.offsets = vmw_binding_shader_offsets,
    209  1.1  riastrad 		.scrub_func = vmw_binding_scrub_dx_shader},
    210  1.1  riastrad 	[vmw_ctx_binding_dx_rt] = {
    211  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_view),
    212  1.1  riastrad 		.offsets = vmw_binding_rt_offsets,
    213  1.1  riastrad 		.scrub_func = vmw_binding_scrub_dx_rt},
    214  1.1  riastrad 	[vmw_ctx_binding_sr] = {
    215  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_view),
    216  1.1  riastrad 		.offsets = vmw_binding_sr_offsets,
    217  1.1  riastrad 		.scrub_func = vmw_binding_scrub_sr},
    218  1.1  riastrad 	[vmw_ctx_binding_ds] = {
    219  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_view),
    220  1.1  riastrad 		.offsets = vmw_binding_dx_ds_offsets,
    221  1.1  riastrad 		.scrub_func = vmw_binding_scrub_dx_rt},
    222  1.1  riastrad 	[vmw_ctx_binding_so] = {
    223  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_so),
    224  1.1  riastrad 		.offsets = vmw_binding_so_offsets,
    225  1.1  riastrad 		.scrub_func = vmw_binding_scrub_so},
    226  1.1  riastrad 	[vmw_ctx_binding_vb] = {
    227  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_vb),
    228  1.1  riastrad 		.offsets = vmw_binding_vb_offsets,
    229  1.1  riastrad 		.scrub_func = vmw_binding_scrub_vb},
    230  1.1  riastrad 	[vmw_ctx_binding_ib] = {
    231  1.1  riastrad 		.size = sizeof(struct vmw_ctx_bindinfo_ib),
    232  1.1  riastrad 		.offsets = vmw_binding_ib_offsets,
    233  1.1  riastrad 		.scrub_func = vmw_binding_scrub_ib},
    234  1.1  riastrad };
    235  1.1  riastrad 
    236  1.1  riastrad /**
    237  1.1  riastrad  * vmw_cbs_context - Return a pointer to the context resource of a
    238  1.1  riastrad  * context binding state tracker.
    239  1.1  riastrad  *
    240  1.1  riastrad  * @cbs: The context binding state tracker.
    241  1.1  riastrad  *
    242  1.1  riastrad  * Provided there are any active bindings, this function will return an
    243  1.1  riastrad  * unreferenced pointer to the context resource that owns the context
    244  1.1  riastrad  * binding state tracker. If there are no active bindings, this function
    245  1.1  riastrad  * will return NULL. Note that the caller must somehow ensure that a reference
    246  1.1  riastrad  * is held on the context resource prior to calling this function.
    247  1.1  riastrad  */
    248  1.1  riastrad static const struct vmw_resource *
    249  1.1  riastrad vmw_cbs_context(const struct vmw_ctx_binding_state *cbs)
    250  1.1  riastrad {
    251  1.1  riastrad 	if (list_empty(&cbs->list))
    252  1.1  riastrad 		return NULL;
    253  1.1  riastrad 
    254  1.1  riastrad 	return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo,
    255  1.1  riastrad 				ctx_list)->ctx;
    256  1.1  riastrad }
    257  1.1  riastrad 
    258  1.1  riastrad /**
    259  1.1  riastrad  * vmw_binding_loc - determine the struct vmw_ctx_bindinfo slot location.
    260  1.1  riastrad  *
    261  1.1  riastrad  * @cbs: Pointer to a struct vmw_ctx_binding state which holds the slot.
    262  1.1  riastrad  * @bt: The binding type.
    263  1.1  riastrad  * @shader_slot: The shader slot of the binding. If none, then set to 0.
    264  1.1  riastrad  * @slot: The slot of the binding.
    265  1.1  riastrad  */
    266  1.1  riastrad static struct vmw_ctx_bindinfo *
    267  1.1  riastrad vmw_binding_loc(struct vmw_ctx_binding_state *cbs,
    268  1.1  riastrad 		enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot)
    269  1.1  riastrad {
    270  1.1  riastrad 	const struct vmw_binding_info *b = &vmw_binding_infos[bt];
    271  1.1  riastrad 	size_t offset = b->offsets[shader_slot] + b->size*slot;
    272  1.1  riastrad 
    273  1.1  riastrad 	return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset);
    274  1.1  riastrad }
    275  1.1  riastrad 
    276  1.1  riastrad /**
    277  1.1  riastrad  * vmw_binding_drop: Stop tracking a context binding
    278  1.1  riastrad  *
    279  1.1  riastrad  * @bi: Pointer to binding tracker storage.
    280  1.1  riastrad  *
    281  1.1  riastrad  * Stops tracking a context binding, and re-initializes its storage.
    282  1.1  riastrad  * Typically used when the context binding is replaced with a binding to
    283  1.1  riastrad  * another (or the same, for that matter) resource.
    284  1.1  riastrad  */
    285  1.1  riastrad static void vmw_binding_drop(struct vmw_ctx_bindinfo *bi)
    286  1.1  riastrad {
    287  1.1  riastrad 	list_del(&bi->ctx_list);
    288  1.1  riastrad 	if (!list_empty(&bi->res_list))
    289  1.1  riastrad 		list_del(&bi->res_list);
    290  1.1  riastrad 	bi->ctx = NULL;
    291  1.1  riastrad }
    292  1.1  riastrad 
    293  1.1  riastrad /**
    294  1.1  riastrad  * vmw_binding_add: Start tracking a context binding
    295  1.1  riastrad  *
    296  1.1  riastrad  * @cbs: Pointer to the context binding state tracker.
    297  1.1  riastrad  * @bi: Information about the binding to track.
    298  1.1  riastrad  *
    299  1.1  riastrad  * Starts tracking the binding in the context binding
    300  1.1  riastrad  * state structure @cbs.
    301  1.1  riastrad  */
    302  1.1  riastrad void vmw_binding_add(struct vmw_ctx_binding_state *cbs,
    303  1.1  riastrad 		    const struct vmw_ctx_bindinfo *bi,
    304  1.1  riastrad 		    u32 shader_slot, u32 slot)
    305  1.1  riastrad {
    306  1.1  riastrad 	struct vmw_ctx_bindinfo *loc =
    307  1.1  riastrad 		vmw_binding_loc(cbs, bi->bt, shader_slot, slot);
    308  1.1  riastrad 	const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt];
    309  1.1  riastrad 
    310  1.1  riastrad 	if (loc->ctx != NULL)
    311  1.1  riastrad 		vmw_binding_drop(loc);
    312  1.1  riastrad 
    313  1.1  riastrad 	memcpy(loc, bi, b->size);
    314  1.1  riastrad 	loc->scrubbed = false;
    315  1.1  riastrad 	list_add(&loc->ctx_list, &cbs->list);
    316  1.1  riastrad 	INIT_LIST_HEAD(&loc->res_list);
    317  1.1  riastrad }
    318  1.1  riastrad 
    319  1.1  riastrad /**
    320  1.1  riastrad  * vmw_binding_transfer: Transfer a context binding tracking entry.
    321  1.1  riastrad  *
    322  1.1  riastrad  * @cbs: Pointer to the persistent context binding state tracker.
    323  1.1  riastrad  * @bi: Information about the binding to track.
    324  1.1  riastrad  *
    325  1.1  riastrad  */
    326  1.1  riastrad static void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs,
    327  1.1  riastrad 				 const struct vmw_ctx_binding_state *from,
    328  1.1  riastrad 				 const struct vmw_ctx_bindinfo *bi)
    329  1.1  riastrad {
    330  1.1  riastrad 	size_t offset = (unsigned long)bi - (unsigned long)from;
    331  1.1  riastrad 	struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *)
    332  1.1  riastrad 		((unsigned long) cbs + offset);
    333  1.1  riastrad 
    334  1.1  riastrad 	if (loc->ctx != NULL) {
    335  1.1  riastrad 		WARN_ON(bi->scrubbed);
    336  1.1  riastrad 
    337  1.1  riastrad 		vmw_binding_drop(loc);
    338  1.1  riastrad 	}
    339  1.1  riastrad 
    340  1.1  riastrad 	if (bi->res != NULL) {
    341  1.1  riastrad 		memcpy(loc, bi, vmw_binding_infos[bi->bt].size);
    342  1.1  riastrad 		list_add_tail(&loc->ctx_list, &cbs->list);
    343  1.1  riastrad 		list_add_tail(&loc->res_list, &loc->res->binding_head);
    344  1.1  riastrad 	}
    345  1.1  riastrad }
    346  1.1  riastrad 
    347  1.1  riastrad /**
    348  1.1  riastrad  * vmw_binding_state_kill - Kill all bindings associated with a
    349  1.1  riastrad  * struct vmw_ctx_binding state structure, and re-initialize the structure.
    350  1.1  riastrad  *
    351  1.1  riastrad  * @cbs: Pointer to the context binding state tracker.
    352  1.1  riastrad  *
    353  1.1  riastrad  * Emits commands to scrub all bindings associated with the
    354  1.1  riastrad  * context binding state tracker. Then re-initializes the whole structure.
    355  1.1  riastrad  */
    356  1.1  riastrad void vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs)
    357  1.1  riastrad {
    358  1.1  riastrad 	struct vmw_ctx_bindinfo *entry, *next;
    359  1.1  riastrad 
    360  1.1  riastrad 	vmw_binding_state_scrub(cbs);
    361  1.1  riastrad 	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
    362  1.1  riastrad 		vmw_binding_drop(entry);
    363  1.1  riastrad }
    364  1.1  riastrad 
    365  1.1  riastrad /**
    366  1.1  riastrad  * vmw_binding_state_scrub - Scrub all bindings associated with a
    367  1.1  riastrad  * struct vmw_ctx_binding state structure.
    368  1.1  riastrad  *
    369  1.1  riastrad  * @cbs: Pointer to the context binding state tracker.
    370  1.1  riastrad  *
    371  1.1  riastrad  * Emits commands to scrub all bindings associated with the
    372  1.1  riastrad  * context binding state tracker.
    373  1.1  riastrad  */
    374  1.1  riastrad void vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
    375  1.1  riastrad {
    376  1.1  riastrad 	struct vmw_ctx_bindinfo *entry;
    377  1.1  riastrad 
    378  1.1  riastrad 	list_for_each_entry(entry, &cbs->list, ctx_list) {
    379  1.1  riastrad 		if (!entry->scrubbed) {
    380  1.1  riastrad 			(void) vmw_binding_infos[entry->bt].scrub_func
    381  1.1  riastrad 				(entry, false);
    382  1.1  riastrad 			entry->scrubbed = true;
    383  1.1  riastrad 		}
    384  1.1  riastrad 	}
    385  1.1  riastrad 
    386  1.1  riastrad 	(void) vmw_binding_emit_dirty(cbs);
    387  1.1  riastrad }
    388  1.1  riastrad 
    389  1.1  riastrad /**
    390  1.1  riastrad  * vmw_binding_res_list_kill - Kill all bindings on a
    391  1.1  riastrad  * resource binding list
    392  1.1  riastrad  *
    393  1.1  riastrad  * @head: list head of resource binding list
    394  1.1  riastrad  *
    395  1.1  riastrad  * Kills all bindings associated with a specific resource. Typically
    396  1.1  riastrad  * called before the resource is destroyed.
    397  1.1  riastrad  */
    398  1.1  riastrad void vmw_binding_res_list_kill(struct list_head *head)
    399  1.1  riastrad {
    400  1.1  riastrad 	struct vmw_ctx_bindinfo *entry, *next;
    401  1.1  riastrad 
    402  1.1  riastrad 	vmw_binding_res_list_scrub(head);
    403  1.1  riastrad 	list_for_each_entry_safe(entry, next, head, res_list)
    404  1.1  riastrad 		vmw_binding_drop(entry);
    405  1.1  riastrad }
    406  1.1  riastrad 
    407  1.1  riastrad /**
    408  1.1  riastrad  * vmw_binding_res_list_scrub - Scrub all bindings on a
    409  1.1  riastrad  * resource binding list
    410  1.1  riastrad  *
    411  1.1  riastrad  * @head: list head of resource binding list
    412  1.1  riastrad  *
    413  1.1  riastrad  * Scrub all bindings associated with a specific resource. Typically
    414  1.1  riastrad  * called before the resource is evicted.
    415  1.1  riastrad  */
    416  1.1  riastrad void vmw_binding_res_list_scrub(struct list_head *head)
    417  1.1  riastrad {
    418  1.1  riastrad 	struct vmw_ctx_bindinfo *entry;
    419  1.1  riastrad 
    420  1.1  riastrad 	list_for_each_entry(entry, head, res_list) {
    421  1.1  riastrad 		if (!entry->scrubbed) {
    422  1.1  riastrad 			(void) vmw_binding_infos[entry->bt].scrub_func
    423  1.1  riastrad 				(entry, false);
    424  1.1  riastrad 			entry->scrubbed = true;
    425  1.1  riastrad 		}
    426  1.1  riastrad 	}
    427  1.1  riastrad 
    428  1.1  riastrad 	list_for_each_entry(entry, head, res_list) {
    429  1.1  riastrad 		struct vmw_ctx_binding_state *cbs =
    430  1.1  riastrad 			vmw_context_binding_state(entry->ctx);
    431  1.1  riastrad 
    432  1.1  riastrad 		(void) vmw_binding_emit_dirty(cbs);
    433  1.1  riastrad 	}
    434  1.1  riastrad }
    435  1.1  riastrad 
    436  1.1  riastrad 
    437  1.1  riastrad /**
    438  1.1  riastrad  * vmw_binding_state_commit - Commit staged binding info
    439  1.1  riastrad  *
    440  1.1  riastrad  * @ctx: Pointer to context to commit the staged binding info to.
    441  1.1  riastrad  * @from: Staged binding info built during execbuf.
    442  1.1  riastrad  * @scrubbed: Transfer only scrubbed bindings.
    443  1.1  riastrad  *
    444  1.1  riastrad  * Transfers binding info from a temporary structure
    445  1.1  riastrad  * (typically used by execbuf) to the persistent
    446  1.1  riastrad  * structure in the context. This can be done once commands have been
    447  1.1  riastrad  * submitted to hardware
    448  1.1  riastrad  */
    449  1.1  riastrad void vmw_binding_state_commit(struct vmw_ctx_binding_state *to,
    450  1.1  riastrad 			      struct vmw_ctx_binding_state *from)
    451  1.1  riastrad {
    452  1.1  riastrad 	struct vmw_ctx_bindinfo *entry, *next;
    453  1.1  riastrad 
    454  1.1  riastrad 	list_for_each_entry_safe(entry, next, &from->list, ctx_list) {
    455  1.1  riastrad 		vmw_binding_transfer(to, from, entry);
    456  1.1  riastrad 		vmw_binding_drop(entry);
    457  1.1  riastrad 	}
    458  1.1  riastrad }
    459  1.1  riastrad 
    460  1.1  riastrad /**
    461  1.1  riastrad  * vmw_binding_rebind_all - Rebind all scrubbed bindings of a context
    462  1.1  riastrad  *
    463  1.1  riastrad  * @ctx: The context resource
    464  1.1  riastrad  *
    465  1.1  riastrad  * Walks through the context binding list and rebinds all scrubbed
    466  1.1  riastrad  * resources.
    467  1.1  riastrad  */
    468  1.1  riastrad int vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs)
    469  1.1  riastrad {
    470  1.1  riastrad 	struct vmw_ctx_bindinfo *entry;
    471  1.1  riastrad 	int ret;
    472  1.1  riastrad 
    473  1.1  riastrad 	list_for_each_entry(entry, &cbs->list, ctx_list) {
    474  1.1  riastrad 		if (likely(!entry->scrubbed))
    475  1.1  riastrad 			continue;
    476  1.1  riastrad 
    477  1.1  riastrad 		if ((entry->res == NULL || entry->res->id ==
    478  1.1  riastrad 			    SVGA3D_INVALID_ID))
    479  1.1  riastrad 			continue;
    480  1.1  riastrad 
    481  1.1  riastrad 		ret = vmw_binding_infos[entry->bt].scrub_func(entry, true);
    482  1.1  riastrad 		if (unlikely(ret != 0))
    483  1.1  riastrad 			return ret;
    484  1.1  riastrad 
    485  1.1  riastrad 		entry->scrubbed = false;
    486  1.1  riastrad 	}
    487  1.1  riastrad 
    488  1.1  riastrad 	return vmw_binding_emit_dirty(cbs);
    489  1.1  riastrad }
    490  1.1  riastrad 
    491  1.1  riastrad /**
    492  1.1  riastrad  * vmw_binding_scrub_shader - scrub a shader binding from a context.
    493  1.1  riastrad  *
    494  1.1  riastrad  * @bi: single binding information.
    495  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
    496  1.1  riastrad  */
    497  1.1  riastrad static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
    498  1.1  riastrad {
    499  1.1  riastrad 	struct vmw_ctx_bindinfo_shader *binding =
    500  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
    501  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
    502  1.1  riastrad 	struct {
    503  1.1  riastrad 		SVGA3dCmdHeader header;
    504  1.1  riastrad 		SVGA3dCmdSetShader body;
    505  1.1  riastrad 	} *cmd;
    506  1.1  riastrad 
    507  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
    508  1.3  riastrad 	if (unlikely(cmd == NULL))
    509  1.1  riastrad 		return -ENOMEM;
    510  1.1  riastrad 
    511  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_SET_SHADER;
    512  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    513  1.1  riastrad 	cmd->body.cid = bi->ctx->id;
    514  1.1  riastrad 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
    515  1.1  riastrad 	cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
    516  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    517  1.1  riastrad 
    518  1.1  riastrad 	return 0;
    519  1.1  riastrad }
    520  1.1  riastrad 
    521  1.1  riastrad /**
    522  1.1  riastrad  * vmw_binding_scrub_render_target - scrub a render target binding
    523  1.1  riastrad  * from a context.
    524  1.1  riastrad  *
    525  1.1  riastrad  * @bi: single binding information.
    526  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
    527  1.1  riastrad  */
    528  1.1  riastrad static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
    529  1.1  riastrad 					   bool rebind)
    530  1.1  riastrad {
    531  1.1  riastrad 	struct vmw_ctx_bindinfo_view *binding =
    532  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
    533  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
    534  1.1  riastrad 	struct {
    535  1.1  riastrad 		SVGA3dCmdHeader header;
    536  1.1  riastrad 		SVGA3dCmdSetRenderTarget body;
    537  1.1  riastrad 	} *cmd;
    538  1.1  riastrad 
    539  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
    540  1.3  riastrad 	if (unlikely(cmd == NULL))
    541  1.1  riastrad 		return -ENOMEM;
    542  1.1  riastrad 
    543  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
    544  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    545  1.1  riastrad 	cmd->body.cid = bi->ctx->id;
    546  1.1  riastrad 	cmd->body.type = binding->slot;
    547  1.1  riastrad 	cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
    548  1.1  riastrad 	cmd->body.target.face = 0;
    549  1.1  riastrad 	cmd->body.target.mipmap = 0;
    550  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    551  1.1  riastrad 
    552  1.1  riastrad 	return 0;
    553  1.1  riastrad }
    554  1.1  riastrad 
    555  1.1  riastrad /**
    556  1.1  riastrad  * vmw_binding_scrub_texture - scrub a texture binding from a context.
    557  1.1  riastrad  *
    558  1.1  riastrad  * @bi: single binding information.
    559  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
    560  1.1  riastrad  *
    561  1.1  riastrad  * TODO: Possibly complement this function with a function that takes
    562  1.1  riastrad  * a list of texture bindings and combines them to a single command.
    563  1.1  riastrad  */
    564  1.1  riastrad static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi,
    565  1.1  riastrad 				     bool rebind)
    566  1.1  riastrad {
    567  1.1  riastrad 	struct vmw_ctx_bindinfo_tex *binding =
    568  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
    569  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
    570  1.1  riastrad 	struct {
    571  1.1  riastrad 		SVGA3dCmdHeader header;
    572  1.1  riastrad 		struct {
    573  1.1  riastrad 			SVGA3dCmdSetTextureState c;
    574  1.1  riastrad 			SVGA3dTextureState s1;
    575  1.1  riastrad 		} body;
    576  1.1  riastrad 	} *cmd;
    577  1.1  riastrad 
    578  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
    579  1.3  riastrad 	if (unlikely(cmd == NULL))
    580  1.1  riastrad 		return -ENOMEM;
    581  1.1  riastrad 
    582  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
    583  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    584  1.1  riastrad 	cmd->body.c.cid = bi->ctx->id;
    585  1.1  riastrad 	cmd->body.s1.stage = binding->texture_stage;
    586  1.1  riastrad 	cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
    587  1.1  riastrad 	cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
    588  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    589  1.1  riastrad 
    590  1.1  riastrad 	return 0;
    591  1.1  riastrad }
    592  1.1  riastrad 
    593  1.1  riastrad /**
    594  1.1  riastrad  * vmw_binding_scrub_dx_shader - scrub a dx shader binding from a context.
    595  1.1  riastrad  *
    596  1.1  riastrad  * @bi: single binding information.
    597  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
    598  1.1  riastrad  */
    599  1.1  riastrad static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
    600  1.1  riastrad {
    601  1.1  riastrad 	struct vmw_ctx_bindinfo_shader *binding =
    602  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
    603  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
    604  1.1  riastrad 	struct {
    605  1.1  riastrad 		SVGA3dCmdHeader header;
    606  1.1  riastrad 		SVGA3dCmdDXSetShader body;
    607  1.1  riastrad 	} *cmd;
    608  1.1  riastrad 
    609  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id);
    610  1.3  riastrad 	if (unlikely(cmd == NULL))
    611  1.1  riastrad 		return -ENOMEM;
    612  1.3  riastrad 
    613  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER;
    614  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    615  1.1  riastrad 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
    616  1.1  riastrad 	cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
    617  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    618  1.1  riastrad 
    619  1.1  riastrad 	return 0;
    620  1.1  riastrad }
    621  1.1  riastrad 
    622  1.1  riastrad /**
    623  1.1  riastrad  * vmw_binding_scrub_cb - scrub a constant buffer binding from a context.
    624  1.1  riastrad  *
    625  1.1  riastrad  * @bi: single binding information.
    626  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
    627  1.1  riastrad  */
    628  1.1  riastrad static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind)
    629  1.1  riastrad {
    630  1.1  riastrad 	struct vmw_ctx_bindinfo_cb *binding =
    631  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
    632  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
    633  1.1  riastrad 	struct {
    634  1.1  riastrad 		SVGA3dCmdHeader header;
    635  1.1  riastrad 		SVGA3dCmdDXSetSingleConstantBuffer body;
    636  1.1  riastrad 	} *cmd;
    637  1.1  riastrad 
    638  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id);
    639  1.3  riastrad 	if (unlikely(cmd == NULL))
    640  1.1  riastrad 		return -ENOMEM;
    641  1.1  riastrad 
    642  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER;
    643  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    644  1.1  riastrad 	cmd->body.slot = binding->slot;
    645  1.1  riastrad 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
    646  1.1  riastrad 	if (rebind) {
    647  1.1  riastrad 		cmd->body.offsetInBytes = binding->offset;
    648  1.1  riastrad 		cmd->body.sizeInBytes = binding->size;
    649  1.1  riastrad 		cmd->body.sid = bi->res->id;
    650  1.1  riastrad 	} else {
    651  1.1  riastrad 		cmd->body.offsetInBytes = 0;
    652  1.1  riastrad 		cmd->body.sizeInBytes = 0;
    653  1.1  riastrad 		cmd->body.sid = SVGA3D_INVALID_ID;
    654  1.1  riastrad 	}
    655  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    656  1.1  riastrad 
    657  1.1  riastrad 	return 0;
    658  1.1  riastrad }
    659  1.1  riastrad 
    660  1.1  riastrad /**
    661  1.1  riastrad  * vmw_collect_view_ids - Build view id data for a view binding command
    662  1.1  riastrad  * without checking which bindings actually need to be emitted
    663  1.1  riastrad  *
    664  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    665  1.1  riastrad  * @bi: Pointer to where the binding info array is stored in @cbs
    666  1.1  riastrad  * @max_num: Maximum number of entries in the @bi array.
    667  1.1  riastrad  *
    668  1.1  riastrad  * Scans the @bi array for bindings and builds a buffer of view id data.
    669  1.1  riastrad  * Stops at the first non-existing binding in the @bi array.
    670  1.1  riastrad  * On output, @cbs->bind_cmd_count contains the number of bindings to be
    671  1.1  riastrad  * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer
    672  1.1  riastrad  * contains the command data.
    673  1.1  riastrad  */
    674  1.1  riastrad static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs,
    675  1.1  riastrad 				 const struct vmw_ctx_bindinfo *bi,
    676  1.1  riastrad 				 u32 max_num)
    677  1.1  riastrad {
    678  1.1  riastrad 	const struct vmw_ctx_bindinfo_view *biv =
    679  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_view, bi);
    680  1.1  riastrad 	unsigned long i;
    681  1.1  riastrad 
    682  1.1  riastrad 	cbs->bind_cmd_count = 0;
    683  1.1  riastrad 	cbs->bind_first_slot = 0;
    684  1.1  riastrad 
    685  1.1  riastrad 	for (i = 0; i < max_num; ++i, ++biv) {
    686  1.1  riastrad 		if (!biv->bi.ctx)
    687  1.1  riastrad 			break;
    688  1.1  riastrad 
    689  1.1  riastrad 		cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
    690  1.1  riastrad 			((biv->bi.scrubbed) ?
    691  1.1  riastrad 			 SVGA3D_INVALID_ID : biv->bi.res->id);
    692  1.1  riastrad 	}
    693  1.1  riastrad }
    694  1.1  riastrad 
    695  1.1  riastrad /**
    696  1.1  riastrad  * vmw_collect_dirty_view_ids - Build view id data for a view binding command
    697  1.1  riastrad  *
    698  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    699  1.1  riastrad  * @bi: Pointer to where the binding info array is stored in @cbs
    700  1.1  riastrad  * @dirty: Bitmap indicating which bindings need to be emitted.
    701  1.1  riastrad  * @max_num: Maximum number of entries in the @bi array.
    702  1.1  riastrad  *
    703  1.1  riastrad  * Scans the @bi array for bindings that need to be emitted and
    704  1.1  riastrad  * builds a buffer of view id data.
    705  1.1  riastrad  * On output, @cbs->bind_cmd_count contains the number of bindings to be
    706  1.1  riastrad  * emitted, @cbs->bind_first_slot indicates the index of the first emitted
    707  1.1  riastrad  * binding, and @cbs->bind_cmd_buffer contains the command data.
    708  1.1  riastrad  */
    709  1.1  riastrad static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs,
    710  1.1  riastrad 				       const struct vmw_ctx_bindinfo *bi,
    711  1.1  riastrad 				       unsigned long *dirty,
    712  1.1  riastrad 				       u32 max_num)
    713  1.1  riastrad {
    714  1.1  riastrad 	const struct vmw_ctx_bindinfo_view *biv =
    715  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_view, bi);
    716  1.1  riastrad 	unsigned long i, next_bit;
    717  1.1  riastrad 
    718  1.1  riastrad 	cbs->bind_cmd_count = 0;
    719  1.1  riastrad 	i = find_first_bit(dirty, max_num);
    720  1.1  riastrad 	next_bit = i;
    721  1.1  riastrad 	cbs->bind_first_slot = i;
    722  1.1  riastrad 
    723  1.1  riastrad 	biv += i;
    724  1.1  riastrad 	for (; i < max_num; ++i, ++biv) {
    725  1.1  riastrad 		cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
    726  1.1  riastrad 			((!biv->bi.ctx || biv->bi.scrubbed) ?
    727  1.1  riastrad 			 SVGA3D_INVALID_ID : biv->bi.res->id);
    728  1.1  riastrad 
    729  1.1  riastrad 		if (next_bit == i) {
    730  1.1  riastrad 			next_bit = find_next_bit(dirty, max_num, i + 1);
    731  1.1  riastrad 			if (next_bit >= max_num)
    732  1.1  riastrad 				break;
    733  1.1  riastrad 		}
    734  1.1  riastrad 	}
    735  1.1  riastrad }
    736  1.1  riastrad 
    737  1.1  riastrad /**
    738  1.1  riastrad  * vmw_binding_emit_set_sr - Issue delayed DX shader resource binding commands
    739  1.1  riastrad  *
    740  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    741  1.1  riastrad  */
    742  1.1  riastrad static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs,
    743  1.1  riastrad 			   int shader_slot)
    744  1.1  riastrad {
    745  1.1  riastrad 	const struct vmw_ctx_bindinfo *loc =
    746  1.1  riastrad 		&cbs->per_shader[shader_slot].shader_res[0].bi;
    747  1.1  riastrad 	struct {
    748  1.1  riastrad 		SVGA3dCmdHeader header;
    749  1.1  riastrad 		SVGA3dCmdDXSetShaderResources body;
    750  1.1  riastrad 	} *cmd;
    751  1.1  riastrad 	size_t cmd_size, view_id_size;
    752  1.1  riastrad 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
    753  1.1  riastrad 
    754  1.1  riastrad 	vmw_collect_dirty_view_ids(cbs, loc,
    755  1.1  riastrad 				   cbs->per_shader[shader_slot].dirty_sr,
    756  1.1  riastrad 				   SVGA3D_DX_MAX_SRVIEWS);
    757  1.1  riastrad 	if (cbs->bind_cmd_count == 0)
    758  1.1  riastrad 		return 0;
    759  1.1  riastrad 
    760  1.1  riastrad 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
    761  1.1  riastrad 	cmd_size = sizeof(*cmd) + view_id_size;
    762  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
    763  1.3  riastrad 	if (unlikely(cmd == NULL))
    764  1.1  riastrad 		return -ENOMEM;
    765  1.1  riastrad 
    766  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES;
    767  1.1  riastrad 	cmd->header.size = sizeof(cmd->body) + view_id_size;
    768  1.1  riastrad 	cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN;
    769  1.1  riastrad 	cmd->body.startView = cbs->bind_first_slot;
    770  1.1  riastrad 
    771  1.1  riastrad 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
    772  1.1  riastrad 
    773  1.1  riastrad 	vmw_fifo_commit(ctx->dev_priv, cmd_size);
    774  1.1  riastrad 	bitmap_clear(cbs->per_shader[shader_slot].dirty_sr,
    775  1.1  riastrad 		     cbs->bind_first_slot, cbs->bind_cmd_count);
    776  1.1  riastrad 
    777  1.1  riastrad 	return 0;
    778  1.1  riastrad }
    779  1.1  riastrad 
    780  1.1  riastrad /**
    781  1.1  riastrad  * vmw_binding_emit_set_rt - Issue delayed DX rendertarget binding commands
    782  1.1  riastrad  *
    783  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    784  1.1  riastrad  */
    785  1.1  riastrad static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
    786  1.1  riastrad {
    787  1.1  riastrad 	const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi;
    788  1.1  riastrad 	struct {
    789  1.1  riastrad 		SVGA3dCmdHeader header;
    790  1.1  riastrad 		SVGA3dCmdDXSetRenderTargets body;
    791  1.1  riastrad 	} *cmd;
    792  1.1  riastrad 	size_t cmd_size, view_id_size;
    793  1.1  riastrad 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
    794  1.1  riastrad 
    795  1.1  riastrad 	vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS);
    796  1.1  riastrad 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
    797  1.1  riastrad 	cmd_size = sizeof(*cmd) + view_id_size;
    798  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
    799  1.3  riastrad 	if (unlikely(cmd == NULL))
    800  1.1  riastrad 		return -ENOMEM;
    801  1.1  riastrad 
    802  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS;
    803  1.1  riastrad 	cmd->header.size = sizeof(cmd->body) + view_id_size;
    804  1.1  riastrad 
    805  1.1  riastrad 	if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed)
    806  1.1  riastrad 		cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id;
    807  1.1  riastrad 	else
    808  1.1  riastrad 		cmd->body.depthStencilViewId = SVGA3D_INVALID_ID;
    809  1.1  riastrad 
    810  1.1  riastrad 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
    811  1.1  riastrad 
    812  1.1  riastrad 	vmw_fifo_commit(ctx->dev_priv, cmd_size);
    813  1.1  riastrad 
    814  1.1  riastrad 	return 0;
    815  1.1  riastrad 
    816  1.1  riastrad }
    817  1.1  riastrad 
    818  1.1  riastrad /**
    819  1.1  riastrad  * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command
    820  1.1  riastrad  * without checking which bindings actually need to be emitted
    821  1.1  riastrad  *
    822  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    823  1.1  riastrad  * @bi: Pointer to where the binding info array is stored in @cbs
    824  1.1  riastrad  * @max_num: Maximum number of entries in the @bi array.
    825  1.1  riastrad  *
    826  1.1  riastrad  * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data.
    827  1.1  riastrad  * Stops at the first non-existing binding in the @bi array.
    828  1.1  riastrad  * On output, @cbs->bind_cmd_count contains the number of bindings to be
    829  1.1  riastrad  * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer
    830  1.1  riastrad  * contains the command data.
    831  1.1  riastrad  */
    832  1.1  riastrad static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs,
    833  1.1  riastrad 				   const struct vmw_ctx_bindinfo *bi,
    834  1.1  riastrad 				   u32 max_num)
    835  1.1  riastrad {
    836  1.1  riastrad 	const struct vmw_ctx_bindinfo_so *biso =
    837  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_so, bi);
    838  1.1  riastrad 	unsigned long i;
    839  1.1  riastrad 	SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer;
    840  1.1  riastrad 
    841  1.1  riastrad 	cbs->bind_cmd_count = 0;
    842  1.1  riastrad 	cbs->bind_first_slot = 0;
    843  1.1  riastrad 
    844  1.1  riastrad 	for (i = 0; i < max_num; ++i, ++biso, ++so_buffer,
    845  1.1  riastrad 		    ++cbs->bind_cmd_count) {
    846  1.1  riastrad 		if (!biso->bi.ctx)
    847  1.1  riastrad 			break;
    848  1.1  riastrad 
    849  1.1  riastrad 		if (!biso->bi.scrubbed) {
    850  1.1  riastrad 			so_buffer->sid = biso->bi.res->id;
    851  1.1  riastrad 			so_buffer->offset = biso->offset;
    852  1.1  riastrad 			so_buffer->sizeInBytes = biso->size;
    853  1.1  riastrad 		} else {
    854  1.1  riastrad 			so_buffer->sid = SVGA3D_INVALID_ID;
    855  1.1  riastrad 			so_buffer->offset = 0;
    856  1.1  riastrad 			so_buffer->sizeInBytes = 0;
    857  1.1  riastrad 		}
    858  1.1  riastrad 	}
    859  1.1  riastrad }
    860  1.1  riastrad 
    861  1.1  riastrad /**
    862  1.1  riastrad  * vmw_binding_emit_set_so - Issue delayed streamout binding commands
    863  1.1  riastrad  *
    864  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    865  1.1  riastrad  */
    866  1.1  riastrad static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs)
    867  1.1  riastrad {
    868  1.1  riastrad 	const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi;
    869  1.1  riastrad 	struct {
    870  1.1  riastrad 		SVGA3dCmdHeader header;
    871  1.1  riastrad 		SVGA3dCmdDXSetSOTargets body;
    872  1.1  riastrad 	} *cmd;
    873  1.1  riastrad 	size_t cmd_size, so_target_size;
    874  1.1  riastrad 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
    875  1.1  riastrad 
    876  1.1  riastrad 	vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS);
    877  1.1  riastrad 	if (cbs->bind_cmd_count == 0)
    878  1.1  riastrad 		return 0;
    879  1.1  riastrad 
    880  1.1  riastrad 	so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget);
    881  1.1  riastrad 	cmd_size = sizeof(*cmd) + so_target_size;
    882  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
    883  1.3  riastrad 	if (unlikely(cmd == NULL))
    884  1.1  riastrad 		return -ENOMEM;
    885  1.1  riastrad 
    886  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS;
    887  1.1  riastrad 	cmd->header.size = sizeof(cmd->body) + so_target_size;
    888  1.1  riastrad 	memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size);
    889  1.1  riastrad 
    890  1.1  riastrad 	vmw_fifo_commit(ctx->dev_priv, cmd_size);
    891  1.1  riastrad 
    892  1.1  riastrad 	return 0;
    893  1.1  riastrad 
    894  1.1  riastrad }
    895  1.1  riastrad 
    896  1.1  riastrad /**
    897  1.1  riastrad  * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands
    898  1.1  riastrad  *
    899  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    900  1.1  riastrad  *
    901  1.1  riastrad  */
    902  1.1  riastrad static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs)
    903  1.1  riastrad {
    904  1.1  riastrad 	struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0];
    905  1.1  riastrad 	u32 i;
    906  1.1  riastrad 	int ret;
    907  1.1  riastrad 
    908  1.1  riastrad 	for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) {
    909  1.1  riastrad 		if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty))
    910  1.1  riastrad 			continue;
    911  1.1  riastrad 
    912  1.1  riastrad 		ret = vmw_emit_set_sr(cbs, i);
    913  1.1  riastrad 		if (ret)
    914  1.1  riastrad 			break;
    915  1.1  riastrad 
    916  1.1  riastrad 		__clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty);
    917  1.1  riastrad 	}
    918  1.1  riastrad 
    919  1.1  riastrad 	return 0;
    920  1.1  riastrad }
    921  1.1  riastrad 
    922  1.1  riastrad /**
    923  1.1  riastrad  * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a
    924  1.1  riastrad  * SVGA3dCmdDXSetVertexBuffers command
    925  1.1  riastrad  *
    926  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    927  1.1  riastrad  * @bi: Pointer to where the binding info array is stored in @cbs
    928  1.1  riastrad  * @dirty: Bitmap indicating which bindings need to be emitted.
    929  1.1  riastrad  * @max_num: Maximum number of entries in the @bi array.
    930  1.1  riastrad  *
    931  1.1  riastrad  * Scans the @bi array for bindings that need to be emitted and
    932  1.1  riastrad  * builds a buffer of SVGA3dVertexBuffer data.
    933  1.1  riastrad  * On output, @cbs->bind_cmd_count contains the number of bindings to be
    934  1.1  riastrad  * emitted, @cbs->bind_first_slot indicates the index of the first emitted
    935  1.1  riastrad  * binding, and @cbs->bind_cmd_buffer contains the command data.
    936  1.1  riastrad  */
    937  1.1  riastrad static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs,
    938  1.1  riastrad 				  const struct vmw_ctx_bindinfo *bi,
    939  1.1  riastrad 				  unsigned long *dirty,
    940  1.1  riastrad 				  u32 max_num)
    941  1.1  riastrad {
    942  1.1  riastrad 	const struct vmw_ctx_bindinfo_vb *biv =
    943  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
    944  1.1  riastrad 	unsigned long i, next_bit;
    945  1.1  riastrad 	SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer;
    946  1.1  riastrad 
    947  1.1  riastrad 	cbs->bind_cmd_count = 0;
    948  1.1  riastrad 	i = find_first_bit(dirty, max_num);
    949  1.1  riastrad 	next_bit = i;
    950  1.1  riastrad 	cbs->bind_first_slot = i;
    951  1.1  riastrad 
    952  1.1  riastrad 	biv += i;
    953  1.1  riastrad 	for (; i < max_num; ++i, ++biv, ++vbs) {
    954  1.1  riastrad 		if (!biv->bi.ctx || biv->bi.scrubbed) {
    955  1.1  riastrad 			vbs->sid = SVGA3D_INVALID_ID;
    956  1.1  riastrad 			vbs->stride = 0;
    957  1.1  riastrad 			vbs->offset = 0;
    958  1.1  riastrad 		} else {
    959  1.1  riastrad 			vbs->sid = biv->bi.res->id;
    960  1.1  riastrad 			vbs->stride = biv->stride;
    961  1.1  riastrad 			vbs->offset = biv->offset;
    962  1.1  riastrad 		}
    963  1.1  riastrad 		cbs->bind_cmd_count++;
    964  1.1  riastrad 		if (next_bit == i) {
    965  1.1  riastrad 			next_bit = find_next_bit(dirty, max_num, i + 1);
    966  1.1  riastrad 			if (next_bit >= max_num)
    967  1.1  riastrad 				break;
    968  1.1  riastrad 		}
    969  1.1  riastrad 	}
    970  1.1  riastrad }
    971  1.1  riastrad 
    972  1.1  riastrad /**
    973  1.1  riastrad  * vmw_binding_emit_set_vb - Issue delayed vertex buffer binding commands
    974  1.1  riastrad  *
    975  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
    976  1.1  riastrad  *
    977  1.1  riastrad  */
    978  1.1  riastrad static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
    979  1.1  riastrad {
    980  1.1  riastrad 	const struct vmw_ctx_bindinfo *loc =
    981  1.1  riastrad 		&cbs->vertex_buffers[0].bi;
    982  1.1  riastrad 	struct {
    983  1.1  riastrad 		SVGA3dCmdHeader header;
    984  1.1  riastrad 		SVGA3dCmdDXSetVertexBuffers body;
    985  1.1  riastrad 	} *cmd;
    986  1.1  riastrad 	size_t cmd_size, set_vb_size;
    987  1.1  riastrad 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
    988  1.1  riastrad 
    989  1.1  riastrad 	vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb,
    990  1.1  riastrad 			     SVGA3D_DX_MAX_VERTEXBUFFERS);
    991  1.1  riastrad 	if (cbs->bind_cmd_count == 0)
    992  1.1  riastrad 		return 0;
    993  1.1  riastrad 
    994  1.1  riastrad 	set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer);
    995  1.1  riastrad 	cmd_size = sizeof(*cmd) + set_vb_size;
    996  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
    997  1.3  riastrad 	if (unlikely(cmd == NULL))
    998  1.1  riastrad 		return -ENOMEM;
    999  1.1  riastrad 
   1000  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS;
   1001  1.1  riastrad 	cmd->header.size = sizeof(cmd->body) + set_vb_size;
   1002  1.1  riastrad 	cmd->body.startBuffer = cbs->bind_first_slot;
   1003  1.1  riastrad 
   1004  1.1  riastrad 	memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size);
   1005  1.1  riastrad 
   1006  1.1  riastrad 	vmw_fifo_commit(ctx->dev_priv, cmd_size);
   1007  1.1  riastrad 	bitmap_clear(cbs->dirty_vb,
   1008  1.1  riastrad 		     cbs->bind_first_slot, cbs->bind_cmd_count);
   1009  1.1  riastrad 
   1010  1.1  riastrad 	return 0;
   1011  1.1  riastrad }
   1012  1.1  riastrad 
   1013  1.1  riastrad /**
   1014  1.1  riastrad  * vmw_binding_emit_dirty - Issue delayed binding commands
   1015  1.1  riastrad  *
   1016  1.1  riastrad  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
   1017  1.1  riastrad  *
   1018  1.1  riastrad  * This function issues the delayed binding commands that arise from
   1019  1.1  riastrad  * previous scrub / unscrub calls. These binding commands are typically
   1020  1.1  riastrad  * commands that batch a number of bindings and therefore it makes sense
   1021  1.1  riastrad  * to delay them.
   1022  1.1  riastrad  */
   1023  1.1  riastrad static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs)
   1024  1.1  riastrad {
   1025  1.1  riastrad 	int ret = 0;
   1026  1.1  riastrad 	unsigned long hit = 0;
   1027  1.1  riastrad 
   1028  1.1  riastrad 	while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit))
   1029  1.1  riastrad 	      < VMW_BINDING_NUM_BITS) {
   1030  1.1  riastrad 
   1031  1.1  riastrad 		switch (hit) {
   1032  1.1  riastrad 		case VMW_BINDING_RT_BIT:
   1033  1.1  riastrad 			ret = vmw_emit_set_rt(cbs);
   1034  1.1  riastrad 			break;
   1035  1.1  riastrad 		case VMW_BINDING_PS_BIT:
   1036  1.1  riastrad 			ret = vmw_binding_emit_dirty_ps(cbs);
   1037  1.1  riastrad 			break;
   1038  1.1  riastrad 		case VMW_BINDING_SO_BIT:
   1039  1.1  riastrad 			ret = vmw_emit_set_so(cbs);
   1040  1.1  riastrad 			break;
   1041  1.1  riastrad 		case VMW_BINDING_VB_BIT:
   1042  1.1  riastrad 			ret = vmw_emit_set_vb(cbs);
   1043  1.1  riastrad 			break;
   1044  1.1  riastrad 		default:
   1045  1.1  riastrad 			BUG();
   1046  1.1  riastrad 		}
   1047  1.1  riastrad 		if (ret)
   1048  1.1  riastrad 			return ret;
   1049  1.1  riastrad 
   1050  1.1  riastrad 		__clear_bit(hit, &cbs->dirty);
   1051  1.1  riastrad 		hit++;
   1052  1.1  riastrad 	}
   1053  1.1  riastrad 
   1054  1.1  riastrad 	return 0;
   1055  1.1  riastrad }
   1056  1.1  riastrad 
   1057  1.1  riastrad /**
   1058  1.1  riastrad  * vmw_binding_scrub_sr - Schedule a dx shaderresource binding
   1059  1.1  riastrad  * scrub from a context
   1060  1.1  riastrad  *
   1061  1.1  riastrad  * @bi: single binding information.
   1062  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
   1063  1.1  riastrad  */
   1064  1.1  riastrad static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind)
   1065  1.1  riastrad {
   1066  1.1  riastrad 	struct vmw_ctx_bindinfo_view *biv =
   1067  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_view, bi);
   1068  1.1  riastrad 	struct vmw_ctx_binding_state *cbs =
   1069  1.1  riastrad 		vmw_context_binding_state(bi->ctx);
   1070  1.1  riastrad 
   1071  1.1  riastrad 	__set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr);
   1072  1.1  riastrad 	__set_bit(VMW_BINDING_PS_SR_BIT,
   1073  1.1  riastrad 		  &cbs->per_shader[biv->shader_slot].dirty);
   1074  1.1  riastrad 	__set_bit(VMW_BINDING_PS_BIT, &cbs->dirty);
   1075  1.1  riastrad 
   1076  1.1  riastrad 	return 0;
   1077  1.1  riastrad }
   1078  1.1  riastrad 
   1079  1.1  riastrad /**
   1080  1.1  riastrad  * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding
   1081  1.1  riastrad  * scrub from a context
   1082  1.1  riastrad  *
   1083  1.1  riastrad  * @bi: single binding information.
   1084  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
   1085  1.1  riastrad  */
   1086  1.1  riastrad static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind)
   1087  1.1  riastrad {
   1088  1.1  riastrad 	struct vmw_ctx_binding_state *cbs =
   1089  1.1  riastrad 		vmw_context_binding_state(bi->ctx);
   1090  1.1  riastrad 
   1091  1.1  riastrad 	__set_bit(VMW_BINDING_RT_BIT, &cbs->dirty);
   1092  1.1  riastrad 
   1093  1.1  riastrad 	return 0;
   1094  1.1  riastrad }
   1095  1.1  riastrad 
   1096  1.1  riastrad /**
   1097  1.1  riastrad  * vmw_binding_scrub_so - Schedule a dx streamoutput buffer binding
   1098  1.1  riastrad  * scrub from a context
   1099  1.1  riastrad  *
   1100  1.1  riastrad  * @bi: single binding information.
   1101  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
   1102  1.1  riastrad  */
   1103  1.1  riastrad static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind)
   1104  1.1  riastrad {
   1105  1.1  riastrad 	struct vmw_ctx_binding_state *cbs =
   1106  1.1  riastrad 		vmw_context_binding_state(bi->ctx);
   1107  1.1  riastrad 
   1108  1.1  riastrad 	__set_bit(VMW_BINDING_SO_BIT, &cbs->dirty);
   1109  1.1  riastrad 
   1110  1.1  riastrad 	return 0;
   1111  1.1  riastrad }
   1112  1.1  riastrad 
   1113  1.1  riastrad /**
   1114  1.1  riastrad  * vmw_binding_scrub_vb - Schedule a dx vertex buffer binding
   1115  1.1  riastrad  * scrub from a context
   1116  1.1  riastrad  *
   1117  1.1  riastrad  * @bi: single binding information.
   1118  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
   1119  1.1  riastrad  */
   1120  1.1  riastrad static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind)
   1121  1.1  riastrad {
   1122  1.1  riastrad 	struct vmw_ctx_bindinfo_vb *bivb =
   1123  1.1  riastrad 		container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
   1124  1.1  riastrad 	struct vmw_ctx_binding_state *cbs =
   1125  1.1  riastrad 		vmw_context_binding_state(bi->ctx);
   1126  1.1  riastrad 
   1127  1.1  riastrad 	__set_bit(bivb->slot, cbs->dirty_vb);
   1128  1.1  riastrad 	__set_bit(VMW_BINDING_VB_BIT, &cbs->dirty);
   1129  1.1  riastrad 
   1130  1.1  riastrad 	return 0;
   1131  1.1  riastrad }
   1132  1.1  riastrad 
   1133  1.1  riastrad /**
   1134  1.1  riastrad  * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context
   1135  1.1  riastrad  *
   1136  1.1  riastrad  * @bi: single binding information.
   1137  1.1  riastrad  * @rebind: Whether to issue a bind instead of scrub command.
   1138  1.1  riastrad  */
   1139  1.1  riastrad static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind)
   1140  1.1  riastrad {
   1141  1.1  riastrad 	struct vmw_ctx_bindinfo_ib *binding =
   1142  1.1  riastrad 		container_of(bi, typeof(*binding), bi);
   1143  1.1  riastrad 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
   1144  1.1  riastrad 	struct {
   1145  1.1  riastrad 		SVGA3dCmdHeader header;
   1146  1.1  riastrad 		SVGA3dCmdDXSetIndexBuffer body;
   1147  1.1  riastrad 	} *cmd;
   1148  1.1  riastrad 
   1149  1.3  riastrad 	cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id);
   1150  1.3  riastrad 	if (unlikely(cmd == NULL))
   1151  1.1  riastrad 		return -ENOMEM;
   1152  1.3  riastrad 
   1153  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER;
   1154  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
   1155  1.1  riastrad 	if (rebind) {
   1156  1.1  riastrad 		cmd->body.sid = bi->res->id;
   1157  1.1  riastrad 		cmd->body.format = binding->format;
   1158  1.1  riastrad 		cmd->body.offset = binding->offset;
   1159  1.1  riastrad 	} else {
   1160  1.1  riastrad 		cmd->body.sid = SVGA3D_INVALID_ID;
   1161  1.1  riastrad 		cmd->body.format = 0;
   1162  1.1  riastrad 		cmd->body.offset = 0;
   1163  1.1  riastrad 	}
   1164  1.1  riastrad 
   1165  1.1  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
   1166  1.1  riastrad 
   1167  1.1  riastrad 	return 0;
   1168  1.1  riastrad }
   1169  1.1  riastrad 
   1170  1.1  riastrad /**
   1171  1.1  riastrad  * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with
   1172  1.1  riastrad  * memory accounting.
   1173  1.1  riastrad  *
   1174  1.1  riastrad  * @dev_priv: Pointer to a device private structure.
   1175  1.1  riastrad  *
   1176  1.1  riastrad  * Returns a pointer to a newly allocated struct or an error pointer on error.
   1177  1.1  riastrad  */
   1178  1.1  riastrad struct vmw_ctx_binding_state *
   1179  1.1  riastrad vmw_binding_state_alloc(struct vmw_private *dev_priv)
   1180  1.1  riastrad {
   1181  1.1  riastrad 	struct vmw_ctx_binding_state *cbs;
   1182  1.3  riastrad 	struct ttm_operation_ctx ctx = {
   1183  1.3  riastrad 		.interruptible = false,
   1184  1.3  riastrad 		.no_wait_gpu = false
   1185  1.3  riastrad 	};
   1186  1.1  riastrad 	int ret;
   1187  1.1  riastrad 
   1188  1.1  riastrad 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs),
   1189  1.3  riastrad 				&ctx);
   1190  1.1  riastrad 	if (ret)
   1191  1.1  riastrad 		return ERR_PTR(ret);
   1192  1.1  riastrad 
   1193  1.1  riastrad 	cbs = vzalloc(sizeof(*cbs));
   1194  1.1  riastrad 	if (!cbs) {
   1195  1.1  riastrad 		ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs));
   1196  1.1  riastrad 		return ERR_PTR(-ENOMEM);
   1197  1.1  riastrad 	}
   1198  1.1  riastrad 
   1199  1.1  riastrad 	cbs->dev_priv = dev_priv;
   1200  1.1  riastrad 	INIT_LIST_HEAD(&cbs->list);
   1201  1.1  riastrad 
   1202  1.1  riastrad 	return cbs;
   1203  1.1  riastrad }
   1204  1.1  riastrad 
   1205  1.1  riastrad /**
   1206  1.1  riastrad  * vmw_binding_state_free - Free a struct vmw_ctx_binding_state and its
   1207  1.1  riastrad  * memory accounting info.
   1208  1.1  riastrad  *
   1209  1.1  riastrad  * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed.
   1210  1.1  riastrad  */
   1211  1.1  riastrad void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs)
   1212  1.1  riastrad {
   1213  1.1  riastrad 	struct vmw_private *dev_priv = cbs->dev_priv;
   1214  1.1  riastrad 
   1215  1.1  riastrad 	vfree(cbs);
   1216  1.1  riastrad 	ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs));
   1217  1.1  riastrad }
   1218  1.1  riastrad 
   1219  1.1  riastrad /**
   1220  1.1  riastrad  * vmw_binding_state_list - Get the binding list of a
   1221  1.1  riastrad  * struct vmw_ctx_binding_state
   1222  1.1  riastrad  *
   1223  1.1  riastrad  * @cbs: Pointer to the struct vmw_ctx_binding_state
   1224  1.1  riastrad  *
   1225  1.1  riastrad  * Returns the binding list which can be used to traverse through the bindings
   1226  1.1  riastrad  * and access the resource information of all bindings.
   1227  1.1  riastrad  */
   1228  1.1  riastrad struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs)
   1229  1.1  riastrad {
   1230  1.1  riastrad 	return &cbs->list;
   1231  1.1  riastrad }
   1232  1.1  riastrad 
   1233  1.1  riastrad /**
   1234  1.1  riastrad  * vmwgfx_binding_state_reset - clear a struct vmw_ctx_binding_state
   1235  1.1  riastrad  *
   1236  1.1  riastrad  * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared
   1237  1.1  riastrad  *
   1238  1.1  riastrad  * Drops all bindings registered in @cbs. No device binding actions are
   1239  1.1  riastrad  * performed.
   1240  1.1  riastrad  */
   1241  1.1  riastrad void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs)
   1242  1.1  riastrad {
   1243  1.1  riastrad 	struct vmw_ctx_bindinfo *entry, *next;
   1244  1.1  riastrad 
   1245  1.1  riastrad 	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
   1246  1.1  riastrad 		vmw_binding_drop(entry);
   1247  1.1  riastrad }
   1248  1.1  riastrad 
   1249  1.3  riastrad /**
   1250  1.3  riastrad  * vmw_binding_dirtying - Return whether a binding type is dirtying its resource
   1251  1.3  riastrad  * @binding_type: The binding type
   1252  1.3  riastrad  *
   1253  1.3  riastrad  * Each time a resource is put on the validation list as the result of a
   1254  1.3  riastrad  * context binding referencing it, we need to determine whether that resource
   1255  1.3  riastrad  * will be dirtied (written to by the GPU) as a result of the corresponding
   1256  1.3  riastrad  * GPU operation. Currently rendertarget-, depth-stencil-, and
   1257  1.3  riastrad  * stream-output-target bindings are capable of dirtying its resource.
   1258  1.3  riastrad  *
   1259  1.3  riastrad  * Return: Whether the binding type dirties the resource its binding points to.
   1260  1.3  riastrad  */
   1261  1.3  riastrad u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type)
   1262  1.3  riastrad {
   1263  1.3  riastrad 	static u32 is_binding_dirtying[vmw_ctx_binding_max] = {
   1264  1.3  riastrad 		[vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET,
   1265  1.3  riastrad 		[vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET,
   1266  1.3  riastrad 		[vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET,
   1267  1.3  riastrad 		[vmw_ctx_binding_so] = VMW_RES_DIRTY_SET,
   1268  1.3  riastrad 	};
   1269  1.3  riastrad 
   1270  1.3  riastrad 	/* Review this function as new bindings are added. */
   1271  1.3  riastrad 	BUILD_BUG_ON(vmw_ctx_binding_max != 11);
   1272  1.3  riastrad 	return is_binding_dirtying[binding_type];
   1273  1.3  riastrad }
   1274  1.3  riastrad 
   1275  1.1  riastrad /*
   1276  1.1  riastrad  * This function is unused at run-time, and only used to hold various build
   1277  1.1  riastrad  * asserts important for code optimization assumptions.
   1278  1.1  riastrad  */
   1279  1.1  riastrad static void vmw_binding_build_asserts(void)
   1280  1.1  riastrad {
   1281  1.1  riastrad 	BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3);
   1282  1.1  riastrad 	BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX);
   1283  1.1  riastrad 	BUILD_BUG_ON(sizeof(uint32) != sizeof(u32));
   1284  1.1  riastrad 
   1285  1.1  riastrad 	/*
   1286  1.1  riastrad 	 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various
   1287  1.1  riastrad 	 * view id arrays.
   1288  1.1  riastrad 	 */
   1289  1.1  riastrad 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX);
   1290  1.1  riastrad 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS);
   1291  1.1  riastrad 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS);
   1292  1.1  riastrad 
   1293  1.1  riastrad 	/*
   1294  1.1  riastrad 	 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for
   1295  1.1  riastrad 	 * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers
   1296  1.1  riastrad 	 */
   1297  1.1  riastrad 	BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) >
   1298  1.1  riastrad 		     VMW_MAX_VIEW_BINDINGS*sizeof(u32));
   1299  1.1  riastrad 	BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) >
   1300  1.1  riastrad 		     VMW_MAX_VIEW_BINDINGS*sizeof(u32));
   1301  1.1  riastrad }
   1302