|
|
@@ -22,52 +22,70 @@ nv50_format(enum pipe_format format) |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
nv50_surface_copy_prep(struct nouveau_context *nv, |
|
|
|
struct pipe_surface *dst, struct pipe_surface *src) |
|
|
|
nv50_surface_set(struct nouveau_context *nv, struct pipe_surface *surf, int dst) |
|
|
|
{ |
|
|
|
struct nouveau_channel *chan = nv->nvc->channel; |
|
|
|
struct nouveau_grobj *eng2d = nv->nvc->Nv2D; |
|
|
|
int surf_format; |
|
|
|
|
|
|
|
assert(src->format == dst->format); |
|
|
|
struct nouveau_bo *bo = nouveau_buffer(surf->buffer)->bo; |
|
|
|
int surf_format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT; |
|
|
|
int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); |
|
|
|
|
|
|
|
surf_format = nv50_format(surf->format); |
|
|
|
if (surf_format < 0) |
|
|
|
return 1; |
|
|
|
|
|
|
|
if (!nouveau_bo(bo)->tiled) { |
|
|
|
BEGIN_RING(chan, eng2d, mthd, 2); |
|
|
|
OUT_RING (chan, surf_format); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
BEGIN_RING(chan, eng2d, mthd + 0x14, 5); |
|
|
|
OUT_RING (chan, surf->stride); |
|
|
|
OUT_RING (chan, surf->width); |
|
|
|
OUT_RING (chan, surf->height); |
|
|
|
OUT_RELOCh(chan, bo, surf->offset, flags); |
|
|
|
OUT_RELOCl(chan, bo, surf->offset, flags); |
|
|
|
} else { |
|
|
|
BEGIN_RING(chan, eng2d, mthd, 5); |
|
|
|
OUT_RING (chan, surf_format); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
BEGIN_RING(chan, eng2d, mthd + 0x18, 4); |
|
|
|
OUT_RING (chan, surf->width); |
|
|
|
OUT_RING (chan, surf->height); |
|
|
|
OUT_RELOCh(chan, bo, surf->offset, flags); |
|
|
|
OUT_RELOCl(chan, bo, surf->offset, flags); |
|
|
|
} |
|
|
|
|
|
|
|
#if 0 |
|
|
|
if (dst) { |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, surf->width); |
|
|
|
OUT_RING (chan, surf->height); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
surf_format = nv50_format(dst->format); |
|
|
|
assert(surf_format >= 0); |
|
|
|
static int |
|
|
|
nv50_surface_copy_prep(struct nouveau_context *nv, |
|
|
|
struct pipe_surface *dst, struct pipe_surface *src) |
|
|
|
{ |
|
|
|
int ret; |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DMA_IN_MEMORY0, 2); |
|
|
|
OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); |
|
|
|
OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
assert(src->format == dst->format); |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2); |
|
|
|
OUT_RING (chan, surf_format); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 5); |
|
|
|
OUT_RING (chan, dst->stride); |
|
|
|
OUT_RING (chan, dst->width); |
|
|
|
OUT_RING (chan, dst->height); |
|
|
|
OUT_RELOCh(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, dst->width); |
|
|
|
OUT_RING (chan, dst->height); |
|
|
|
ret = nv50_surface_set(nv, dst, 1); |
|
|
|
if (ret) |
|
|
|
return ret; |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_SRC_FORMAT, 2); |
|
|
|
OUT_RING (chan, surf_format); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_SRC_PITCH, 5); |
|
|
|
OUT_RING (chan, src->stride); |
|
|
|
OUT_RING (chan, src->width); |
|
|
|
OUT_RING (chan, src->height); |
|
|
|
OUT_RELOCh(chan, nouveau_buffer(src->buffer)->bo, src->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); |
|
|
|
OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); |
|
|
|
ret = nv50_surface_set(nv, src, 0); |
|
|
|
if (ret) |
|
|
|
return ret; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
@@ -79,17 +97,19 @@ nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy, |
|
|
|
struct nouveau_channel *chan = nv->nvc->channel; |
|
|
|
struct nouveau_grobj *eng2d = nv->nvc->Nv2D; |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, 0x0110, 1); |
|
|
|
BEGIN_RING(chan, eng2d, 0x088c, 1); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4); |
|
|
|
OUT_RING (chan, dx); |
|
|
|
OUT_RING (chan, dy); |
|
|
|
OUT_RING (chan, w); |
|
|
|
OUT_RING (chan, h); |
|
|
|
BEGIN_RING(chan, eng2d, 0x08c0, 4); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
BEGIN_RING(chan, eng2d, 0x08d0, 4); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, sx); |
|
|
|
OUT_RING (chan, 0); |
|
|
@@ -109,35 +129,15 @@ nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst, |
|
|
|
{ |
|
|
|
struct nouveau_channel *chan = nv->nvc->channel; |
|
|
|
struct nouveau_grobj *eng2d = nv->nvc->Nv2D; |
|
|
|
int surf_format, rect_format; |
|
|
|
|
|
|
|
surf_format = nv50_format(dst->format); |
|
|
|
if (surf_format < 0) |
|
|
|
return 1; |
|
|
|
int rect_format, ret; |
|
|
|
|
|
|
|
rect_format = nv50_format(dst->format); |
|
|
|
if (rect_format < 0) |
|
|
|
return 1; |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DMA_IN_MEMORY1, 1); |
|
|
|
OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2); |
|
|
|
OUT_RING (chan, surf_format); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 5); |
|
|
|
OUT_RING (chan, dst->stride); |
|
|
|
OUT_RING (chan, dst->width); |
|
|
|
OUT_RING (chan, dst->height); |
|
|
|
OUT_RELOCh(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, |
|
|
|
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
OUT_RING (chan, dst->width); |
|
|
|
OUT_RING (chan, dst->height); |
|
|
|
ret = nv50_surface_set(nv, dst, 1); |
|
|
|
if (ret) |
|
|
|
return ret; |
|
|
|
|
|
|
|
BEGIN_RING(chan, eng2d, 0x0580, 3); |
|
|
|
OUT_RING (chan, 4); |
|
|
@@ -151,27 +151,33 @@ nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst, |
|
|
|
OUT_RING (chan, dy + h); |
|
|
|
|
|
|
|
FIRE_RING(chan); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
nouveau_surface_channel_create_nv50(struct nouveau_channel_context *nvc) |
|
|
|
{ |
|
|
|
struct nouveau_channel *chan = nvc->channel; |
|
|
|
struct nouveau_grobj *eng2d = NULL; |
|
|
|
int ret; |
|
|
|
|
|
|
|
ret = nouveau_grobj_alloc(nvc->channel, nvc->next_handle++, NV50_2D, |
|
|
|
&nvc->Nv2D); |
|
|
|
ret = nouveau_grobj_alloc(chan, nvc->next_handle++, NV50_2D, &eng2d); |
|
|
|
if (ret) |
|
|
|
return ret; |
|
|
|
BIND_RING (nvc->channel, nvc->Nv2D, nvc->next_subchannel++); |
|
|
|
BEGIN_RING(nvc->channel, nvc->Nv2D, NV50_2D_DMA_NOTIFY, 1); |
|
|
|
OUT_RING (nvc->channel, nvc->sync_notifier->handle); |
|
|
|
BEGIN_RING(nvc->channel, nvc->Nv2D, NV50_2D_DMA_IN_MEMORY0, 2); |
|
|
|
OUT_RING (nvc->channel, nvc->channel->vram->handle); |
|
|
|
OUT_RING (nvc->channel, nvc->channel->vram->handle); |
|
|
|
BEGIN_RING(nvc->channel, nvc->Nv2D, NV50_2D_OPERATION, 1); |
|
|
|
OUT_RING (nvc->channel, NV50_2D_OPERATION_SRCCOPY); |
|
|
|
nvc->Nv2D = eng2d; |
|
|
|
|
|
|
|
BIND_RING (chan, eng2d, nvc->next_subchannel++); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_DMA_NOTIFY, 4); |
|
|
|
OUT_RING (chan, nvc->sync_notifier->handle); |
|
|
|
OUT_RING (chan, chan->vram->handle); |
|
|
|
OUT_RING (chan, chan->vram->handle); |
|
|
|
OUT_RING (chan, chan->vram->handle); |
|
|
|
BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1); |
|
|
|
OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY); |
|
|
|
BEGIN_RING(chan, eng2d, 0x0290, 1); |
|
|
|
OUT_RING (chan, 0); |
|
|
|
BEGIN_RING(chan, eng2d, 0x0888, 1); |
|
|
|
OUT_RING (chan, 1); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |