1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Copyright 2014, 2015 Intel Corporation
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 **************************************************************************/
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <assert.h>
36
37 #include "intel_batchbuffer.h"
38
bb_area_emit(struct bb_area * a,uint32_t dword,item_type type,const char * str)39 void bb_area_emit(struct bb_area *a, uint32_t dword, item_type type, const char *str)
40 {
41 struct bb_item *item;
42 assert(a != NULL);
43 assert(a->num_items < MAX_ITEMS);
44 item = &a->item[a->num_items];
45
46 item->data = dword;
47 item->type = type;
48 strncpy(item->str, str, MAX_STRLEN);
49 item->str[MAX_STRLEN - 1] = 0;
50
51 a->num_items++;
52 }
53
bb_area_emit_offset(struct bb_area * a,unsigned offset,uint32_t dword,item_type type,const char * str)54 void bb_area_emit_offset(struct bb_area *a, unsigned offset, uint32_t dword, item_type type, const char *str)
55 {
56 const unsigned i = offset / 4;
57 struct bb_item *item;
58 assert(a != NULL);
59 assert(a->num_items < MAX_ITEMS);
60 assert(i < a->num_items);
61 item = &a->item[i];
62
63 item->data = dword;
64 item->type = type;
65 strncpy(item->str, str, MAX_STRLEN);
66 item->str[MAX_STRLEN - 1] = 0;
67 }
68
bb_area_get(struct bb_area * a,unsigned i)69 static struct bb_item *bb_area_get(struct bb_area *a, unsigned i)
70 {
71 assert (i < a->num_items);
72 return &a->item[i];
73 }
74
bb_area_items(struct bb_area * a)75 static unsigned bb_area_items(struct bb_area *a)
76 {
77 return a->num_items;
78 }
79
bb_area_used(struct bb_area * a)80 static unsigned long bb_area_used(struct bb_area *a)
81 {
82 assert(a != NULL);
83 assert(a->num_items <= MAX_ITEMS);
84
85 return a->num_items * 4;
86 }
87
bb_area_room(struct bb_area * a)88 static unsigned long bb_area_room(struct bb_area *a)
89 {
90 assert (a != NULL);
91 assert (a->num_items <= MAX_ITEMS);
92
93 return (MAX_ITEMS - a->num_items) * 4;
94 }
95
intel_batchbuffer_create(void)96 struct intel_batchbuffer *intel_batchbuffer_create(void)
97 {
98 struct intel_batchbuffer *batch;
99
100 batch = calloc(1, sizeof(*batch));
101 if (batch == NULL)
102 return NULL;
103
104 batch->cmds = calloc(1, sizeof(struct bb_area));
105 if (batch->cmds == NULL) {
106 free(batch);
107 return NULL;
108 }
109
110 batch->state = calloc(1, sizeof(struct bb_area));
111 if (batch->state == NULL) {
112 free(batch->cmds);
113 free(batch);
114 return NULL;
115 }
116
117 batch->state_start_offset = -1;
118 batch->cmds_end_offset = -1;
119
120 return batch;
121 }
122
bb_area_align(struct bb_area * a,unsigned align)123 static void bb_area_align(struct bb_area *a, unsigned align)
124 {
125 if (align == 0)
126 return;
127
128 assert((align % 4) == 0);
129
130 while ((a->num_items * 4) % align != 0)
131 bb_area_emit(a, 0, PAD, "align pad");
132 }
133
reloc_exists(struct intel_batchbuffer * batch,uint32_t offset)134 static int reloc_exists(struct intel_batchbuffer *batch, uint32_t offset)
135 {
136 int i;
137
138 for (i = 0; i < batch->cmds->num_items; i++)
139 if ((batch->cmds->item[i].type == RELOC ||
140 batch->cmds->item[i].type == RELOC_STATE) &&
141 i * 4 == offset)
142 return 1;
143
144 return 0;
145 }
146
intel_batch_is_reloc(struct intel_batchbuffer * batch,unsigned i)147 int intel_batch_is_reloc(struct intel_batchbuffer *batch, unsigned i)
148 {
149 return reloc_exists(batch, i * 4);
150 }
151
intel_batch_cmd_align(struct intel_batchbuffer * batch,unsigned align)152 static void intel_batch_cmd_align(struct intel_batchbuffer *batch, unsigned align)
153 {
154 bb_area_align(batch->cmds, align);
155 }
156
intel_batch_state_align(struct intel_batchbuffer * batch,unsigned align)157 static void intel_batch_state_align(struct intel_batchbuffer *batch, unsigned align)
158 {
159 bb_area_align(batch->state, align);
160 }
161
intel_batch_num_cmds(struct intel_batchbuffer * batch)162 unsigned intel_batch_num_cmds(struct intel_batchbuffer *batch)
163 {
164 return bb_area_items(batch->cmds);
165 }
166
intel_batch_num_state(struct intel_batchbuffer * batch)167 unsigned intel_batch_num_state(struct intel_batchbuffer *batch)
168 {
169 return bb_area_items(batch->state);
170 }
171
intel_batch_cmd_get(struct intel_batchbuffer * batch,unsigned i)172 struct bb_item *intel_batch_cmd_get(struct intel_batchbuffer *batch, unsigned i)
173 {
174 return bb_area_get(batch->cmds, i);
175 }
176
intel_batch_state_get(struct intel_batchbuffer * batch,unsigned i)177 struct bb_item *intel_batch_state_get(struct intel_batchbuffer *batch, unsigned i)
178 {
179 return bb_area_get(batch->state, i);
180 }
181
intel_batch_state_offset(struct intel_batchbuffer * batch,unsigned align)182 uint32_t intel_batch_state_offset(struct intel_batchbuffer *batch, unsigned align)
183 {
184 intel_batch_state_align(batch, align);
185 return bb_area_used(batch->state);
186 }
187
intel_batch_state_alloc(struct intel_batchbuffer * batch,unsigned bytes,unsigned align,const char * str)188 uint32_t intel_batch_state_alloc(struct intel_batchbuffer *batch, unsigned bytes, unsigned align,
189 const char *str)
190 {
191 unsigned offset;
192 unsigned dwords = bytes/4;
193 assert ((bytes % 4) == 0);
194 assert (bb_area_room(batch->state) >= bytes);
195
196 offset = intel_batch_state_offset(batch, align);
197
198 while (dwords--)
199 bb_area_emit(batch->state, 0, UNINITIALIZED, str);
200
201 return offset;
202 }
203
intel_batch_state_copy(struct intel_batchbuffer * batch,const void * d,unsigned bytes,unsigned align,const char * str)204 uint32_t intel_batch_state_copy(struct intel_batchbuffer *batch,
205 const void *d, unsigned bytes,
206 unsigned align,
207 const char *str)
208 {
209 unsigned offset;
210 unsigned i;
211 unsigned dwords = bytes/4;
212 assert (d);
213 assert ((bytes % 4) == 0);
214 assert (bb_area_room(batch->state) >= bytes);
215
216 offset = intel_batch_state_offset(batch, align);
217
218 for (i = 0; i < dwords; i++) {
219 char offsetinside[80];
220 const uint32_t *s;
221 sprintf(offsetinside, "%s: 0x%x", str, i * 4);
222
223 s = (const uint32_t *)(const uint8_t *)d + i;
224 bb_area_emit(batch->state, *s, STATE, offsetinside);
225 }
226
227 return offset;
228 }
229
intel_batch_relocate_state(struct intel_batchbuffer * batch)230 void intel_batch_relocate_state(struct intel_batchbuffer *batch)
231 {
232 unsigned int i;
233
234 assert (batch->state_start_offset == -1);
235
236 batch->cmds_end_offset = bb_area_used(batch->cmds) - 4;
237
238 /* Hardcoded, could track max align done also */
239 intel_batch_cmd_align(batch, 64);
240
241 batch->state_start_offset = bb_area_used(batch->cmds);
242
243 for (i = 0; i < bb_area_items(batch->state); i++) {
244 const struct bb_item *s = bb_area_get(batch->state, i);
245
246 bb_area_emit(batch->cmds, s->data, s->type, s->str);
247 }
248
249 for (i = 0; i < bb_area_items(batch->cmds); i++) {
250 struct bb_item *s = bb_area_get(batch->cmds, i);
251
252 if (s->type == STATE_OFFSET || s->type == RELOC_STATE)
253 s->data += batch->state_start_offset;
254 }
255 }
256
intel_batch_type_as_str(const struct bb_item * item)257 const char *intel_batch_type_as_str(const struct bb_item *item)
258 {
259 switch (item->type) {
260 case UNINITIALIZED:
261 return "UNINITIALIZED";
262 case CMD:
263 return "CMD";
264 case STATE:
265 return "STATE";
266 case PAD:
267 return "PAD";
268 case RELOC:
269 return "RELOC";
270 case RELOC_STATE:
271 return "RELOC_STATE";
272 case STATE_OFFSET:
273 return "STATE_OFFSET";
274 }
275
276 return "UNKNOWN";
277 }
278
intel_batch_cmd_emit_null(struct intel_batchbuffer * batch,const int cmd,const int len,const int len_bias,const char * str)279 void intel_batch_cmd_emit_null(struct intel_batchbuffer *batch,
280 const int cmd, const int len, const int len_bias,
281 const char *str)
282 {
283 int i;
284
285 assert(len > 1);
286 assert((len - len_bias) >= 0);
287
288 bb_area_emit(batch->cmds, (cmd | (len - len_bias)), CMD, str);
289
290 for (i = len_bias-1; i < len; i++)
291 OUT_BATCH(0);
292 }
293