blob: 2ead22e1beed86ff76020dd817571b49da5f77b5 [file] [log] [blame]
Mika Kuoppalad60d4c82014-04-10 15:15:13 +03001/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
Thomas Woodb9d27f02015-08-26 12:05:13 +01006 * Copyright 2014, 2015 Intel Corporation
Mika Kuoppalad60d4c82014-04-10 15:15:13 +03007 * 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>
Mika Kuoppala4a604de2014-08-01 21:19:56 +030032#include <stdlib.h>
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030033#include <string.h>
34#include <errno.h>
Mika Kuoppala4a604de2014-08-01 21:19:56 +030035#include <assert.h>
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030036
37#include "intel_batchbuffer.h"
38
Mika Kuoppala4a604de2014-08-01 21:19:56 +030039void bb_area_emit(struct bb_area *a, uint32_t dword, item_type type, const char *str)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030040{
Mika Kuoppala4a604de2014-08-01 21:19:56 +030041 struct bb_item *item;
42 assert(a != NULL);
43 assert(a->num_items < MAX_ITEMS);
44 item = &a->item[a->num_items];
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030045
Mika Kuoppala4a604de2014-08-01 21:19:56 +030046 item->data = dword;
47 item->type = type;
48 strncpy(item->str, str, MAX_STRLEN);
49 item->str[MAX_STRLEN - 1] = 0;
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030050
Mika Kuoppala4a604de2014-08-01 21:19:56 +030051 a->num_items++;
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030052}
53
Mika Kuoppala4a604de2014-08-01 21:19:56 +030054void bb_area_emit_offset(struct bb_area *a, unsigned offset, uint32_t dword, item_type type, const char *str)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030055{
Mika Kuoppala4a604de2014-08-01 21:19:56 +030056 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;
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030067}
68
Mika Kuoppala4a604de2014-08-01 21:19:56 +030069static struct bb_item *bb_area_get(struct bb_area *a, unsigned i)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030070{
Mika Kuoppala4a604de2014-08-01 21:19:56 +030071 assert (i < a->num_items);
72 return &a->item[i];
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030073}
74
Mika Kuoppala4a604de2014-08-01 21:19:56 +030075static unsigned bb_area_items(struct bb_area *a)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030076{
Mika Kuoppala4a604de2014-08-01 21:19:56 +030077 return a->num_items;
78}
Mika Kuoppalad60d4c82014-04-10 15:15:13 +030079
Mika Kuoppala4a604de2014-08-01 21:19:56 +030080static 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
88static 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
96struct intel_batchbuffer *intel_batchbuffer_create(void)
97{
98 struct intel_batchbuffer *batch;
99
100 batch = calloc(1, sizeof(*batch));
101 if (batch == NULL)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300102 return NULL;
103
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300104 batch->cmds = calloc(1, sizeof(struct bb_area));
105 if (batch->cmds == NULL) {
106 free(batch);
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300107 return NULL;
108 }
109
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300110 batch->state = calloc(1, sizeof(struct bb_area));
111 if (batch->state == NULL) {
112 free(batch->cmds);
113 free(batch);
114 return NULL;
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300115 }
116
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300117 batch->state_start_offset = -1;
118 batch->cmds_end_offset = -1;
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300119
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300120 return batch;
121}
122
123static 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
134static 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
147int intel_batch_is_reloc(struct intel_batchbuffer *batch, unsigned i)
148{
149 return reloc_exists(batch, i * 4);
150}
151
152static void intel_batch_cmd_align(struct intel_batchbuffer *batch, unsigned align)
153{
154 bb_area_align(batch->cmds, align);
155}
156
157static void intel_batch_state_align(struct intel_batchbuffer *batch, unsigned align)
158{
159 bb_area_align(batch->state, align);
160}
161
162unsigned intel_batch_num_cmds(struct intel_batchbuffer *batch)
163{
164 return bb_area_items(batch->cmds);
165}
166
Thomas Woodb9d27f02015-08-26 12:05:13 +0100167unsigned intel_batch_num_state(struct intel_batchbuffer *batch)
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300168{
169 return bb_area_items(batch->state);
170}
171
172struct bb_item *intel_batch_cmd_get(struct intel_batchbuffer *batch, unsigned i)
173{
174 return bb_area_get(batch->cmds, i);
175}
176
177struct bb_item *intel_batch_state_get(struct intel_batchbuffer *batch, unsigned i)
178{
179 return bb_area_get(batch->state, i);
180}
181
182uint32_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
188uint32_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);
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300200
201 return offset;
202}
203
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300204uint32_t intel_batch_state_copy(struct intel_batchbuffer *batch,
Thomas Wood35465142015-09-08 16:49:24 +0100205 const void *d, unsigned bytes,
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300206 unsigned align,
207 const char *str)
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300208{
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300209 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);
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300215
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300216 offset = intel_batch_state_offset(batch, align);
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300217
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300218 for (i = 0; i < dwords; i++) {
219 char offsetinside[80];
Thomas Wood35465142015-09-08 16:49:24 +0100220 const uint32_t *s;
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300221 sprintf(offsetinside, "%s: 0x%x", str, i * 4);
222
Thomas Wood35465142015-09-08 16:49:24 +0100223 s = (const uint32_t *)(const uint8_t *)d + i;
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300224 bb_area_emit(batch->state, *s, STATE, offsetinside);
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300225 }
226
Mika Kuoppalad60d4c82014-04-10 15:15:13 +0300227 return offset;
228}
Mika Kuoppala4a604de2014-08-01 21:19:56 +0300229
230void 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
257const 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}
Mika Kuoppalab69659c2014-09-08 10:41:38 +0300278
279void 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}