root/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vmw_cbs_context
  2. vmw_binding_loc
  3. vmw_binding_drop
  4. vmw_binding_add
  5. vmw_binding_transfer
  6. vmw_binding_state_kill
  7. vmw_binding_state_scrub
  8. vmw_binding_res_list_kill
  9. vmw_binding_res_list_scrub
  10. vmw_binding_state_commit
  11. vmw_binding_rebind_all
  12. vmw_binding_scrub_shader
  13. vmw_binding_scrub_render_target
  14. vmw_binding_scrub_texture
  15. vmw_binding_scrub_dx_shader
  16. vmw_binding_scrub_cb
  17. vmw_collect_view_ids
  18. vmw_collect_dirty_view_ids
  19. vmw_emit_set_sr
  20. vmw_emit_set_rt
  21. vmw_collect_so_targets
  22. vmw_emit_set_so
  23. vmw_binding_emit_dirty_ps
  24. vmw_collect_dirty_vbs
  25. vmw_emit_set_vb
  26. vmw_binding_emit_dirty
  27. vmw_binding_scrub_sr
  28. vmw_binding_scrub_dx_rt
  29. vmw_binding_scrub_so
  30. vmw_binding_scrub_vb
  31. vmw_binding_scrub_ib
  32. vmw_binding_state_alloc
  33. vmw_binding_state_free
  34. vmw_binding_state_list
  35. vmw_binding_state_reset
  36. vmw_binding_dirtying
  37. vmw_binding_build_asserts

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

/* [<][>][^][v][top][bottom][index][help] */