9aee9e495664e3c8b3caf97669106e2b729ff256
[mesa.git] / src / gallium / drivers / nouveau / nouveau_stateobj.h
1 #ifndef __NOUVEAU_STATEOBJ_H__
2 #define __NOUVEAU_STATEOBJ_H__
3
4 #include "util/u_debug.h"
5
6 struct nouveau_stateobj_reloc {
7 struct nouveau_bo *bo;
8
9 unsigned offset;
10 unsigned packet;
11
12 unsigned data;
13 unsigned flags;
14 unsigned vor;
15 unsigned tor;
16 };
17
18 struct nouveau_stateobj {
19 struct pipe_reference reference;
20
21 unsigned *push;
22 struct nouveau_stateobj_reloc *reloc;
23
24 unsigned *cur;
25 unsigned cur_packet;
26 unsigned cur_reloc;
27 };
28
29 static INLINE struct nouveau_stateobj *
30 so_new(unsigned push, unsigned reloc)
31 {
32 struct nouveau_stateobj *so;
33
34 so = MALLOC(sizeof(struct nouveau_stateobj));
35 pipe_reference_init(&so->reference, 1);
36 so->push = MALLOC(sizeof(unsigned) * push);
37 so->reloc = MALLOC(sizeof(struct nouveau_stateobj_reloc) * reloc);
38
39 so->cur = so->push;
40 so->cur_reloc = so->cur_packet = 0;
41
42 return so;
43 }
44
45 static INLINE void
46 so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso)
47 {
48 struct nouveau_stateobj *so = *pso;
49 int i;
50
51 if (pipe_reference(&(*pso)->reference, &ref->reference)) {
52 free(so->push);
53 for (i = 0; i < so->cur_reloc; i++)
54 nouveau_bo_ref(NULL, &so->reloc[i].bo);
55 free(so->reloc);
56 free(so);
57 }
58 *pso = ref;
59 }
60
61 static INLINE void
62 so_data(struct nouveau_stateobj *so, unsigned data)
63 {
64 (*so->cur++) = (data);
65 so->cur_packet += 4;
66 }
67
68 static INLINE void
69 so_datap(struct nouveau_stateobj *so, unsigned *data, unsigned size)
70 {
71 so->cur_packet += (4 * size);
72 while (size--)
73 (*so->cur++) = (*data++);
74 }
75
76 static INLINE void
77 so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
78 unsigned mthd, unsigned size)
79 {
80 so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4);
81 so_data(so, (gr->subc << 13) | (size << 18) | mthd);
82 }
83
84 static INLINE void
85 so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
86 unsigned data, unsigned flags, unsigned vor, unsigned tor)
87 {
88 struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
89
90 r->bo = NULL;
91 nouveau_bo_ref(bo, &r->bo);
92 r->offset = so->cur - so->push;
93 r->packet = so->cur_packet;
94 r->data = data;
95 r->flags = flags;
96 r->vor = vor;
97 r->tor = tor;
98 so_data(so, data);
99 }
100
101 static INLINE void
102 so_dump(struct nouveau_stateobj *so)
103 {
104 unsigned i, nr = so->cur - so->push;
105
106 for (i = 0; i < nr; i++)
107 debug_printf("+0x%04x: 0x%08x\n", i, so->push[i]);
108 }
109
110 static INLINE void
111 so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
112 {
113 struct nouveau_pushbuf *pb = chan->pushbuf;
114 unsigned nr, i;
115 int ret = 0;
116
117 nr = so->cur - so->push;
118 /* This will flush if we need space.
119 * We don't actually need the marker.
120 */
121 if ((ret = nouveau_pushbuf_marker_emit(chan, nr, so->cur_reloc))) {
122 debug_printf("so_emit failed marker emit with error %d\n", ret);
123 return;
124 }
125 pb->remaining -= nr;
126
127 memcpy(pb->cur, so->push, nr * 4);
128 for (i = 0; i < so->cur_reloc; i++) {
129 struct nouveau_stateobj_reloc *r = &so->reloc[i];
130
131 if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
132 r->bo, r->data, 0, r->flags,
133 r->vor, r->tor))) {
134 debug_printf("so_emit failed reloc with error %d\n", ret);
135 goto out;
136 }
137 }
138 out:
139 pb->cur += nr;
140 }
141
142 static INLINE void
143 so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
144 {
145 struct nouveau_pushbuf *pb = chan->pushbuf;
146 unsigned i;
147 int ret = 0;
148
149 if (!so)
150 return;
151
152 i = so->cur_reloc << 1;
153 /* This will flush if we need space.
154 * We don't actually need the marker.
155 */
156 if ((ret = nouveau_pushbuf_marker_emit(chan, i, i))) {
157 debug_printf("so_emit_reloc_markers failed marker emit with" \
158 "error %d\n", ret);
159 return;
160 }
161 pb->remaining -= i;
162
163 for (i = 0; i < so->cur_reloc; i++) {
164 struct nouveau_stateobj_reloc *r = &so->reloc[i];
165
166 if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
167 r->packet, 0,
168 (r->flags & (NOUVEAU_BO_VRAM |
169 NOUVEAU_BO_GART |
170 NOUVEAU_BO_RDWR)) |
171 NOUVEAU_BO_DUMMY, 0, 0))) {
172 debug_printf("so_emit_reloc_markers failed reloc" \
173 "with error %d\n", ret);
174 pb->remaining += ((so->cur_reloc - i) << 1);
175 return;
176 }
177 if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
178 r->data, 0,
179 r->flags | NOUVEAU_BO_DUMMY,
180 r->vor, r->tor))) {
181 debug_printf("so_emit_reloc_markers failed reloc" \
182 "with error %d\n", ret);
183 pb->remaining += ((so->cur_reloc - i) << 1) - 1;
184 return;
185 }
186 }
187 }
188
189 #endif