Merge remote branch 'origin/master' into nvc0-new
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_bo_state.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29
30 static GLboolean
31 nouveau_bo_marker_emit(struct gl_context *ctx, struct nouveau_bo_marker *m,
32 uint32_t flags)
33 {
34 struct nouveau_channel *chan = context_chan(ctx);
35 uint32_t packet;
36
37 if (m->gr->bound == NOUVEAU_GROBJ_UNBOUND)
38 nouveau_grobj_autobind(m->gr);
39
40 if (MARK_RING(chan, 2, 2))
41 return GL_FALSE;
42
43 packet = (m->gr->subc << 13) | (1 << 18) | m->mthd;
44
45 if (flags) {
46 if (nouveau_pushbuf_emit_reloc(chan, chan->cur++, m->bo,
47 packet, 0, flags |
48 (m->flags & (NOUVEAU_BO_VRAM |
49 NOUVEAU_BO_GART |
50 NOUVEAU_BO_RDWR)),
51 0, 0))
52 goto fail;
53 } else {
54 *(chan->cur++) = packet;
55 }
56
57 if (nouveau_pushbuf_emit_reloc(chan, chan->cur++, m->bo, m->data,
58 m->data2, flags | m->flags,
59 m->vor, m->tor))
60 goto fail;
61
62 return GL_TRUE;
63
64 fail:
65 MARK_UNDO(chan);
66 return GL_FALSE;
67 }
68
69 static GLboolean
70 nouveau_bo_context_grow(struct nouveau_bo_context *bctx)
71 {
72 struct nouveau_bo_marker *marker = bctx->marker;
73 int allocated = bctx->allocated + 1;
74
75 marker = realloc(marker, allocated * sizeof(struct nouveau_bo_marker));
76 if (!marker)
77 return GL_FALSE;
78
79 bctx->marker = marker;
80 bctx->allocated = allocated;
81
82 return GL_TRUE;
83 }
84
85 GLboolean
86 nouveau_bo_mark(struct nouveau_bo_context *bctx, struct nouveau_grobj *gr,
87 uint32_t mthd, struct nouveau_bo *bo,
88 uint32_t data, uint32_t data2, uint32_t vor, uint32_t tor,
89 uint32_t flags)
90 {
91 struct nouveau_bo_state *s = &to_nouveau_context(bctx->ctx)->bo;
92 struct nouveau_bo_marker *m;
93
94 if (bctx->count == bctx->allocated) {
95 if (!nouveau_bo_context_grow(bctx))
96 goto fail;
97 }
98
99 m = &bctx->marker[bctx->count];
100
101 *m = (struct nouveau_bo_marker) {
102 .gr = gr,
103 .mthd = mthd,
104 .data = data,
105 .data2 = data2,
106 .vor = vor,
107 .tor = tor,
108 .flags = flags,
109 };
110 nouveau_bo_ref(bo, &m->bo);
111
112 s->count++;
113 bctx->count++;
114
115 if (!nouveau_bo_marker_emit(bctx->ctx, m, 0))
116 goto fail;
117
118 return GL_TRUE;
119
120 fail:
121 nouveau_bo_context_reset(bctx);
122 return GL_FALSE;
123 }
124
125 void
126 nouveau_bo_context_reset(struct nouveau_bo_context *bctx)
127 {
128 struct nouveau_bo_state *s = &to_nouveau_context(bctx->ctx)->bo;
129 int i, n = bctx->count;
130
131 s->count -= n;
132 bctx->count = 0;
133
134 for (i = 0; i < n; i++)
135 nouveau_bo_ref(NULL, &bctx->marker[i].bo);
136 }
137
138 GLboolean
139 nouveau_bo_state_emit(struct gl_context *ctx)
140 {
141 struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
142 int i, j;
143
144 for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++) {
145 struct nouveau_bo_context *bctx = &s->context[i];
146
147 for (j = 0; j < bctx->count; j++) {
148 if (!nouveau_bo_marker_emit(ctx, &bctx->marker[j],
149 NOUVEAU_BO_DUMMY))
150 return GL_FALSE;
151 }
152 }
153
154 return GL_TRUE;
155 }
156
157 void
158 nouveau_bo_state_init(struct gl_context *ctx)
159 {
160 struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
161 int i;
162
163 for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++)
164 s->context[i].ctx = ctx;
165 }
166
167 void
168 nouveau_bo_state_destroy(struct gl_context *ctx)
169 {
170 struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
171 int i, j;
172
173 for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++) {
174 struct nouveau_bo_context *bctx = &s->context[i];
175
176 for (j = 0; j < bctx->count; j++)
177 nouveau_bo_ref(NULL, &bctx->marker[j].bo);
178
179 if (bctx->marker)
180 free(bctx->marker);
181 }
182 }