+++ /dev/null
-#ifndef __NOUVEAU_STATEOBJ_H__
-#define __NOUVEAU_STATEOBJ_H__
-
-#include "util/u_debug.h"
-
-#ifdef DEBUG
-#define DEBUG_NOUVEAU_STATEOBJ
-#endif /* DEBUG */
-
-struct nouveau_stateobj_reloc {
- struct nouveau_bo *bo;
-
- struct nouveau_grobj *gr;
- uint32_t push_offset;
- uint32_t mthd;
-
- uint32_t data;
- unsigned flags;
- unsigned vor;
- unsigned tor;
-};
-
-struct nouveau_stateobj_start {
- struct nouveau_grobj *gr;
- uint32_t mthd;
- uint32_t size;
- unsigned offset;
-};
-
-struct nouveau_stateobj {
- struct pipe_reference reference;
-
- struct nouveau_stateobj_start *start;
- struct nouveau_stateobj_reloc *reloc;
-
- /* Common memory pool for data. */
- uint32_t *pool;
- unsigned pool_cur;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- unsigned start_alloc;
- unsigned reloc_alloc;
- unsigned pool_alloc;
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- unsigned total; /* includes begin_ring */
- unsigned cur; /* excludes begin_ring, offset from "cur_start" */
- unsigned cur_start;
- unsigned cur_reloc;
-};
-
-static INLINE void
-so_dump(struct nouveau_stateobj *so)
-{
- unsigned i, nr, total = 0;
-
- for (i = 0; i < so->cur_start; i++) {
- if (so->start[i].gr->subc > -1)
- debug_printf("+0x%04x: 0x%08x\n", total++,
- (so->start[i].size << 18) | (so->start[i].gr->subc << 13)
- | so->start[i].mthd);
- else
- debug_printf("+0x%04x: 0x%08x\n", total++,
- (so->start[i].size << 18) | so->start[i].mthd);
- for (nr = 0; nr < so->start[i].size; nr++, total++)
- debug_printf("+0x%04x: 0x%08x\n", total,
- so->pool[so->start[i].offset + nr]);
- }
-}
-
-static INLINE struct nouveau_stateobj *
-so_new(unsigned start, unsigned push, unsigned reloc)
-{
- struct nouveau_stateobj *so;
-
- so = MALLOC(sizeof(struct nouveau_stateobj));
- pipe_reference_init(&so->reference, 1);
- so->total = so->cur = so->cur_start = so->cur_reloc = 0;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- so->start_alloc = start;
- so->reloc_alloc = reloc;
- so->pool_alloc = push;
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- so->start = MALLOC(start * sizeof(struct nouveau_stateobj_start));
- so->reloc = MALLOC(reloc * sizeof(struct nouveau_stateobj_reloc));
- so->pool = MALLOC(push * sizeof(uint32_t));
- so->pool_cur = 0;
-
- if (!so->start || !so->reloc || !so->pool) {
- debug_printf("malloc failed\n");
- assert(0);
- }
-
- return so;
-}
-
-static INLINE void
-so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso)
-{
- struct nouveau_stateobj *so = *pso;
- int i;
-
- if (pipe_reference(&(*pso)->reference, &ref->reference)) {
- FREE(so->start);
- for (i = 0; i < so->cur_reloc; i++)
- nouveau_bo_ref(NULL, &so->reloc[i].bo);
- FREE(so->reloc);
- FREE(so->pool);
- FREE(so);
- }
- *pso = ref;
-}
-
-static INLINE void
-so_data(struct nouveau_stateobj *so, uint32_t data)
-{
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->cur >= so->start[so->cur_start - 1].size) {
- debug_printf("exceeding specified size\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- so->pool[so->start[so->cur_start - 1].offset + so->cur++] = data;
-}
-
-static INLINE void
-so_datap(struct nouveau_stateobj *so, uint32_t *data, unsigned size)
-{
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if ((so->cur + size) > so->start[so->cur_start - 1].size) {
- debug_printf("exceeding specified size\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- while (size--)
- so->pool[so->start[so->cur_start - 1].offset + so->cur++] =
- *data++;
-}
-
-static INLINE void
-so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
- unsigned mthd, unsigned size)
-{
- struct nouveau_stateobj_start *start;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->start_alloc <= so->cur_start) {
- debug_printf("exceeding num_start size\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
- start = so->start;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->cur_start > 0 && start[so->cur_start - 1].size > so->cur) {
- debug_printf("previous so_method was not filled\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- start[so->cur_start].gr = gr;
- start[so->cur_start].mthd = mthd;
- start[so->cur_start].size = size;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->pool_alloc < (size + so->pool_cur)) {
- debug_printf("exceeding num_pool size\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- start[so->cur_start].offset = so->pool_cur;
- so->pool_cur += size;
-
- so->cur_start++;
- /* The 1 is for *this* begin_ring. */
- so->total += so->cur + 1;
- so->cur = 0;
-}
-
-static INLINE void
-so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
- unsigned data, unsigned flags, unsigned vor, unsigned tor)
-{
- struct nouveau_stateobj_reloc *r;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->reloc_alloc <= so->cur_reloc) {
- debug_printf("exceeding num_reloc size\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
- r = so->reloc;
-
- r[so->cur_reloc].bo = NULL;
- nouveau_bo_ref(bo, &(r[so->cur_reloc].bo));
- r[so->cur_reloc].gr = so->start[so->cur_start-1].gr;
- r[so->cur_reloc].push_offset = so->total + so->cur;
- r[so->cur_reloc].data = data;
- r[so->cur_reloc].flags = flags;
- r[so->cur_reloc].mthd = so->start[so->cur_start-1].mthd +
- (so->cur << 2);
- r[so->cur_reloc].vor = vor;
- r[so->cur_reloc].tor = tor;
-
- so_data(so, data);
- so->cur_reloc++;
-}
-
-/* Determine if this buffer object is referenced by this state object. */
-static INLINE boolean
-so_bo_is_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo)
-{
- int i;
-
- for (i = 0; i < so->cur_reloc; i++)
- if (so->reloc[i].bo == bo)
- return true;
-
- return false;
-}
-
-static INLINE void
-so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
-{
- unsigned nr, i;
- int ret = 0;
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (so->start[so->cur_start - 1].size > so->cur) {
- debug_printf("emit: previous so_method was not filled\n");
- assert(0);
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- /* We cannot update total in case we so_emit again. */
- nr = so->total + so->cur;
-
- /* This will flush if we need space.
- * We don't actually need the marker.
- */
- if ((ret = nouveau_pushbuf_marker_emit(chan, nr, so->cur_reloc))) {
- debug_printf("so_emit failed marker emit with error %d\n", ret);
- assert(0);
- }
-
- /* Submit data. This will ensure proper binding of objects. */
- for (i = 0; i < so->cur_start; i++) {
- BEGIN_RING(chan, so->start[i].gr, so->start[i].mthd, so->start[i].size);
- OUT_RINGp(chan, &(so->pool[so->start[i].offset]), so->start[i].size);
- }
-
- for (i = 0; i < so->cur_reloc; i++) {
- struct nouveau_stateobj_reloc *r = &so->reloc[i];
-
- if ((ret = nouveau_pushbuf_emit_reloc(chan, chan->cur - nr +
- r->push_offset, r->bo, r->data,
- 0, r->flags, r->vor, r->tor))) {
- debug_printf("so_emit failed reloc with error %d\n", ret);
- assert(0);
- }
- }
-}
-
-static INLINE void
-so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
-{
- unsigned i;
- int ret = 0;
-
- if (!so)
- return;
-
- /* If we need to flush in flush notify, then we have a problem anyway. */
- for (i = 0; i < so->cur_reloc; i++) {
- struct nouveau_stateobj_reloc *r = &so->reloc[i];
-
-#ifdef DEBUG_NOUVEAU_STATEOBJ
- if (r->mthd & 0x40000000) {
- debug_printf("error: NI mthd 0x%08X\n", r->mthd);
- continue;
- }
-#endif /* DEBUG_NOUVEAU_STATEOBJ */
-
- /* We don't need to autobind, since there are enough subchannels
- * for all objects we use. If this is changed, account for the extra
- * space in callers of this function.
- */
- assert(r->gr->bound != NOUVEAU_GROBJ_UNBOUND);
-
- /* Some relocs really don't like to be hammered,
- * NOUVEAU_BO_DUMMY makes sure it only
- * happens when needed.
- */
- ret = OUT_RELOC(chan, r->bo, (r->gr->subc << 13) | (1<< 18) |
- r->mthd, (r->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART
- | NOUVEAU_BO_RDWR)) | NOUVEAU_BO_DUMMY, 0, 0);
- if (ret) {
- debug_printf("OUT_RELOC failed %d\n", ret);
- assert(0);
- }
-
- ret = OUT_RELOC(chan, r->bo, r->data, r->flags |
- NOUVEAU_BO_DUMMY, r->vor, r->tor);
- if (ret) {
- debug_printf("OUT_RELOC failed %d\n", ret);
- assert(0);
- }
- }
-}
-
-#endif