nouveau: use "indirect" push buffers
This commit is contained in:
@@ -17,9 +17,11 @@ DRIVER_SOURCES = \
|
||||
nouveau_context.c \
|
||||
nouveau_device.c \
|
||||
nouveau_dma.c \
|
||||
nouveau_fence.c \
|
||||
nouveau_grobj.c \
|
||||
nouveau_lock.c \
|
||||
nouveau_notifier.c \
|
||||
nouveau_pushbuf.c \
|
||||
nouveau_screen.c \
|
||||
nouveau_swapbuffers.c \
|
||||
nouveau_winsys.c \
|
||||
|
||||
@@ -91,6 +91,7 @@ nouveau_channel_alloc(struct nouveau_device *userdev, uint32_t fb_ctxdma,
|
||||
malloc(sizeof(struct nouveau_bo_reloc) * chan->max_relocs);
|
||||
|
||||
nouveau_dma_channel_init(&chan->base);
|
||||
nouveau_pushbuf_init(&chan->base);
|
||||
|
||||
*userchan = &chan->base;
|
||||
return 0;
|
||||
|
||||
@@ -44,6 +44,7 @@ struct nouveau_context {
|
||||
struct nouveau_bo *reloc_head;
|
||||
|
||||
/* Hardware context */
|
||||
uint32_t *pushbuf;
|
||||
struct nouveau_channel *channel;
|
||||
struct nouveau_notifier *sync_notifier;
|
||||
struct nouveau_grobj *NvNull;
|
||||
@@ -98,4 +99,7 @@ extern void UNLOCK_HARDWARE(struct nouveau_context *);
|
||||
extern int nouveau_surface_init_nv04(struct nouveau_context *);
|
||||
extern int nouveau_surface_init_nv50(struct nouveau_context *);
|
||||
|
||||
extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int);
|
||||
extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -141,35 +141,6 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan)
|
||||
if (chan->dma.cur == chan->dma.put)
|
||||
return;
|
||||
|
||||
if (chan->num_relocs) {
|
||||
nouveau_bo_validate(userchan);
|
||||
|
||||
for (i = 0; i < chan->num_relocs; i++) {
|
||||
struct nouveau_bo_reloc *r = &chan->relocs[i];
|
||||
uint32_t push;
|
||||
|
||||
if (r->flags & NOUVEAU_BO_LOW) {
|
||||
push = r->bo->base.offset + r->data;
|
||||
} else
|
||||
if (r->flags & NOUVEAU_BO_HIGH) {
|
||||
push = (r->bo->base.offset + r->data) >> 32;
|
||||
} else {
|
||||
push = r->data;
|
||||
}
|
||||
|
||||
if (r->flags & NOUVEAU_BO_OR) {
|
||||
if (r->bo->base.flags & NOUVEAU_BO_VRAM)
|
||||
push |= r->vor;
|
||||
else
|
||||
push |= r->tor;
|
||||
}
|
||||
|
||||
*r->ptr = push;
|
||||
}
|
||||
|
||||
chan->num_relocs = 0;
|
||||
}
|
||||
|
||||
#ifdef NOUVEAU_DMA_DEBUG
|
||||
if (chan->dma.push_free) {
|
||||
NOUVEAU_ERR("Packet incomplete: %d left\n", chan->dma.push_free);
|
||||
@@ -178,8 +149,20 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan)
|
||||
#endif
|
||||
|
||||
#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
|
||||
for (i = chan->dma.put; i < chan->dma.cur; i++)
|
||||
NOUVEAU_MSG("0x%08x\n", chan->pushbuf[i]);
|
||||
for (i = chan->dma.put; i < chan->dma.cur; i++) {
|
||||
NOUVEAU_MSG("0x%08x 0x%08x\n", (i<<2)+chan->dma.base,
|
||||
chan->pushbuf[i]);
|
||||
if ((chan->pushbuf[i] & 0xf0000000) == 0x20000000) {
|
||||
int n = (((chan->pushbuf[i] & 0x0fffffff) -
|
||||
chan->dma.base) / 4);
|
||||
|
||||
do {
|
||||
NOUVEAU_MSG("\t0x%08x 0x%08x\n",
|
||||
(n<<2)+chan->dma.base,
|
||||
chan->pushbuf[n]);
|
||||
} while ((chan->pushbuf[n++]&0xf0000000) != 0x20000000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
put_offset = (chan->dma.cur << 2) + chan->dma.base;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "pipe/nouveau/nouveau_grobj.h"
|
||||
#include "pipe/nouveau/nouveau_notifier.h"
|
||||
#include "pipe/nouveau/nouveau_bo.h"
|
||||
#include "pipe/nouveau/nouveau_resource.h"
|
||||
|
||||
struct nouveau_device_priv {
|
||||
struct nouveau_device base;
|
||||
@@ -59,6 +60,61 @@ nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
|
||||
extern int
|
||||
nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
|
||||
|
||||
struct nouveau_fence {
|
||||
struct nouveau_channel *channel;
|
||||
};
|
||||
|
||||
struct nouveau_fence_priv {
|
||||
struct nouveau_fence base;
|
||||
int refcount;
|
||||
|
||||
struct nouveau_fence *next;
|
||||
|
||||
uint32_t sequence;
|
||||
int emitted;
|
||||
int signalled;
|
||||
};
|
||||
#define nouveau_fence(n) ((struct nouveau_fence_priv *)(n))
|
||||
|
||||
extern int
|
||||
nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **);
|
||||
|
||||
extern int
|
||||
nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **);
|
||||
|
||||
extern void
|
||||
nouveau_fence_del(struct nouveau_fence **);
|
||||
|
||||
extern void
|
||||
nouveau_fence_emit(struct nouveau_fence *);
|
||||
|
||||
extern int
|
||||
nouveau_fence_wait(struct nouveau_fence **);
|
||||
|
||||
extern void
|
||||
nouveau_fence_flush(struct nouveau_channel *);
|
||||
|
||||
struct nouveau_pushbuf {
|
||||
struct nouveau_channel *channel;
|
||||
unsigned remaining;
|
||||
uint32_t *cur;
|
||||
};
|
||||
|
||||
struct nouveau_pushbuf_priv {
|
||||
struct nouveau_pushbuf base;
|
||||
struct nouveau_pushbuf *next;
|
||||
|
||||
struct nouveau_resource *res;
|
||||
struct nouveau_fence *fence;
|
||||
};
|
||||
#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
|
||||
|
||||
extern int
|
||||
nouveau_pushbuf_init(struct nouveau_channel *);
|
||||
|
||||
extern int
|
||||
nouveau_pushbuf_flush(struct nouveau_channel *);
|
||||
|
||||
struct nouveau_channel_priv {
|
||||
struct nouveau_channel base;
|
||||
|
||||
@@ -95,6 +151,14 @@ struct nouveau_channel_priv {
|
||||
struct nouveau_bo_reloc *relocs;
|
||||
int num_relocs;
|
||||
int max_relocs;
|
||||
|
||||
struct nouveau_fence *fence_head;
|
||||
struct nouveau_fence *fence_tail;
|
||||
uint32_t fence_sequence;
|
||||
|
||||
struct nouveau_resource *pb_heap;
|
||||
struct nouveau_pushbuf *pb_head;
|
||||
struct nouveau_pushbuf *pb_tail;
|
||||
};
|
||||
#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
|
||||
|
||||
@@ -148,6 +212,8 @@ nouveau_notifier_wait_status(struct nouveau_notifier *, int id, int status,
|
||||
struct nouveau_bo_priv {
|
||||
struct nouveau_bo base;
|
||||
|
||||
struct nouveau_fence *fence;
|
||||
|
||||
struct drm_nouveau_mem_alloc drm;
|
||||
void *map;
|
||||
|
||||
@@ -203,4 +269,14 @@ nouveau_bo_emit_reloc(struct nouveau_channel *chan, void *ptr,
|
||||
extern void
|
||||
nouveau_bo_validate(struct nouveau_channel *);
|
||||
|
||||
extern int
|
||||
nouveau_resource_init(struct nouveau_resource **heap, int size);
|
||||
|
||||
extern int
|
||||
nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
|
||||
struct nouveau_resource **);
|
||||
|
||||
extern void
|
||||
nouveau_resource_free(struct nouveau_resource **);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2007 Nouveau Project
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS 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 <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nouveau_drmif.h"
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_local.h"
|
||||
|
||||
int
|
||||
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **fence)
|
||||
{
|
||||
struct nouveau_fence_priv *nvfence;
|
||||
|
||||
if (!chan || !fence || *fence)
|
||||
return -EINVAL;
|
||||
|
||||
nvfence = calloc(1, sizeof(struct nouveau_fence_priv));
|
||||
if (!nvfence)
|
||||
return -ENOMEM;
|
||||
nvfence->base.channel = chan;
|
||||
nvfence->refcount = 1;
|
||||
|
||||
*fence = &nvfence->base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence)
|
||||
{
|
||||
struct nouveau_fence_priv *nvfence;
|
||||
|
||||
if (!ref || !fence || *fence)
|
||||
return -EINVAL;
|
||||
nvfence = nouveau_fence(ref);
|
||||
nvfence->refcount++;
|
||||
|
||||
*fence = &nvfence->base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fence_del(struct nouveau_fence **fence)
|
||||
{
|
||||
struct nouveau_fence_priv *nvfence;
|
||||
|
||||
if (!fence || !*fence)
|
||||
return;
|
||||
nvfence = nouveau_fence(*fence);
|
||||
*fence = NULL;
|
||||
|
||||
if (--nvfence->refcount <= 0) {
|
||||
if (nvfence->emitted && !nvfence->signalled)
|
||||
nouveau_fence_wait((void *)&nvfence);
|
||||
free(nvfence);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
{
|
||||
struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel);
|
||||
struct nouveau_fence_priv *nvfence = nouveau_fence(fence);
|
||||
|
||||
nvfence->emitted = 1;
|
||||
nvfence->sequence = ++nvchan->fence_sequence;
|
||||
if (nvfence->sequence == 0xffffffff)
|
||||
NOUVEAU_ERR("AII wrap unhandled\n");
|
||||
|
||||
BEGIN_RING_CH(&nvchan->base, nvchan->subchannel[0].grobj, 0x50, 1);
|
||||
OUT_RING_CH (&nvchan->base, nvfence->sequence);
|
||||
|
||||
if (nvchan->fence_tail) {
|
||||
nouveau_fence(nvchan->fence_tail)->next = fence;
|
||||
} else {
|
||||
nvchan->fence_head = fence;
|
||||
}
|
||||
nvchan->fence_tail = fence;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fence_flush(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
|
||||
struct nouveau_fence_priv *nvfence = nouveau_fence(nvchan->fence_head);
|
||||
uint32_t sequence = *nvchan->ref_cnt;
|
||||
|
||||
while (nvchan->fence_head && nvfence->sequence <= sequence) {
|
||||
nvfence->signalled = 1;
|
||||
|
||||
nvchan->fence_head = nvfence->next;
|
||||
if (nvchan->fence_head == NULL)
|
||||
nvchan->fence_tail = NULL;
|
||||
nvfence = nouveau_fence(nvchan->fence_head);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fence_wait(struct nouveau_fence **fence)
|
||||
{
|
||||
struct nouveau_fence_priv *nvfence;
|
||||
|
||||
if (!fence || !*fence)
|
||||
return -EINVAL;
|
||||
nvfence = nouveau_fence(*fence);
|
||||
|
||||
if (nvfence->emitted) {
|
||||
while (!nvfence->signalled)
|
||||
nouveau_fence_flush(nvfence->base.channel);
|
||||
}
|
||||
nouveau_fence_del(fence);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -26,15 +26,16 @@
|
||||
|
||||
/* Push buffer access macros */
|
||||
#define BEGIN_RING(obj,mthd,size) do { \
|
||||
BEGIN_RING_CH(nv->channel, nv->obj, (mthd), (size)); \
|
||||
nv->pushbuf = nouveau_pipe_dma_beginp(nv->obj, (mthd), (size)); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RING(data) do { \
|
||||
OUT_RING_CH(nv->channel, (data)); \
|
||||
(*nv->pushbuf++) = (data); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RINGp(src,size) do { \
|
||||
OUT_RINGp_CH(nv->channel, (src), (size)); \
|
||||
memcpy(nv->pushbuf, (src), (size)<<2); \
|
||||
nv->pushbuf += (size); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RINGf(data) do { \
|
||||
@@ -43,18 +44,13 @@
|
||||
OUT_RING(c.u); \
|
||||
} while(0)
|
||||
|
||||
#define WAIT_RING(size) do { \
|
||||
WAIT_RING_CH(nv->channel, (size)); \
|
||||
} while(0)
|
||||
|
||||
#define FIRE_RING() do { \
|
||||
FIRE_RING_CH(nv->channel); \
|
||||
nouveau_pipe_dma_kickoff(nv->channel); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RELOC(bo,data,flags,vor,tor) do { \
|
||||
struct nouveau_channel_priv *chan = nouveau_channel(nv->channel); \
|
||||
nouveau_bo_emit_reloc(nv->channel, &chan->pushbuf[chan->dma.cur], \
|
||||
(void*)(bo), (data), (flags), (vor), (tor)); \
|
||||
nouveau_bo_emit_reloc(nv->channel, nv->pushbuf, (void*)(bo), (data), \
|
||||
(flags), (vor), (tor)); \
|
||||
OUT_RING(0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2007 Nouveau Project
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS 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 <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nouveau_drmif.h"
|
||||
#include "nouveau_dma.h"
|
||||
|
||||
int
|
||||
nouveau_pushbuf_init(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
|
||||
|
||||
if (!nvchan)
|
||||
return -EINVAL;
|
||||
|
||||
/* Everything except first 4KiB of the push buffer is managed by us */
|
||||
if (nouveau_resource_init(&nvchan->pb_heap,
|
||||
nvchan->drm.cmdbuf_size - 4096))
|
||||
return -EINVAL;
|
||||
|
||||
/* Shrink master ring to 4KiB */
|
||||
assert(nvchan->dma.cur <= (4096/4));
|
||||
nvchan->dma.max = (4096 / 4) - 2;
|
||||
nvchan->dma.free = nvchan->dma.max - nvchan->dma.cur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This would be our TTM "superioctl" */
|
||||
int
|
||||
nouveau_pushbuf_flush(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
|
||||
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
|
||||
int i, ret;
|
||||
|
||||
if (!nvpb)
|
||||
goto out_realloc;
|
||||
|
||||
if (nvpb->base.remaining == nvpb->res->size / 4)
|
||||
return 0;
|
||||
|
||||
ret = nouveau_fence_new(chan, &nvpb->fence);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Validate buffers */
|
||||
nouveau_bo_validate(chan);
|
||||
|
||||
/* Apply relocations */
|
||||
if (nvchan->num_relocs) {
|
||||
for (i = 0; i < nvchan->num_relocs; i++) {
|
||||
struct nouveau_bo_reloc *r = &nvchan->relocs[i];
|
||||
uint32_t push;
|
||||
|
||||
if (r->flags & NOUVEAU_BO_LOW) {
|
||||
push = r->bo->base.offset + r->data;
|
||||
} else
|
||||
if (r->flags & NOUVEAU_BO_HIGH) {
|
||||
push = (r->bo->base.offset + r->data) >> 32;
|
||||
} else {
|
||||
push = r->data;
|
||||
}
|
||||
|
||||
if (r->flags & NOUVEAU_BO_OR) {
|
||||
if (r->bo->base.flags & NOUVEAU_BO_VRAM)
|
||||
push |= r->vor;
|
||||
else
|
||||
push |= r->tor;
|
||||
}
|
||||
|
||||
*r->ptr = push;
|
||||
}
|
||||
|
||||
nvchan->num_relocs = 0;
|
||||
}
|
||||
|
||||
/* Emit JMP to indirect pushbuf */
|
||||
if (nvchan->dma.free < 1)
|
||||
WAIT_RING_CH(chan, 1);
|
||||
nvchan->dma.free -= 1;
|
||||
OUT_RING_CH(chan, 0x20000000 | (nvpb->res->start + 4096));
|
||||
|
||||
/* Add JMP back to master pushbuf from indirect pushbuf */
|
||||
(*nvpb->base.cur++) =
|
||||
0x20000000 | ((nvchan->dma.cur << 2) + nvchan->dma.base);
|
||||
|
||||
/* Fence */
|
||||
nouveau_fence_emit(nvpb->fence);
|
||||
|
||||
/* Kickoff */
|
||||
FIRE_RING_CH(chan);
|
||||
|
||||
/* Allocate space for next push buffer */
|
||||
out_realloc:
|
||||
nvpb = calloc(1, sizeof(struct nouveau_pushbuf_priv));
|
||||
if (!nvpb)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, NULL, &nvpb->res)) {
|
||||
struct nouveau_pushbuf_priv *e;
|
||||
int nr = 0;
|
||||
|
||||
/* Update fences */
|
||||
nouveau_fence_flush(chan);
|
||||
|
||||
/* Free any push buffers that have already been executed */
|
||||
e = nouveau_pushbuf(nvchan->pb_head);
|
||||
while (e && e->fence) {
|
||||
if (!e->fence || !nouveau_fence(e->fence)->signalled)
|
||||
break;
|
||||
nouveau_fence_del(&e->fence);
|
||||
nouveau_resource_free(&e->res);
|
||||
nr++;
|
||||
|
||||
nvchan->pb_head = e->next;
|
||||
if (nvchan->pb_head == NULL)
|
||||
nvchan->pb_tail = NULL;
|
||||
free(e);
|
||||
e = nouveau_pushbuf(nvchan->pb_head);
|
||||
}
|
||||
|
||||
/* We didn't free any buffers above. As a last resort, busy
|
||||
* wait on the oldest buffer becoming available.
|
||||
*/
|
||||
if (!nr) {
|
||||
e = nouveau_pushbuf(nvchan->pb_head);
|
||||
nouveau_fence_wait(&e->fence);
|
||||
nouveau_resource_free(&e->res);
|
||||
|
||||
nvchan->pb_head = e->next;
|
||||
if (nvchan->pb_head == NULL)
|
||||
nvchan->pb_tail = NULL;
|
||||
free(e);
|
||||
}
|
||||
|
||||
if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, nvpb,
|
||||
&nvpb->res))
|
||||
assert(0);
|
||||
}
|
||||
|
||||
nvpb->base.channel = chan;
|
||||
nvpb->base.remaining = nvpb->res->size / 4;
|
||||
nvpb->base.cur = &nvchan->pushbuf[(nvpb->res->start + 4096)/4];
|
||||
|
||||
if (nvchan->pb_tail) {
|
||||
nouveau_pushbuf(nvchan->pb_tail)->next = & nvpb->base;
|
||||
} else {
|
||||
nvchan->pb_head = &nvpb->base;
|
||||
}
|
||||
nvchan->pb_tail = &nvpb->base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "pipe/nouveau/nouveau_winsys.h"
|
||||
|
||||
static int
|
||||
int
|
||||
nouveau_resource_init(struct nouveau_resource **heap, int size)
|
||||
{
|
||||
struct nouveau_resource *r;
|
||||
@@ -20,7 +20,7 @@ nouveau_resource_init(struct nouveau_resource **heap, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
|
||||
struct nouveau_resource **res)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nouveau_resource_free(struct nouveau_resource **res)
|
||||
{
|
||||
struct nouveau_resource *r;
|
||||
@@ -108,25 +108,31 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
|
||||
grclass, grobj);
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
uint32_t *
|
||||
nouveau_pipe_dma_beginp(struct nouveau_grobj *grobj, int mthd, int size)
|
||||
{
|
||||
struct nouveau_channel_priv *chan = nouveau_channel(grobj->channel);
|
||||
struct nouveau_channel_priv *nvchan = nouveau_channel(grobj->channel);
|
||||
uint32_t *pushbuf;
|
||||
|
||||
BEGIN_RING_CH(&chan->base, grobj, mthd, size);
|
||||
pushbuf = &chan->pushbuf[chan->dma.cur];
|
||||
chan->dma.cur += size;
|
||||
#ifdef NOUVEAU_DMA_DEBUG
|
||||
chan->dma.push_free -= size;
|
||||
#endif
|
||||
if (!nvchan->pb_tail || nvchan->pb_tail->remaining < (size + 1))
|
||||
nouveau_pushbuf_flush(grobj->channel);
|
||||
|
||||
if (grobj->bound == NOUVEAU_GROBJ_UNBOUND)
|
||||
nouveau_dma_subc_bind(grobj);
|
||||
nvchan->subchannel[grobj->subc].seq = nvchan->subc_sequence++;
|
||||
|
||||
pushbuf = nvchan->pb_tail->cur;
|
||||
nvchan->pb_tail->cur += (size + 1);
|
||||
nvchan->pb_tail->remaining -= (size + 1);
|
||||
|
||||
(*pushbuf++) = ((grobj->subc << 13) | (size << 18) | mthd);
|
||||
return pushbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_pipe_dma_kickoff(struct nouveau_channel *userchan)
|
||||
void
|
||||
nouveau_pipe_dma_kickoff(struct nouveau_channel *chan)
|
||||
{
|
||||
FIRE_RING_CH(userchan);
|
||||
nouveau_pushbuf_flush(chan);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2007 Nouveau Project
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS 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.
|
||||
*/
|
||||
|
||||
#ifndef __NOUVEAU_RESOURCE_H__
|
||||
#define __NOUVEAU_RESOURCE_H__
|
||||
|
||||
struct nouveau_resource {
|
||||
struct nouveau_resource *prev;
|
||||
struct nouveau_resource *next;
|
||||
|
||||
int in_use;
|
||||
void *priv;
|
||||
|
||||
unsigned int start;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,17 +10,7 @@
|
||||
#include "pipe/nouveau/nouveau_class.h"
|
||||
#include "pipe/nouveau/nouveau_grobj.h"
|
||||
#include "pipe/nouveau/nouveau_notifier.h"
|
||||
|
||||
struct nouveau_resource {
|
||||
struct nouveau_resource *prev;
|
||||
struct nouveau_resource *next;
|
||||
|
||||
boolean in_use;
|
||||
void *priv;
|
||||
|
||||
uint start;
|
||||
uint size;
|
||||
};
|
||||
#include "pipe/nouveau/nouveau_resource.h"
|
||||
|
||||
struct nouveau_winsys {
|
||||
struct nouveau_context *nv;
|
||||
|
||||
Reference in New Issue
Block a user