summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/dri/nouveau/nouveau_winsys.c
blob: 2ca05d84c6066b55b87be8c8208b2b6db73dccc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "pipe/p_util.h"

#include "nouveau_context.h"
#include "nouveau_winsys_pipe.h"

#include "nouveau/nouveau_winsys.h"

static int
nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count,
			    struct nouveau_notifier **notify)
{
	struct nouveau_context *nv = nvws->nv;

	return nouveau_notifier_alloc(nv->channel, nv->next_handle++,
				      count, notify);
}

static int
nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
			 struct nouveau_grobj **grobj)
{
	struct nouveau_context *nv = nvws->nv;
	int ret;

	ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++,
				  grclass, grobj);
	if (ret)
		return ret;

	(*grobj)->subc = nv->next_subchannel++;
	assert((*grobj)->subc <= 7);
	BEGIN_RING_GR(*grobj, 0x0000, 1);
	OUT_RING     ((*grobj)->handle);
	return 0;
}

static int
nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst,
			  unsigned dx, unsigned dy, struct pipe_surface *src,
			  unsigned sx, unsigned sy, unsigned w, unsigned h)
{
	struct nouveau_context *nv = nvws->nv;

	if (nv->surface_copy_prep(nv, dst, src))
		return 1;
	nv->surface_copy(nv, dx, dy, sx, sy, w, h);
	nv->surface_copy_done(nv);

	return 0;
}

static int
nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst,
			  unsigned dx, unsigned dy, unsigned w, unsigned h,
			  unsigned value)
{
	if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value))
		return 1;
	return 0;
}

int
nouveau_pipe_emit_reloc(struct nouveau_channel *chan, void *ptr,
			struct pipe_buffer *buf, uint32_t data,
			uint32_t flags, uint32_t vor, uint32_t tor)
{
	return nouveau_pushbuf_emit_reloc(chan, ptr, nouveau_buffer(buf)->bo,
					  data, flags, vor, tor);
}

struct pipe_context *
nouveau_pipe_create(struct nouveau_context *nv)
{
	struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys);
	struct pipe_context *(*hw_create)(struct pipe_winsys *,
					  struct nouveau_winsys *,
					  unsigned);

	if (!nvws)
		return NULL;

	switch (nv->chipset & 0xf0) {
	case 0x30:
		hw_create = nv30_create;
		break;
	case 0x40:
	case 0x60:
		hw_create = nv40_create;
		break;
	case 0x50:
	case 0x80:
		hw_create = nv50_create;
		break;
	default:
		NOUVEAU_ERR("Unknown chipset NV%02x\n", (int)nv->chipset);
		return NULL;
	}

	nvws->nv		= nv;
	nvws->channel		= nv->channel;

	nvws->res_init		= nouveau_resource_init;
	nvws->res_alloc		= nouveau_resource_alloc;
	nvws->res_free		= nouveau_resource_free;

	nvws->push_reloc        = nouveau_pipe_emit_reloc;
	nvws->push_flush	= nouveau_pushbuf_flush;

	nvws->grobj_alloc	= nouveau_pipe_grobj_alloc;
	nvws->grobj_free	= nouveau_grobj_free;

	nvws->notifier_alloc	= nouveau_pipe_notifier_alloc;
	nvws->notifier_free	= nouveau_notifier_free;
	nvws->notifier_reset	= nouveau_notifier_reset;
	nvws->notifier_status	= nouveau_notifier_status;
	nvws->notifier_retval	= nouveau_notifier_return_val;
	nvws->notifier_wait	= nouveau_notifier_wait_status;

	nvws->surface_copy	= nouveau_pipe_surface_copy;
	nvws->surface_fill	= nouveau_pipe_surface_fill;

	return hw_create(nouveau_create_pipe_winsys(nv), nvws, nv->chipset);
}