Subversion Repositories Kolibri OS

Rev

Rev 4075 | Rev 5078 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4075 Rev 4569
Line 30... Line 30...
30
#include "ttm/ttm_placement.h"
30
#include "ttm/ttm_placement.h"
Line 31... Line 31...
31
 
31
 
32
struct vmw_user_context {
32
struct vmw_user_context {
33
	struct ttm_base_object base;
33
	struct ttm_base_object base;
-
 
34
	struct vmw_resource res;
34
	struct vmw_resource res;
35
	struct vmw_ctx_binding_state cbs;
Line -... Line 36...
-
 
36
};
-
 
37
 
-
 
38
 
-
 
39
 
35
};
40
typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *);
36
 
41
 
37
static void vmw_user_context_free(struct vmw_resource *res);
42
static void vmw_user_context_free(struct vmw_resource *res);
Line -... Line 43...
-
 
43
static struct vmw_resource *
-
 
44
vmw_user_context_base_to_res(struct ttm_base_object *base);
-
 
45
 
-
 
46
static int vmw_gb_context_create(struct vmw_resource *res);
-
 
47
static int vmw_gb_context_bind(struct vmw_resource *res,
-
 
48
			       struct ttm_validate_buffer *val_buf);
-
 
49
static int vmw_gb_context_unbind(struct vmw_resource *res,
-
 
50
				 bool readback,
-
 
51
				 struct ttm_validate_buffer *val_buf);
-
 
52
static int vmw_gb_context_destroy(struct vmw_resource *res);
-
 
53
static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi);
38
static struct vmw_resource *
54
static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi);
Line 39... Line 55...
39
vmw_user_context_base_to_res(struct ttm_base_object *base);
55
static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi);
40
 
56
static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
41
static uint64_t vmw_user_context_size;
57
static uint64_t vmw_user_context_size;
Line 60... Line 76...
60
	.destroy = NULL,
76
	.destroy = NULL,
61
	.bind = NULL,
77
	.bind = NULL,
62
	.unbind = NULL
78
	.unbind = NULL
63
};
79
};
Line -... Line 80...
-
 
80
 
-
 
81
static const struct vmw_res_func vmw_gb_context_func = {
-
 
82
	.res_type = vmw_res_context,
-
 
83
	.needs_backup = true,
-
 
84
	.may_evict = true,
-
 
85
	.type_name = "guest backed contexts",
-
 
86
	.backup_placement = &vmw_mob_placement,
-
 
87
	.create = vmw_gb_context_create,
-
 
88
	.destroy = vmw_gb_context_destroy,
-
 
89
	.bind = vmw_gb_context_bind,
-
 
90
	.unbind = vmw_gb_context_unbind
-
 
91
};
-
 
92
 
-
 
93
static const vmw_scrub_func vmw_scrub_funcs[vmw_ctx_binding_max] = {
-
 
94
	[vmw_ctx_binding_shader] = vmw_context_scrub_shader,
-
 
95
	[vmw_ctx_binding_rt] = vmw_context_scrub_render_target,
-
 
96
	[vmw_ctx_binding_tex] = vmw_context_scrub_texture };
64
 
97
 
65
/**
98
/**
66
 * Context management:
99
 * Context management:
Line 67... Line 100...
67
 */
100
 */
Line 74... Line 107...
74
		SVGA3dCmdHeader header;
107
		SVGA3dCmdHeader header;
75
		SVGA3dCmdDestroyContext body;
108
		SVGA3dCmdDestroyContext body;
76
	} *cmd;
109
	} *cmd;
Line -... Line 110...
-
 
110
 
-
 
111
 
-
 
112
	if (res->func->destroy == vmw_gb_context_destroy) {
-
 
113
		mutex_lock(&dev_priv->cmdbuf_mutex);
-
 
114
		(void) vmw_gb_context_destroy(res);
-
 
115
		if (dev_priv->pinned_bo != NULL &&
-
 
116
		    !dev_priv->query_cid_valid)
-
 
117
			__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
-
 
118
		mutex_unlock(&dev_priv->cmdbuf_mutex);
-
 
119
		return;
77
 
120
	}
78
 
121
 
79
	vmw_execbuf_release_pinned_bo(dev_priv);
122
	vmw_execbuf_release_pinned_bo(dev_priv);
80
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
123
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
81
	if (unlikely(cmd == NULL)) {
124
	if (unlikely(cmd == NULL)) {
Line 90... Line 133...
90
 
133
 
91
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
134
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
92
	vmw_3d_resource_dec(dev_priv, false);
135
	vmw_3d_resource_dec(dev_priv, false);
Line -... Line 136...
-
 
136
}
-
 
137
 
-
 
138
static int vmw_gb_context_init(struct vmw_private *dev_priv,
-
 
139
			       struct vmw_resource *res,
-
 
140
			       void (*res_free) (struct vmw_resource *res))
-
 
141
{
-
 
142
	int ret;
-
 
143
	struct vmw_user_context *uctx =
-
 
144
		container_of(res, struct vmw_user_context, res);
-
 
145
 
-
 
146
	ret = vmw_resource_init(dev_priv, res, true,
-
 
147
				res_free, &vmw_gb_context_func);
-
 
148
	res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
-
 
149
 
-
 
150
	if (unlikely(ret != 0)) {
-
 
151
		if (res_free)
-
 
152
			res_free(res);
-
 
153
		else
-
 
154
			kfree(res);
-
 
155
		return ret;
-
 
156
	}
-
 
157
 
-
 
158
	memset(&uctx->cbs, 0, sizeof(uctx->cbs));
-
 
159
	INIT_LIST_HEAD(&uctx->cbs.list);
-
 
160
 
-
 
161
	vmw_resource_activate(res, vmw_hw_context_destroy);
-
 
162
	return 0;
93
}
163
}
94
 
164
 
95
static int vmw_context_init(struct vmw_private *dev_priv,
165
static int vmw_context_init(struct vmw_private *dev_priv,
96
			    struct vmw_resource *res,
166
			    struct vmw_resource *res,
97
			    void (*res_free) (struct vmw_resource *res))
167
			    void (*res_free) (struct vmw_resource *res))
Line 101... Line 171...
101
	struct {
171
	struct {
102
		SVGA3dCmdHeader header;
172
		SVGA3dCmdHeader header;
103
		SVGA3dCmdDefineContext body;
173
		SVGA3dCmdDefineContext body;
104
	} *cmd;
174
	} *cmd;
Line -... Line 175...
-
 
175
 
-
 
176
	if (dev_priv->has_mob)
-
 
177
		return vmw_gb_context_init(dev_priv, res, res_free);
105
 
178
 
106
	ret = vmw_resource_init(dev_priv, res, false,
179
	ret = vmw_resource_init(dev_priv, res, false,
Line 107... Line 180...
107
				res_free, &vmw_legacy_context_func);
180
				res_free, &vmw_legacy_context_func);
108
 
181
 
Line 152... Line 225...
152
	ret = vmw_context_init(dev_priv, res, NULL);
225
	ret = vmw_context_init(dev_priv, res, NULL);
Line 153... Line 226...
153
 
226
 
154
	return (ret == 0) ? res : NULL;
227
	return (ret == 0) ? res : NULL;
Line -... Line 228...
-
 
228
}
-
 
229
 
-
 
230
 
-
 
231
static int vmw_gb_context_create(struct vmw_resource *res)
-
 
232
{
-
 
233
	struct vmw_private *dev_priv = res->dev_priv;
-
 
234
	int ret;
-
 
235
	struct {
-
 
236
		SVGA3dCmdHeader header;
-
 
237
		SVGA3dCmdDefineGBContext body;
-
 
238
	} *cmd;
-
 
239
 
-
 
240
	if (likely(res->id != -1))
-
 
241
		return 0;
-
 
242
 
-
 
243
	ret = vmw_resource_alloc_id(res);
-
 
244
	if (unlikely(ret != 0)) {
-
 
245
		DRM_ERROR("Failed to allocate a context id.\n");
-
 
246
		goto out_no_id;
-
 
247
	}
-
 
248
 
-
 
249
	if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
-
 
250
		ret = -EBUSY;
-
 
251
		goto out_no_fifo;
-
 
252
	}
-
 
253
 
-
 
254
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
255
	if (unlikely(cmd == NULL)) {
-
 
256
		DRM_ERROR("Failed reserving FIFO space for context "
-
 
257
			  "creation.\n");
-
 
258
		ret = -ENOMEM;
-
 
259
		goto out_no_fifo;
-
 
260
	}
-
 
261
 
-
 
262
	cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
-
 
263
	cmd->header.size = sizeof(cmd->body);
-
 
264
	cmd->body.cid = res->id;
-
 
265
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
266
	(void) vmw_3d_resource_inc(dev_priv, false);
-
 
267
 
-
 
268
	return 0;
-
 
269
 
-
 
270
out_no_fifo:
-
 
271
	vmw_resource_release_id(res);
-
 
272
out_no_id:
-
 
273
	return ret;
-
 
274
}
-
 
275
 
-
 
276
static int vmw_gb_context_bind(struct vmw_resource *res,
-
 
277
			       struct ttm_validate_buffer *val_buf)
-
 
278
{
-
 
279
	struct vmw_private *dev_priv = res->dev_priv;
-
 
280
	struct {
-
 
281
		SVGA3dCmdHeader header;
-
 
282
		SVGA3dCmdBindGBContext body;
-
 
283
	} *cmd;
-
 
284
	struct ttm_buffer_object *bo = val_buf->bo;
-
 
285
 
-
 
286
	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
-
 
287
 
-
 
288
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
289
	if (unlikely(cmd == NULL)) {
-
 
290
		DRM_ERROR("Failed reserving FIFO space for context "
-
 
291
			  "binding.\n");
-
 
292
		return -ENOMEM;
-
 
293
	}
-
 
294
 
-
 
295
	cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
-
 
296
	cmd->header.size = sizeof(cmd->body);
-
 
297
	cmd->body.cid = res->id;
-
 
298
	cmd->body.mobid = bo->mem.start;
-
 
299
	cmd->body.validContents = res->backup_dirty;
-
 
300
	res->backup_dirty = false;
-
 
301
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
302
 
-
 
303
	return 0;
-
 
304
}
-
 
305
 
-
 
306
static int vmw_gb_context_unbind(struct vmw_resource *res,
-
 
307
				 bool readback,
-
 
308
				 struct ttm_validate_buffer *val_buf)
-
 
309
{
-
 
310
	struct vmw_private *dev_priv = res->dev_priv;
-
 
311
	struct ttm_buffer_object *bo = val_buf->bo;
-
 
312
	struct vmw_fence_obj *fence;
-
 
313
	struct vmw_user_context *uctx =
-
 
314
		container_of(res, struct vmw_user_context, res);
-
 
315
 
-
 
316
	struct {
-
 
317
		SVGA3dCmdHeader header;
-
 
318
		SVGA3dCmdReadbackGBContext body;
-
 
319
	} *cmd1;
-
 
320
	struct {
-
 
321
		SVGA3dCmdHeader header;
-
 
322
		SVGA3dCmdBindGBContext body;
-
 
323
	} *cmd2;
-
 
324
	uint32_t submit_size;
-
 
325
	uint8_t *cmd;
-
 
326
 
-
 
327
 
-
 
328
	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
-
 
329
 
-
 
330
	mutex_lock(&dev_priv->binding_mutex);
-
 
331
	vmw_context_binding_state_kill(&uctx->cbs);
-
 
332
 
-
 
333
	submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
-
 
334
 
-
 
335
	cmd = vmw_fifo_reserve(dev_priv, submit_size);
-
 
336
	if (unlikely(cmd == NULL)) {
-
 
337
		DRM_ERROR("Failed reserving FIFO space for context "
-
 
338
			  "unbinding.\n");
-
 
339
		mutex_unlock(&dev_priv->binding_mutex);
-
 
340
		return -ENOMEM;
-
 
341
	}
-
 
342
 
-
 
343
	cmd2 = (void *) cmd;
-
 
344
	if (readback) {
-
 
345
		cmd1 = (void *) cmd;
-
 
346
		cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
-
 
347
		cmd1->header.size = sizeof(cmd1->body);
-
 
348
		cmd1->body.cid = res->id;
-
 
349
		cmd2 = (void *) (&cmd1[1]);
-
 
350
	}
-
 
351
	cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
-
 
352
	cmd2->header.size = sizeof(cmd2->body);
-
 
353
	cmd2->body.cid = res->id;
-
 
354
	cmd2->body.mobid = SVGA3D_INVALID_ID;
-
 
355
 
-
 
356
	vmw_fifo_commit(dev_priv, submit_size);
-
 
357
	mutex_unlock(&dev_priv->binding_mutex);
-
 
358
 
-
 
359
	/*
-
 
360
	 * Create a fence object and fence the backup buffer.
-
 
361
	 */
-
 
362
 
-
 
363
	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
-
 
364
					  &fence, NULL);
-
 
365
 
-
 
366
	vmw_fence_single_bo(bo, fence);
-
 
367
 
-
 
368
	if (likely(fence != NULL))
-
 
369
		vmw_fence_obj_unreference(&fence);
-
 
370
 
-
 
371
	return 0;
-
 
372
}
-
 
373
 
-
 
374
static int vmw_gb_context_destroy(struct vmw_resource *res)
-
 
375
{
-
 
376
	struct vmw_private *dev_priv = res->dev_priv;
-
 
377
	struct {
-
 
378
		SVGA3dCmdHeader header;
-
 
379
		SVGA3dCmdDestroyGBContext body;
-
 
380
	} *cmd;
-
 
381
	struct vmw_user_context *uctx =
-
 
382
		container_of(res, struct vmw_user_context, res);
-
 
383
 
-
 
384
	BUG_ON(!list_empty(&uctx->cbs.list));
-
 
385
 
-
 
386
	if (likely(res->id == -1))
-
 
387
		return 0;
-
 
388
 
-
 
389
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
390
	if (unlikely(cmd == NULL)) {
-
 
391
		DRM_ERROR("Failed reserving FIFO space for context "
-
 
392
			  "destruction.\n");
-
 
393
		return -ENOMEM;
-
 
394
	}
-
 
395
 
-
 
396
	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
-
 
397
	cmd->header.size = sizeof(cmd->body);
-
 
398
	cmd->body.cid = res->id;
-
 
399
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
400
	if (dev_priv->query_cid == res->id)
-
 
401
		dev_priv->query_cid_valid = false;
-
 
402
	vmw_resource_release_id(res);
-
 
403
	vmw_3d_resource_dec(dev_priv, false);
-
 
404
 
-
 
405
	return 0;
155
}
406
}
156
 
407
 
157
/**
408
/**
Line 158... Line 409...
158
 * User-space context management:
409
 * User-space context management:
Line 272... Line 523...
272
	ttm_read_unlock(&vmaster->lock);
523
	ttm_read_unlock(&vmaster->lock);
273
	return ret;
524
	return ret;
Line 274... Line 525...
274
 
525
 
275
}
526
}
-
 
527
#endif
-
 
528
 
-
 
529
/**
-
 
530
 * vmw_context_scrub_shader - scrub a shader binding from a context.
-
 
531
 *
-
 
532
 * @bi: single binding information.
-
 
533
 */
-
 
534
static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
-
 
535
{
-
 
536
	struct vmw_private *dev_priv = bi->ctx->dev_priv;
-
 
537
	struct {
-
 
538
		SVGA3dCmdHeader header;
-
 
539
		SVGA3dCmdSetShader body;
-
 
540
	} *cmd;
-
 
541
 
-
 
542
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
543
	if (unlikely(cmd == NULL)) {
-
 
544
		DRM_ERROR("Failed reserving FIFO space for shader "
-
 
545
			  "unbinding.\n");
-
 
546
		return -ENOMEM;
-
 
547
	}
-
 
548
 
-
 
549
	cmd->header.id = SVGA_3D_CMD_SET_SHADER;
-
 
550
	cmd->header.size = sizeof(cmd->body);
-
 
551
	cmd->body.cid = bi->ctx->id;
-
 
552
	cmd->body.type = bi->i1.shader_type;
-
 
553
	cmd->body.shid = SVGA3D_INVALID_ID;
-
 
554
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
555
 
-
 
556
	return 0;
-
 
557
}
-
 
558
 
-
 
559
/**
-
 
560
 * vmw_context_scrub_render_target - scrub a render target binding
-
 
561
 * from a context.
-
 
562
 *
-
 
563
 * @bi: single binding information.
-
 
564
 */
-
 
565
static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
-
 
566
{
-
 
567
	struct vmw_private *dev_priv = bi->ctx->dev_priv;
-
 
568
	struct {
-
 
569
		SVGA3dCmdHeader header;
-
 
570
		SVGA3dCmdSetRenderTarget body;
-
 
571
	} *cmd;
-
 
572
 
-
 
573
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
574
	if (unlikely(cmd == NULL)) {
-
 
575
		DRM_ERROR("Failed reserving FIFO space for render target "
-
 
576
			  "unbinding.\n");
-
 
577
		return -ENOMEM;
-
 
578
	}
-
 
579
 
-
 
580
	cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
-
 
581
	cmd->header.size = sizeof(cmd->body);
-
 
582
	cmd->body.cid = bi->ctx->id;
-
 
583
	cmd->body.type = bi->i1.rt_type;
-
 
584
	cmd->body.target.sid = SVGA3D_INVALID_ID;
-
 
585
	cmd->body.target.face = 0;
-
 
586
	cmd->body.target.mipmap = 0;
-
 
587
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
588
 
-
 
589
	return 0;
-
 
590
}
-
 
591
 
-
 
592
/**
-
 
593
 * vmw_context_scrub_texture - scrub a texture binding from a context.
-
 
594
 *
-
 
595
 * @bi: single binding information.
-
 
596
 *
-
 
597
 * TODO: Possibly complement this function with a function that takes
-
 
598
 * a list of texture bindings and combines them to a single command.
-
 
599
 */
-
 
600
static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
-
 
601
{
-
 
602
	struct vmw_private *dev_priv = bi->ctx->dev_priv;
-
 
603
	struct {
-
 
604
		SVGA3dCmdHeader header;
-
 
605
		struct {
-
 
606
			SVGA3dCmdSetTextureState c;
-
 
607
			SVGA3dTextureState s1;
-
 
608
		} body;
-
 
609
	} *cmd;
-
 
610
 
-
 
611
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-
 
612
	if (unlikely(cmd == NULL)) {
-
 
613
		DRM_ERROR("Failed reserving FIFO space for texture "
-
 
614
			  "unbinding.\n");
-
 
615
		return -ENOMEM;
-
 
616
	}
-
 
617
 
-
 
618
 
-
 
619
	cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
-
 
620
	cmd->header.size = sizeof(cmd->body);
-
 
621
	cmd->body.c.cid = bi->ctx->id;
-
 
622
	cmd->body.s1.stage = bi->i1.texture_stage;
-
 
623
	cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
-
 
624
	cmd->body.s1.value = (uint32) SVGA3D_INVALID_ID;
-
 
625
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-
 
626
 
-
 
627
	return 0;
-
 
628
}
-
 
629
 
-
 
630
/**
-
 
631
 * vmw_context_binding_drop: Stop tracking a context binding
-
 
632
 *
-
 
633
 * @cb: Pointer to binding tracker storage.
-
 
634
 *
-
 
635
 * Stops tracking a context binding, and re-initializes its storage.
-
 
636
 * Typically used when the context binding is replaced with a binding to
-
 
637
 * another (or the same, for that matter) resource.
-
 
638
 */
-
 
639
static void vmw_context_binding_drop(struct vmw_ctx_binding *cb)
-
 
640
{
-
 
641
	list_del(&cb->ctx_list);
-
 
642
	if (!list_empty(&cb->res_list))
-
 
643
		list_del(&cb->res_list);
-
 
644
	cb->bi.ctx = NULL;
-
 
645
}
-
 
646
 
-
 
647
/**
-
 
648
 * vmw_context_binding_add: Start tracking a context binding
-
 
649
 *
-
 
650
 * @cbs: Pointer to the context binding state tracker.
-
 
651
 * @bi: Information about the binding to track.
-
 
652
 *
-
 
653
 * Performs basic checks on the binding to make sure arguments are within
-
 
654
 * bounds and then starts tracking the binding in the context binding
-
 
655
 * state structure @cbs.
-
 
656
 */
-
 
657
int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
-
 
658
			    const struct vmw_ctx_bindinfo *bi)
-
 
659
{
-
 
660
	struct vmw_ctx_binding *loc;
-
 
661
 
-
 
662
	switch (bi->bt) {
-
 
663
	case vmw_ctx_binding_rt:
-
 
664
		if (unlikely((unsigned)bi->i1.rt_type >= SVGA3D_RT_MAX)) {
-
 
665
			DRM_ERROR("Illegal render target type %u.\n",
-
 
666
				  (unsigned) bi->i1.rt_type);
-
 
667
			return -EINVAL;
-
 
668
		}
-
 
669
		loc = &cbs->render_targets[bi->i1.rt_type];
-
 
670
		break;
-
 
671
	case vmw_ctx_binding_tex:
-
 
672
		if (unlikely((unsigned)bi->i1.texture_stage >=
-
 
673
			     SVGA3D_NUM_TEXTURE_UNITS)) {
-
 
674
			DRM_ERROR("Illegal texture/sampler unit %u.\n",
-
 
675
				  (unsigned) bi->i1.texture_stage);
-
 
676
			return -EINVAL;
-
 
677
		}
-
 
678
		loc = &cbs->texture_units[bi->i1.texture_stage];
-
 
679
		break;
-
 
680
	case vmw_ctx_binding_shader:
-
 
681
		if (unlikely((unsigned)bi->i1.shader_type >=
-
 
682
			     SVGA3D_SHADERTYPE_MAX)) {
-
 
683
			DRM_ERROR("Illegal shader type %u.\n",
-
 
684
				  (unsigned) bi->i1.shader_type);
-
 
685
			return -EINVAL;
-
 
686
		}
-
 
687
		loc = &cbs->shaders[bi->i1.shader_type];
-
 
688
		break;
-
 
689
	default:
-
 
690
		BUG();
-
 
691
	}
-
 
692
 
-
 
693
	if (loc->bi.ctx != NULL)
-
 
694
		vmw_context_binding_drop(loc);
-
 
695
 
-
 
696
	loc->bi = *bi;
-
 
697
	list_add_tail(&loc->ctx_list, &cbs->list);
-
 
698
	INIT_LIST_HEAD(&loc->res_list);
-
 
699
 
-
 
700
	return 0;
-
 
701
}
-
 
702
 
-
 
703
/**
-
 
704
 * vmw_context_binding_transfer: Transfer a context binding tracking entry.
-
 
705
 *
-
 
706
 * @cbs: Pointer to the persistent context binding state tracker.
-
 
707
 * @bi: Information about the binding to track.
-
 
708
 *
-
 
709
 */
-
 
710
static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
-
 
711
					 const struct vmw_ctx_bindinfo *bi)
-
 
712
{
-
 
713
	struct vmw_ctx_binding *loc;
-
 
714
 
-
 
715
	switch (bi->bt) {
-
 
716
	case vmw_ctx_binding_rt:
-
 
717
		loc = &cbs->render_targets[bi->i1.rt_type];
-
 
718
		break;
-
 
719
	case vmw_ctx_binding_tex:
-
 
720
		loc = &cbs->texture_units[bi->i1.texture_stage];
-
 
721
		break;
-
 
722
	case vmw_ctx_binding_shader:
-
 
723
		loc = &cbs->shaders[bi->i1.shader_type];
-
 
724
		break;
-
 
725
	default:
-
 
726
		BUG();
-
 
727
	}
-
 
728
 
-
 
729
	if (loc->bi.ctx != NULL)
-
 
730
		vmw_context_binding_drop(loc);
-
 
731
 
-
 
732
	loc->bi = *bi;
-
 
733
	list_add_tail(&loc->ctx_list, &cbs->list);
-
 
734
	if (bi->res != NULL)
-
 
735
		list_add_tail(&loc->res_list, &bi->res->binding_head);
-
 
736
	else
-
 
737
		INIT_LIST_HEAD(&loc->res_list);
-
 
738
}
-
 
739
 
-
 
740
/**
-
 
741
 * vmw_context_binding_kill - Kill a binding on the device
-
 
742
 * and stop tracking it.
-
 
743
 *
-
 
744
 * @cb: Pointer to binding tracker storage.
-
 
745
 *
-
 
746
 * Emits FIFO commands to scrub a binding represented by @cb.
-
 
747
 * Then stops tracking the binding and re-initializes its storage.
-
 
748
 */
-
 
749
static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
-
 
750
{
-
 
751
	(void) vmw_scrub_funcs[cb->bi.bt](&cb->bi);
-
 
752
	vmw_context_binding_drop(cb);
-
 
753
}
-
 
754
 
-
 
755
/**
-
 
756
 * vmw_context_binding_state_kill - Kill all bindings associated with a
-
 
757
 * struct vmw_ctx_binding state structure, and re-initialize the structure.
-
 
758
 *
-
 
759
 * @cbs: Pointer to the context binding state tracker.
-
 
760
 *
-
 
761
 * Emits commands to scrub all bindings associated with the
-
 
762
 * context binding state tracker. Then re-initializes the whole structure.
-
 
763
 */
-
 
764
static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
-
 
765
{
-
 
766
	struct vmw_ctx_binding *entry, *next;
-
 
767
 
-
 
768
	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
-
 
769
		vmw_context_binding_kill(entry);
-
 
770
}
-
 
771
 
-
 
772
/**
-
 
773
 * vmw_context_binding_res_list_kill - Kill all bindings on a
-
 
774
 * resource binding list
-
 
775
 *
-
 
776
 * @head: list head of resource binding list
-
 
777
 *
-
 
778
 * Kills all bindings associated with a specific resource. Typically
-
 
779
 * called before the resource is destroyed.
-
 
780
 */
-
 
781
void vmw_context_binding_res_list_kill(struct list_head *head)
-
 
782
{
-
 
783
	struct vmw_ctx_binding *entry, *next;
-
 
784
 
-
 
785
	list_for_each_entry_safe(entry, next, head, res_list)
-
 
786
		vmw_context_binding_kill(entry);
-
 
787
}
-
 
788
 
-
 
789
/**
-
 
790
 * vmw_context_binding_state_transfer - Commit staged binding info
-
 
791
 *
-
 
792
 * @ctx: Pointer to context to commit the staged binding info to.
-
 
793
 * @from: Staged binding info built during execbuf.
-
 
794
 *
-
 
795
 * Transfers binding info from a temporary structure to the persistent
-
 
796
 * structure in the context. This can be done once commands
-
 
797
 */
-
 
798
void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
-
 
799
					struct vmw_ctx_binding_state *from)
-
 
800
{
-
 
801
	struct vmw_user_context *uctx =
-
 
802
		container_of(ctx, struct vmw_user_context, res);
-
 
803
	struct vmw_ctx_binding *entry, *next;
-
 
804
 
-
 
805
	list_for_each_entry_safe(entry, next, &from->list, ctx_list)
-
 
806
		vmw_context_binding_transfer(&uctx->cbs, &entry->bi);