diff options
Diffstat (limited to 'libdrm')
| -rw-r--r-- | libdrm/nouveau/nouveau_private.h | 3 | ||||
| -rw-r--r-- | libdrm/nouveau/nouveau_pushbuf.c | 53 | ||||
| -rw-r--r-- | libdrm/nouveau/nouveau_pushbuf.h | 53 | 
3 files changed, 90 insertions, 19 deletions
| diff --git a/libdrm/nouveau/nouveau_private.h b/libdrm/nouveau/nouveau_private.h index 743c8314..784afc91 100644 --- a/libdrm/nouveau/nouveau_private.h +++ b/libdrm/nouveau/nouveau_private.h @@ -52,6 +52,9 @@ struct nouveau_pushbuf_priv {  	unsigned *pushbuf;  	unsigned  size; +	unsigned marker; +	unsigned marker_relocs; +  	struct drm_nouveau_gem_pushbuf_bo *buffers;  	unsigned nr_buffers;  	struct drm_nouveau_gem_pushbuf_reloc *relocs; diff --git a/libdrm/nouveau/nouveau_pushbuf.c b/libdrm/nouveau/nouveau_pushbuf.c index af181b2e..df43effc 100644 --- a/libdrm/nouveau/nouveau_pushbuf.c +++ b/libdrm/nouveau/nouveau_pushbuf.c @@ -67,7 +67,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,  	if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {  		fprintf(stderr, "too many relocs!!\n"); -		assert(0);  		return -ENOMEM;  	} @@ -79,7 +78,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,  	pbbo = nouveau_bo_emit_buffer(chan, bo);  	if (!pbbo) {  		fprintf(stderr, "buffer emit fail :(\n"); -		assert(0);  		return -ENOMEM;  	} @@ -353,6 +351,57 @@ restart_push:  	if (chan->flush_notify)  		chan->flush_notify(chan); +	nvpb->marker = 0;  	return ret;  } +int +nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, +			    unsigned wait_dwords, unsigned wait_relocs) +{ +	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); + +	if (AVAIL_RING(chan) < wait_dwords) +		return nouveau_pushbuf_flush(chan, wait_dwords); + +	if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS) +		return nouveau_pushbuf_flush(chan, wait_dwords); + +	nvpb->marker = nvpb->base.cur - nvpb->pushbuf; +	nvpb->marker_relocs = nvpb->nr_relocs; +	return 0; +} + +void +nouveau_pushbuf_marker_undo(struct nouveau_channel *chan) +{ +	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); +	unsigned i; + +	if (!nvpb->marker) +		return; + +	/* undo any relocs/buffers added to the list since last marker */ +	for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) { +		struct drm_nouveau_gem_pushbuf_reloc *r = &nvpb->relocs[i]; +		struct drm_nouveau_gem_pushbuf_bo *pbbo = +			&nvpb->buffers[r->bo_index]; +		struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv; +		struct nouveau_bo_priv *nvbo = nouveau_bo(bo); + +		if (--nvbo->pending_refcnt) +			continue; + +		nvbo->pending = NULL; +		nouveau_bo_ref(NULL, &bo); +		nvpb->nr_buffers--; +	} +	nvpb->nr_relocs = nvpb->marker_relocs; + +	/* reset pushbuf back to last marker */ +	nvpb->base.cur = nvpb->pushbuf + nvpb->marker; +	nvpb->base.remaining = nvpb->size - nvpb->marker; +	nvpb->marker = 0; +} + + diff --git a/libdrm/nouveau/nouveau_pushbuf.h b/libdrm/nouveau/nouveau_pushbuf.h index 3c746ed2..c7ac8c45 100644 --- a/libdrm/nouveau/nouveau_pushbuf.h +++ b/libdrm/nouveau/nouveau_pushbuf.h @@ -40,11 +40,30 @@ int  nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);  int +nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, +			    unsigned wait_dwords, unsigned wait_relocs); + +void +nouveau_pushbuf_marker_undo(struct nouveau_channel *chan); + +int  nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,  			   struct nouveau_bo *, uint32_t data, uint32_t data2,  			   uint32_t flags, uint32_t vor, uint32_t tor);  /* Push buffer access macros */ +static __inline__ int +MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs) +{ +	return nouveau_pushbuf_marker_emit(chan, dwords, relocs); +} + +static __inline__ void +MARK_UNDO(struct nouveau_channel *chan) +{ +	nouveau_pushbuf_marker_undo(chan); +} +  static __inline__ void  OUT_RING(struct nouveau_channel *chan, unsigned data)  { @@ -116,62 +135,62 @@ BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)  	OUT_RING  (chan, gr->handle);  } -static __inline__ void +static __inline__ int  OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,  	  unsigned data, unsigned flags, unsigned vor, unsigned tor)  { -	nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, -				   data, 0, flags, vor, tor); +	return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, +					  data, 0, flags, vor, tor);  } -static __inline__ void +static __inline__ int  OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned data, unsigned data2, unsigned flags,  	   unsigned vor, unsigned tor)  { -	nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, -				   data, data2, flags, vor, tor); +	return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, +					  data, data2, flags, vor, tor);  }  /* Raw data + flags depending on FB/TT buffer */ -static __inline__ void +static __inline__ int  OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned data, unsigned flags, unsigned vor, unsigned tor)  { -	OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor); +	return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);  }  /* FB/TT object handle */ -static __inline__ void +static __inline__ int  OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned flags)  { -	OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR, -		  chan->vram->handle, chan->gart->handle); +	return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR, +			 chan->vram->handle, chan->gart->handle);  }  /* Low 32-bits of offset */ -static __inline__ void +static __inline__ int  OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned delta, unsigned flags)  { -	OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); +	return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);  }  /* Low 32-bits of offset + GPU linear access range info */ -static __inline__ void +static __inline__ int  OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned delta, unsigned size, unsigned flags)  { -	OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0); +	return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);  }  /* High 32-bits of offset */ -static __inline__ void +static __inline__ int  OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,  	   unsigned delta, unsigned flags)  { -	OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0); +	return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);  }  #endif | 
