Tizen 2.0 Release
[profile/ivi/osmesa.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 }