0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include "vmwgfx_drv.h"
0028 #include "vmwgfx_resource_priv.h"
0029 #include "vmwgfx_so.h"
0030 #include "vmwgfx_binding.h"
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 struct vmw_view {
0062 struct rcu_head rcu;
0063 struct vmw_resource res;
0064 struct vmw_resource *ctx;
0065 struct vmw_resource *srf;
0066 struct vmw_resource *cotable;
0067 struct list_head srf_head;
0068 struct list_head cotable_head;
0069 unsigned view_type;
0070 unsigned view_id;
0071 u32 cmd_size;
0072 bool committed;
0073 u32 cmd[1];
0074 };
0075
0076 static int vmw_view_create(struct vmw_resource *res);
0077 static int vmw_view_destroy(struct vmw_resource *res);
0078 static void vmw_hw_view_destroy(struct vmw_resource *res);
0079 static void vmw_view_commit_notify(struct vmw_resource *res,
0080 enum vmw_cmdbuf_res_state state);
0081
0082 static const struct vmw_res_func vmw_view_func = {
0083 .res_type = vmw_res_view,
0084 .needs_backup = false,
0085 .may_evict = false,
0086 .type_name = "DX view",
0087 .backup_placement = NULL,
0088 .create = vmw_view_create,
0089 .commit_notify = vmw_view_commit_notify,
0090 };
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 struct vmw_view_define {
0102 uint32 view_id;
0103 uint32 sid;
0104 };
0105
0106
0107
0108
0109
0110
0111
0112
0113 static struct vmw_view *vmw_view(struct vmw_resource *res)
0114 {
0115 return container_of(res, struct vmw_view, res);
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 static void vmw_view_commit_notify(struct vmw_resource *res,
0127 enum vmw_cmdbuf_res_state state)
0128 {
0129 struct vmw_view *view = vmw_view(res);
0130 struct vmw_private *dev_priv = res->dev_priv;
0131
0132 mutex_lock(&dev_priv->binding_mutex);
0133 if (state == VMW_CMDBUF_RES_ADD) {
0134 struct vmw_surface *srf = vmw_res_to_srf(view->srf);
0135
0136 list_add_tail(&view->srf_head, &srf->view_list);
0137 vmw_cotable_add_resource(view->cotable, &view->cotable_head);
0138 view->committed = true;
0139 res->id = view->view_id;
0140
0141 } else {
0142 list_del_init(&view->cotable_head);
0143 list_del_init(&view->srf_head);
0144 view->committed = false;
0145 res->id = -1;
0146 }
0147 mutex_unlock(&dev_priv->binding_mutex);
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static int vmw_view_create(struct vmw_resource *res)
0159 {
0160 struct vmw_view *view = vmw_view(res);
0161 struct vmw_surface *srf = vmw_res_to_srf(view->srf);
0162 struct vmw_private *dev_priv = res->dev_priv;
0163 struct {
0164 SVGA3dCmdHeader header;
0165 struct vmw_view_define body;
0166 } *cmd;
0167
0168 mutex_lock(&dev_priv->binding_mutex);
0169 if (!view->committed) {
0170 mutex_unlock(&dev_priv->binding_mutex);
0171 return 0;
0172 }
0173
0174 cmd = VMW_CMD_CTX_RESERVE(res->dev_priv, view->cmd_size, view->ctx->id);
0175 if (!cmd) {
0176 mutex_unlock(&dev_priv->binding_mutex);
0177 return -ENOMEM;
0178 }
0179
0180 memcpy(cmd, &view->cmd, view->cmd_size);
0181 WARN_ON(cmd->body.view_id != view->view_id);
0182
0183 WARN_ON(view->srf->id == SVGA3D_INVALID_ID);
0184 cmd->body.sid = view->srf->id;
0185 vmw_cmd_commit(res->dev_priv, view->cmd_size);
0186 res->id = view->view_id;
0187 list_add_tail(&view->srf_head, &srf->view_list);
0188 vmw_cotable_add_resource(view->cotable, &view->cotable_head);
0189 mutex_unlock(&dev_priv->binding_mutex);
0190
0191 return 0;
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 static int vmw_view_destroy(struct vmw_resource *res)
0203 {
0204 struct vmw_private *dev_priv = res->dev_priv;
0205 struct vmw_view *view = vmw_view(res);
0206 struct {
0207 SVGA3dCmdHeader header;
0208 union vmw_view_destroy body;
0209 } *cmd;
0210
0211 lockdep_assert_held_once(&dev_priv->binding_mutex);
0212 vmw_binding_res_list_scrub(&res->binding_head);
0213
0214 if (!view->committed || res->id == -1)
0215 return 0;
0216
0217 cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), view->ctx->id);
0218 if (!cmd)
0219 return -ENOMEM;
0220
0221 cmd->header.id = vmw_view_destroy_cmds[view->view_type];
0222 cmd->header.size = sizeof(cmd->body);
0223 cmd->body.view_id = view->view_id;
0224 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0225 res->id = -1;
0226 list_del_init(&view->cotable_head);
0227 list_del_init(&view->srf_head);
0228
0229 return 0;
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239 static void vmw_hw_view_destroy(struct vmw_resource *res)
0240 {
0241 struct vmw_private *dev_priv = res->dev_priv;
0242
0243 mutex_lock(&dev_priv->binding_mutex);
0244 WARN_ON(vmw_view_destroy(res));
0245 res->id = -1;
0246 mutex_unlock(&dev_priv->binding_mutex);
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 static u32 vmw_view_key(u32 user_key, enum vmw_view_type view_type)
0258 {
0259 return user_key | (view_type << 20);
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 static bool vmw_view_id_ok(u32 user_key, enum vmw_view_type view_type)
0272 {
0273 return (user_key < SVGA_COTABLE_MAX_IDS &&
0274 view_type < vmw_view_max);
0275 }
0276
0277
0278
0279
0280
0281
0282
0283
0284 static void vmw_view_res_free(struct vmw_resource *res)
0285 {
0286 struct vmw_view *view = vmw_view(res);
0287
0288 vmw_resource_unreference(&view->cotable);
0289 vmw_resource_unreference(&view->srf);
0290 kfree_rcu(view, rcu);
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 int vmw_view_add(struct vmw_cmdbuf_res_manager *man,
0309 struct vmw_resource *ctx,
0310 struct vmw_resource *srf,
0311 enum vmw_view_type view_type,
0312 u32 user_key,
0313 const void *cmd,
0314 size_t cmd_size,
0315 struct list_head *list)
0316 {
0317 static const size_t vmw_view_define_sizes[] = {
0318 [vmw_view_sr] = sizeof(SVGA3dCmdDXDefineShaderResourceView),
0319 [vmw_view_rt] = sizeof(SVGA3dCmdDXDefineRenderTargetView),
0320 [vmw_view_ds] = sizeof(SVGA3dCmdDXDefineDepthStencilView),
0321 [vmw_view_ua] = sizeof(SVGA3dCmdDXDefineUAView)
0322 };
0323
0324 struct vmw_private *dev_priv = ctx->dev_priv;
0325 struct vmw_resource *res;
0326 struct vmw_view *view;
0327 size_t size;
0328 int ret;
0329
0330 if (cmd_size != vmw_view_define_sizes[view_type] +
0331 sizeof(SVGA3dCmdHeader)) {
0332 VMW_DEBUG_USER("Illegal view create command size.\n");
0333 return -EINVAL;
0334 }
0335
0336 if (!vmw_view_id_ok(user_key, view_type)) {
0337 VMW_DEBUG_USER("Illegal view add view id.\n");
0338 return -EINVAL;
0339 }
0340
0341 size = offsetof(struct vmw_view, cmd) + cmd_size;
0342
0343 view = kmalloc(size, GFP_KERNEL);
0344 if (!view) {
0345 return -ENOMEM;
0346 }
0347
0348 res = &view->res;
0349 view->ctx = ctx;
0350 view->srf = vmw_resource_reference(srf);
0351 view->cotable = vmw_resource_reference
0352 (vmw_context_cotable(ctx, vmw_view_cotables[view_type]));
0353 view->view_type = view_type;
0354 view->view_id = user_key;
0355 view->cmd_size = cmd_size;
0356 view->committed = false;
0357 INIT_LIST_HEAD(&view->srf_head);
0358 INIT_LIST_HEAD(&view->cotable_head);
0359 memcpy(&view->cmd, cmd, cmd_size);
0360 ret = vmw_resource_init(dev_priv, res, true,
0361 vmw_view_res_free, &vmw_view_func);
0362 if (ret)
0363 goto out_resource_init;
0364
0365 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_view,
0366 vmw_view_key(user_key, view_type),
0367 res, list);
0368 if (ret)
0369 goto out_resource_init;
0370
0371 res->id = view->view_id;
0372 res->hw_destroy = vmw_hw_view_destroy;
0373
0374 out_resource_init:
0375 vmw_resource_unreference(&res);
0376
0377 return ret;
0378 }
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392 int vmw_view_remove(struct vmw_cmdbuf_res_manager *man,
0393 u32 user_key, enum vmw_view_type view_type,
0394 struct list_head *list,
0395 struct vmw_resource **res_p)
0396 {
0397 if (!vmw_view_id_ok(user_key, view_type)) {
0398 VMW_DEBUG_USER("Illegal view remove view id.\n");
0399 return -EINVAL;
0400 }
0401
0402 return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_view,
0403 vmw_view_key(user_key, view_type),
0404 list, res_p);
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419 void vmw_view_cotable_list_destroy(struct vmw_private *dev_priv,
0420 struct list_head *list,
0421 bool readback)
0422 {
0423 struct vmw_view *entry, *next;
0424
0425 lockdep_assert_held_once(&dev_priv->binding_mutex);
0426
0427 list_for_each_entry_safe(entry, next, list, cotable_head)
0428 WARN_ON(vmw_view_destroy(&entry->res));
0429 }
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 void vmw_view_surface_list_destroy(struct vmw_private *dev_priv,
0441 struct list_head *list)
0442 {
0443 struct vmw_view *entry, *next;
0444
0445 lockdep_assert_held_once(&dev_priv->binding_mutex);
0446
0447 list_for_each_entry_safe(entry, next, list, srf_head)
0448 WARN_ON(vmw_view_destroy(&entry->res));
0449 }
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460 struct vmw_resource *vmw_view_srf(struct vmw_resource *res)
0461 {
0462 return vmw_view(res)->srf;
0463 }
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 struct vmw_resource *vmw_view_lookup(struct vmw_cmdbuf_res_manager *man,
0475 enum vmw_view_type view_type,
0476 u32 user_key)
0477 {
0478 return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_view,
0479 vmw_view_key(user_key, view_type));
0480 }
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 u32 vmw_view_dirtying(struct vmw_resource *res)
0495 {
0496 static u32 view_is_dirtying[vmw_view_max] = {
0497 [vmw_view_rt] = VMW_RES_DIRTY_SET,
0498 [vmw_view_ds] = VMW_RES_DIRTY_SET,
0499 [vmw_view_ua] = VMW_RES_DIRTY_SET,
0500 };
0501
0502
0503 BUILD_BUG_ON(vmw_view_max != 4);
0504 return view_is_dirtying[vmw_view(res)->view_type];
0505 }
0506
0507 const u32 vmw_view_destroy_cmds[] = {
0508 [vmw_view_sr] = SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW,
0509 [vmw_view_rt] = SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW,
0510 [vmw_view_ds] = SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW,
0511 [vmw_view_ua] = SVGA_3D_CMD_DX_DESTROY_UA_VIEW,
0512 };
0513
0514 const SVGACOTableType vmw_view_cotables[] = {
0515 [vmw_view_sr] = SVGA_COTABLE_SRVIEW,
0516 [vmw_view_rt] = SVGA_COTABLE_RTVIEW,
0517 [vmw_view_ds] = SVGA_COTABLE_DSVIEW,
0518 [vmw_view_ua] = SVGA_COTABLE_UAVIEW,
0519 };
0520
0521 const SVGACOTableType vmw_so_cotables[] = {
0522 [vmw_so_el] = SVGA_COTABLE_ELEMENTLAYOUT,
0523 [vmw_so_bs] = SVGA_COTABLE_BLENDSTATE,
0524 [vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL,
0525 [vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE,
0526 [vmw_so_ss] = SVGA_COTABLE_SAMPLER,
0527 [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT,
0528 [vmw_so_max]= SVGA_COTABLE_MAX
0529 };
0530
0531
0532
0533 static void vmw_so_build_asserts(void) __attribute__((used));
0534
0535
0536
0537
0538
0539
0540 static void vmw_so_build_asserts(void)
0541 {
0542
0543 BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW !=
0544 SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 1);
0545 BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW !=
0546 SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 2);
0547 BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW !=
0548 SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 3);
0549 BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW !=
0550 SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 4);
0551 BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW !=
0552 SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 5);
0553
0554
0555 BUILD_BUG_ON(sizeof(union vmw_view_destroy) != sizeof(u32));
0556
0557
0558 BUILD_BUG_ON(SVGA_COTABLE_MAX_IDS >= ((1 << 20) - 1));
0559
0560
0561
0562
0563
0564 BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
0565 offsetof(SVGA3dCmdDXDefineShaderResourceView, sid));
0566 BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
0567 offsetof(SVGA3dCmdDXDefineRenderTargetView, sid));
0568 BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
0569 offsetof(SVGA3dCmdDXDefineDepthStencilView, sid));
0570 BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
0571 offsetof(SVGA3dCmdDXDefineUAView, sid));
0572 BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
0573 offsetof(SVGA3dCmdDXDefineDepthStencilView_v2, sid));
0574 }