Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / mesa / pipe / nouveau / nouveau_stateobj.h
1 #ifndef __NOUVEAU_STATEOBJ_H__
2 #define __NOUVEAU_STATEOBJ_H__
3
4 #include "pipe/p_util.h"
5
6 struct nouveau_stateobj_reloc {
7 struct pipe_buffer *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 int refcount;
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 so->refcount = 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;
49
50 so = *pso;
51 if (so) {
52 if (--so->refcount <= 0) {
53 free(so->push);
54 free(so->reloc);
55 free(so);
56 }
57 *pso = NULL;
58 }
59
60 if (ref) {
61 ref->refcount++;
62 *pso = ref;
63 }
64 }
65
66 static INLINE void
67 so_data(struct nouveau_stateobj *so, unsigned data)
68 {
69 (*so->cur++) = (data);
70 so->cur_packet += 4;
71 }
72
73 static INLINE void
74 so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
75 unsigned mthd, unsigned size)
76 {
77 so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4);
78 so_data(so, (gr->subc << 13) | (size << 18) | mthd);
79 }
80
81 static INLINE void
82 so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo,
83 unsigned data, unsigned flags, unsigned vor, unsigned tor)
84 {
85 struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
86
87 r->bo = bo;
88 r->offset = so->cur - so->push;
89 r->packet = so->cur_packet;
90 r->data = data;
91 r->flags = flags;
92 r->vor = vor;
93 r->tor = tor;
94 so_data(so, data);
95 }
96
97 static INLINE void
98 so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
99 {
100 struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
101 unsigned nr, i;
102
103 nr = so->cur - so->push;
104 if (pb->remaining < nr)
105 nvws->push_flush(nvws->channel, nr);
106 pb->remaining -= nr;
107
108 memcpy(pb->cur, so->push, nr * 4);
109 for (i = 0; i < so->cur_reloc; i++) {
110 struct nouveau_stateobj_reloc *r = &so->reloc[i];
111
112 nvws->push_reloc(nvws->channel, pb->cur + r->offset, r->bo,
113 r->data, r->flags, r->vor, r->tor);
114 }
115 pb->cur += nr;
116 }
117
118 static INLINE void
119 so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
120 {
121 struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
122 unsigned i;
123
124 i = so->cur_reloc << 1;
125 if (nvws->channel->pushbuf->remaining < i)
126 nvws->push_flush(nvws->channel, i);
127 nvws->channel->pushbuf->remaining -= i;
128
129 for (i = 0; i < so->cur_reloc; i++) {
130 struct nouveau_stateobj_reloc *r = &so->reloc[i];
131
132 nvws->push_reloc(nvws->channel, pb->cur++, r->bo, r->packet,
133 (r->flags &
134 (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) |
135 NOUVEAU_BO_DUMMY, 0, 0);
136 nvws->push_reloc(nvws->channel, pb->cur++, r->bo, r->data,
137 r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor);
138 }
139 }
140
141 #endif