/************************************************************************** * * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Copyright 2014, 2015 Intel Corporation * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ #include #include #include #include #include #include "intel_batchbuffer.h" void bb_area_emit(struct bb_area *a, uint32_t dword, item_type type, const char *str) { struct bb_item *item; assert(a != NULL); assert(a->num_items < MAX_ITEMS); item = &a->item[a->num_items]; item->data = dword; item->type = type; strncpy(item->str, str, MAX_STRLEN); item->str[MAX_STRLEN - 1] = 0; a->num_items++; } void bb_area_emit_offset(struct bb_area *a, unsigned offset, uint32_t dword, item_type type, const char *str) { const unsigned i = offset / 4; struct bb_item *item; assert(a != NULL); assert(a->num_items < MAX_ITEMS); assert(i < a->num_items); item = &a->item[i]; item->data = dword; item->type = type; strncpy(item->str, str, MAX_STRLEN); item->str[MAX_STRLEN - 1] = 0; } static struct bb_item *bb_area_get(struct bb_area *a, unsigned i) { assert (i < a->num_items); return &a->item[i]; } static unsigned bb_area_items(struct bb_area *a) { return a->num_items; } static unsigned long bb_area_used(struct bb_area *a) { assert(a != NULL); assert(a->num_items <= MAX_ITEMS); return a->num_items * 4; } static unsigned long bb_area_room(struct bb_area *a) { assert (a != NULL); assert (a->num_items <= MAX_ITEMS); return (MAX_ITEMS - a->num_items) * 4; } struct intel_batchbuffer *intel_batchbuffer_create(void) { struct intel_batchbuffer *batch; batch = calloc(1, sizeof(*batch)); if (batch == NULL) return NULL; batch->cmds = calloc(1, sizeof(struct bb_area)); if (batch->cmds == NULL) { free(batch); return NULL; } batch->state = calloc(1, sizeof(struct bb_area)); if (batch->state == NULL) { free(batch->cmds); free(batch); return NULL; } batch->state_start_offset = -1; batch->cmds_end_offset = -1; return batch; } static void bb_area_align(struct bb_area *a, unsigned align) { if (align == 0) return; assert((align % 4) == 0); while ((a->num_items * 4) % align != 0) bb_area_emit(a, 0, PAD, "align pad"); } static int reloc_exists(struct intel_batchbuffer *batch, uint32_t offset) { int i; for (i = 0; i < batch->cmds->num_items; i++) if ((batch->cmds->item[i].type == RELOC || batch->cmds->item[i].type == RELOC_STATE) && i * 4 == offset) return 1; return 0; } int intel_batch_is_reloc(struct intel_batchbuffer *batch, unsigned i) { return reloc_exists(batch, i * 4); } static void intel_batch_cmd_align(struct intel_batchbuffer *batch, unsigned align) { bb_area_align(batch->cmds, align); } static void intel_batch_state_align(struct intel_batchbuffer *batch, unsigned align) { bb_area_align(batch->state, align); } unsigned intel_batch_num_cmds(struct intel_batchbuffer *batch) { return bb_area_items(batch->cmds); } unsigned intel_batch_num_state(struct intel_batchbuffer *batch) { return bb_area_items(batch->state); } struct bb_item *intel_batch_cmd_get(struct intel_batchbuffer *batch, unsigned i) { return bb_area_get(batch->cmds, i); } struct bb_item *intel_batch_state_get(struct intel_batchbuffer *batch, unsigned i) { return bb_area_get(batch->state, i); } uint32_t intel_batch_state_offset(struct intel_batchbuffer *batch, unsigned align) { intel_batch_state_align(batch, align); return bb_area_used(batch->state); } uint32_t intel_batch_state_alloc(struct intel_batchbuffer *batch, unsigned bytes, unsigned align, const char *str) { unsigned offset; unsigned dwords = bytes/4; assert ((bytes % 4) == 0); assert (bb_area_room(batch->state) >= bytes); offset = intel_batch_state_offset(batch, align); while (dwords--) bb_area_emit(batch->state, 0, UNINITIALIZED, str); return offset; } uint32_t intel_batch_state_copy(struct intel_batchbuffer *batch, const void *d, unsigned bytes, unsigned align, const char *str) { unsigned offset; unsigned i; unsigned dwords = bytes/4; assert (d); assert ((bytes % 4) == 0); assert (bb_area_room(batch->state) >= bytes); offset = intel_batch_state_offset(batch, align); for (i = 0; i < dwords; i++) { char offsetinside[80]; const uint32_t *s; sprintf(offsetinside, "%s: 0x%x", str, i * 4); s = (const uint32_t *)(const uint8_t *)d + i; bb_area_emit(batch->state, *s, STATE, offsetinside); } return offset; } void intel_batch_relocate_state(struct intel_batchbuffer *batch) { unsigned int i; assert (batch->state_start_offset == -1); batch->cmds_end_offset = bb_area_used(batch->cmds) - 4; /* Hardcoded, could track max align done also */ intel_batch_cmd_align(batch, 64); batch->state_start_offset = bb_area_used(batch->cmds); for (i = 0; i < bb_area_items(batch->state); i++) { const struct bb_item *s = bb_area_get(batch->state, i); bb_area_emit(batch->cmds, s->data, s->type, s->str); } for (i = 0; i < bb_area_items(batch->cmds); i++) { struct bb_item *s = bb_area_get(batch->cmds, i); if (s->type == STATE_OFFSET || s->type == RELOC_STATE) s->data += batch->state_start_offset; } } const char *intel_batch_type_as_str(const struct bb_item *item) { switch (item->type) { case UNINITIALIZED: return "UNINITIALIZED"; case CMD: return "CMD"; case STATE: return "STATE"; case PAD: return "PAD"; case RELOC: return "RELOC"; case RELOC_STATE: return "RELOC_STATE"; case STATE_OFFSET: return "STATE_OFFSET"; } return "UNKNOWN"; } void intel_batch_cmd_emit_null(struct intel_batchbuffer *batch, const int cmd, const int len, const int len_bias, const char *str) { int i; assert(len > 1); assert((len - len_bias) >= 0); bb_area_emit(batch->cmds, (cmd | (len - len_bias)), CMD, str); for (i = len_bias-1; i < len; i++) OUT_BATCH(0); }