i965: fix bugs in projective texture coordinates
[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 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 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((struct pipe_reference**)pso, &ref->reference)) {
52 free(so->push);
53 for (i = 0; i < so->cur_reloc; i++)
54 pipe_buffer_reference(&so->reloc[i].bo, NULL);
55 free(so->reloc);
56 free(so);
57 }
58 }
59
60 static INLINE void
61 so_data(struct nouveau_stateobj *so, unsigned data)
62 {
63 (*so->cur++) = (data);
64 so->cur_packet += 4;
65 }
66
67 static INLINE void
68 so_datap(struct nouveau_stateobj *so, unsigned *data, unsigned size)
69 {
70 so->cur_packet += (4 * size);
71 while (size--)
72 (*so->cur++) = (*data++);
73 }
74
75 static INLINE void
76 so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
77 unsigned mthd, unsigned size)
78 {
79 so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4);
80 so_data(so, (gr->subc << 13) | (size << 18) | mthd);
81 }
82
83 static INLINE void
84 so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo,
85 unsigned data, unsigned flags, unsigned vor, unsigned tor)
86 {
87 struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
88
89 r->bo = NULL;
90 pipe_buffer_reference(&r->bo, bo);
91 r->offset = so->cur - so->push;
92 r->packet = so->cur_packet;
93 r->data = data;
94 r->flags = flags;
95 r->vor = vor;
96 r->tor = tor;
97 so_data(so, data);
98 }
99
100 static INLINE void
101 so_dump(struct nouveau_stateobj *so)
102 {
103 unsigned i, nr = so->cur - so->push;
104
105 for (i = 0; i < nr; i++)
106 debug_printf("+0x%04x: 0x%08x\n", i, so->push[i]);
107 }
108
109 static INLINE void
110 so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
111 {
112 struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
113 unsigned nr, i;
114
115 nr = so->cur - so->push;
116 if (pb->remaining < nr)
117 nvws->push_flush(nvws, nr, NULL);
118 pb->remaining -= nr;
119
120 memcpy(pb->cur, so->push, nr * 4);
121 for (i = 0; i < so->cur_reloc; i++) {
122 struct nouveau_stateobj_reloc *r = &so->reloc[i];
123
124 nvws->push_reloc(nvws, pb->cur + r->offset, r->bo,
125 r->data, r->flags, r->vor, r->tor);
126 }
127 pb->cur += nr;
128 }
129
130 static INLINE void
131 so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
132 {
133 struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
134 unsigned i;
135
136 if (!so)
137 return;
138
139 i = so->cur_reloc << 1;
140 if (nvws->channel->pushbuf->remaining < i)
141 nvws->push_flush(nvws, i, NULL);
142 nvws->channel->pushbuf->remaining -= i;
143
144 for (i = 0; i < so->cur_reloc; i++) {
145 struct nouveau_stateobj_reloc *r = &so->reloc[i];
146
147 nvws->push_reloc(nvws, pb->cur++, r->bo, r->packet,
148 (r->flags & (NOUVEAU_BO_VRAM |
149 NOUVEAU_BO_GART |
150 NOUVEAU_BO_RDWR)) |
151 NOUVEAU_BO_DUMMY, 0, 0);
152 nvws->push_reloc(nvws, pb->cur++, r->bo, r->data,
153 r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor);
154 }
155 }
156
157 #endif