• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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