OSDN Git Service

intel: Fix up math errors when allocating very large BOs.
[android-x86/external-libdrm.git] / libdrm / nouveau / nouveau_pushbuf.h
1 /*
2  * Copyright 2007 Nouveau Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #ifndef __NOUVEAU_PUSHBUF_H__
24 #define __NOUVEAU_PUSHBUF_H__
25
26 #include <assert.h>
27 #include <string.h>
28
29 #include "nouveau_bo.h"
30 #include "nouveau_grobj.h"
31
32 struct nouveau_pushbuf {
33         struct nouveau_channel *channel;
34
35         unsigned remaining;
36         uint32_t *cur;
37 };
38
39 int
40 nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
41
42 int
43 nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
44                            struct nouveau_bo *, uint32_t data, uint32_t data2,
45                            uint32_t flags, uint32_t vor, uint32_t tor);
46
47 /* Push buffer access macros */
48 static __inline__ void
49 OUT_RING(struct nouveau_channel *chan, unsigned data)
50 {
51         *(chan->pushbuf->cur++) = (data);
52 }
53
54 static __inline__ void
55 OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
56 {
57         memcpy(chan->pushbuf->cur, data, size * 4);
58         chan->pushbuf->cur += size;
59 }
60
61 static __inline__ void
62 OUT_RINGf(struct nouveau_channel *chan, float f)
63 {
64         union { uint32_t i; float f; } c;
65         c.f = f;
66         OUT_RING(chan, c.i);
67 }
68
69 static __inline__ unsigned
70 AVAIL_RING(struct nouveau_channel *chan)
71 {
72         return chan->pushbuf->remaining;
73 }
74
75 static __inline__ void
76 WAIT_RING(struct nouveau_channel *chan, unsigned size)
77 {
78         if (chan->pushbuf->remaining < size)
79                 nouveau_pushbuf_flush(chan, size);
80 }
81
82 static __inline__ void
83 BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
84            unsigned mthd, unsigned size)
85 {
86         if (gr->bound == NOUVEAU_GROBJ_UNBOUND)
87                 nouveau_grobj_autobind(gr);
88         chan->subc[gr->subc].sequence = chan->subc_sequence++;
89
90         WAIT_RING(chan, size + 1);
91         OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
92         chan->pushbuf->remaining -= (size + 1);
93 }
94
95 static __inline__ void
96 FIRE_RING(struct nouveau_channel *chan)
97 {
98         nouveau_pushbuf_flush(chan, 0);
99 }
100
101 static __inline__ void
102 BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
103 {
104         struct nouveau_subchannel *subc = &gr->channel->subc[sc];
105         
106         if (subc->gr) {
107                 if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
108                         assert(0);
109                 subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
110         }
111         subc->gr = gr;
112         subc->gr->subc = sc;
113         subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
114
115         BEGIN_RING(chan, gr, 0x0000, 1);
116         OUT_RING  (chan, gr->handle);
117 }
118
119 static __inline__ void
120 OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
121           unsigned data, unsigned flags, unsigned vor, unsigned tor)
122 {
123         nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
124                                    data, 0, flags, vor, tor);
125 }
126
127 static __inline__ void
128 OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
129            unsigned data, unsigned data2, unsigned flags,
130            unsigned vor, unsigned tor)
131 {
132         nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
133                                    data, data2, flags, vor, tor);
134 }
135
136 /* Raw data + flags depending on FB/TT buffer */
137 static __inline__ void
138 OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
139            unsigned data, unsigned flags, unsigned vor, unsigned tor)
140 {
141         OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
142 }
143
144 /* FB/TT object handle */
145 static __inline__ void
146 OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
147            unsigned flags)
148 {
149         OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
150                   chan->vram->handle, chan->gart->handle);
151 }
152
153 /* Low 32-bits of offset */
154 static __inline__ void
155 OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
156            unsigned delta, unsigned flags)
157 {
158         OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
159 }
160
161 /* Low 32-bits of offset + GPU linear access range info */
162 static __inline__ void
163 OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
164            unsigned delta, unsigned size, unsigned flags)
165 {
166         OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
167 }
168
169 /* High 32-bits of offset */
170 static __inline__ void
171 OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
172            unsigned delta, unsigned flags)
173 {
174         OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
175 }
176
177 #endif