nouveau: turn pushbuf macros into inline functions

This commit is contained in:
Ben Skeggs 2008-03-02 14:09:57 +11:00
parent 132def0c41
commit 0a12e4587c
7 changed files with 404 additions and 267 deletions

View file

@ -21,6 +21,75 @@ static const struct dri_debug_control debug_control[] = {
int __nouveau_debug = 0;
#endif
static void
nouveau_channel_context_destroy(struct nouveau_channel_context *nvc)
{
nouveau_grobj_free(&nvc->NvNull);
nouveau_grobj_free(&nvc->NvCtxSurf2D);
nouveau_grobj_free(&nvc->NvImageBlit);
nouveau_grobj_free(&nvc->NvGdiRect);
nouveau_grobj_free(&nvc->NvM2MF);
nouveau_grobj_free(&nvc->Nv2D);
nouveau_notifier_free(&nvc->sync_notifier);
nouveau_channel_free(&nvc->channel);
FREE(nvc);
}
static struct nouveau_channel_context *
nouveau_channel_context_create(struct nouveau_device *nvdev, unsigned chipset)
{
struct nouveau_channel_context *nvc;
int ret;
nvc = CALLOC_STRUCT(nouveau_channel_context);
if (!nvc)
return NULL;
nvc->chipset = chipset;
if ((ret = nouveau_channel_alloc(nvdev, 0x8003d001, 0x8003d002,
&nvc->channel))) {
NOUVEAU_ERR("Error creating GPU channel: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
if ((ret = nouveau_grobj_alloc(nvc->channel, 0x00000000, 0x30,
&nvc->NvNull))) {
NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
nvc->next_handle = 0x80000000;
if ((ret = nouveau_notifier_alloc(nvc->channel, nvc->next_handle++, 1,
&nvc->sync_notifier))) {
NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
switch (chipset) {
case 0x50:
case 0x80:
ret = nouveau_surface_channel_create_nv50(nvc);
break;
default:
ret = nouveau_surface_channel_create_nv04(nvc);
break;
}
if (ret) {
NOUVEAU_ERR("Error initialising surface objects: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
return nvc;
}
GLboolean
nouveau_context_create(const __GLcontextModes *glVis,
__DRIcontextPrivate *driContextPriv,
@ -45,13 +114,6 @@ nouveau_context_create(const __GLcontextModes *glVis,
return GL_FALSE;
}
if ((ret = nouveau_channel_alloc(nv_screen->device,
0x8003d001, 0x8003d002,
&nv->channel))) {
NOUVEAU_ERR("Error creating GPU channel: %d\n", ret);
return GL_FALSE;
}
driContextPriv->driverPrivate = (void *)nv;
nv->nv_screen = nv_screen;
nv->dri_screen = driScrnPriv;
@ -101,16 +163,9 @@ nouveau_context_create(const __GLcontextModes *glVis,
nv->frontbuffer = fb_surf;
}
if ((ret = nouveau_grobj_alloc(nv->channel, 0x00000000, 0x30,
&nv->NvNull))) {
NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
return GL_FALSE;
}
nv->next_handle = 0x80000000;
if ((ret = nouveau_notifier_alloc(nv->channel, nv->next_handle++, 1,
&nv->sync_notifier))) {
NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
nv->nvc = nouveau_channel_context_create(&nvdev->base, nv->chipset);
if (!nv->nvc) {
NOUVEAU_ERR("Failed initialising GPU channel context\n");
return GL_FALSE;
}
@ -152,9 +207,7 @@ nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
st_flush(nv->st, PIPE_FLUSH_WAIT);
st_destroy_context(nv->st);
nouveau_grobj_free(&nv->NvCtxSurf2D);
nouveau_grobj_free(&nv->NvImageBlit);
nouveau_channel_free(&nv->channel);
nouveau_channel_context_destroy(nv->nvc);
free(nv);
}

View file

@ -13,6 +13,25 @@ struct nouveau_framebuffer {
struct st_framebuffer *stfb;
};
struct nouveau_channel_context {
unsigned chipset;
struct nouveau_channel *channel;
struct nouveau_notifier *sync_notifier;
struct nouveau_grobj *NvNull;
struct nouveau_grobj *NvCtxSurf2D;
struct nouveau_grobj *NvImageBlit;
struct nouveau_grobj *NvGdiRect;
struct nouveau_grobj *NvM2MF;
struct nouveau_grobj *Nv2D;
uint32_t next_handle;
uint32_t next_subchannel;
uint32_t next_sequence;
};
struct nouveau_context {
struct st_context *st;
@ -31,17 +50,7 @@ struct nouveau_context {
struct pipe_surface *frontbuffer;
/* Hardware context */
struct nouveau_channel *channel;
struct nouveau_notifier *sync_notifier;
struct nouveau_grobj *NvNull;
struct nouveau_grobj *NvCtxSurf2D;
struct nouveau_grobj *NvImageBlit;
struct nouveau_grobj *NvGdiRect;
struct nouveau_grobj *NvM2MF;
struct nouveau_grobj *Nv2D;
uint32_t next_handle;
uint32_t next_subchannel;
uint32_t next_sequence;
struct nouveau_channel_context *nvc;
/* pipe_surface accel */
struct pipe_surface *surf_src, *surf_dst;
@ -80,6 +89,10 @@ extern int __nouveau_debug;
extern void LOCK_HARDWARE(struct nouveau_context *);
extern void UNLOCK_HARDWARE(struct nouveau_context *);
extern int
nouveau_surface_channel_create_nv04(struct nouveau_channel_context *);
extern int
nouveau_surface_channel_create_nv50(struct nouveau_channel_context *);
extern int nouveau_surface_init_nv04(struct nouveau_context *);
extern int nouveau_surface_init_nv50(struct nouveau_context *);

View file

@ -1,8 +1,11 @@
#ifndef __NOUVEAU_LOCAL_H__
#define __NOUVEAU_LOCAL_H__
#include "pipe/p_compiler.h"
#include <stdio.h>
struct pipe_buffer;
/* Debug output */
#define NOUVEAU_MSG(fmt, args...) do { \
fprintf(stdout, "nouveau: "fmt, ##args); \
@ -24,66 +27,90 @@
#define NOUVEAU_DMA_TIMEOUT 2000
/* Push buffer access macros */
#define OUT_RING(data) do { \
(*nv->channel->pushbuf->cur++) = (data); \
} while(0)
static INLINE void
OUT_RING(struct nouveau_channel *chan, unsigned data)
{
*(chan->pushbuf->cur++) = (data);
}
#define OUT_RINGp(src,size) do { \
memcpy(nv->channel->pushbuf->cur, (src), (size)<<2); \
nv->channel->pushbuf->cur += (size); \
} while(0)
static INLINE void
OUT_RINGp(struct nouveau_channel *chan, uint32_t *data, unsigned size)
{
memcpy(chan->pushbuf->cur, data, size * 4);
chan->pushbuf->cur += size;
}
#define OUT_RINGf(data) do { \
union { float v; uint32_t u; } c; \
c.v = (data); \
OUT_RING(c.u); \
} while(0)
static INLINE void
OUT_RINGf(struct nouveau_channel *chan, float f)
{
union { uint32_t i; float f; } c;
c.f = f;
OUT_RING(chan, c.i);
}
#define FIRE_RING() do { \
nouveau_pushbuf_flush(nv->channel, 0); \
} while(0)
static INLINE void
BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
unsigned mthd, unsigned size)
{
if (chan->pushbuf->remaining < (size + 1))
nouveau_pushbuf_flush(chan, (size + 1));
OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
chan->pushbuf->remaining -= (size + 1);
}
#define BEGIN_RING_GR(obj,mthd,size) do { \
if (nv->channel->pushbuf->remaining < ((size) + 1)) \
nouveau_pushbuf_flush(nv->channel, ((size) + 1)); \
OUT_RING(((obj)->subc << 13) | ((size) << 18) | (mthd)); \
nv->channel->pushbuf->remaining -= ((size) + 1); \
} while(0)
static INLINE void
FIRE_RING(struct nouveau_channel *chan)
{
nouveau_pushbuf_flush(chan, 0);
}
#define BEGIN_RING(obj,mthd,size) do { \
BEGIN_RING_GR(nv->obj, (mthd), (size)); \
} while(0)
static INLINE void
BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned subc)
{
gr->subc = subc;
BEGIN_RING(chan, gr, 0x0000, 1);
OUT_RING (chan, gr->handle);
}
#define BIND_RING(o,s) do { \
nv->o->subc = (s); \
BEGIN_RING(o, 0x0000, 1); \
OUT_RING (nv->o->handle); \
} while(0)
#define OUT_RELOC(buf,data,flags,vor,tor) do { \
nouveau_pipe_emit_reloc(nv->channel, nv->channel->pushbuf->cur++, \
buf, (data), (flags), (vor), (tor)); \
} while(0)
static INLINE void
OUT_RELOC(struct nouveau_channel *chan, struct pipe_buffer *buf,
unsigned data, unsigned flags, unsigned vor, unsigned tor)
{
nouveau_pipe_emit_reloc(chan, chan->pushbuf->cur++, buf,
data, flags, vor, tor);
}
/* Raw data + flags depending on FB/TT buffer */
#define OUT_RELOCd(bo,data,flags,vor,tor) do { \
OUT_RELOC((bo), (data), (flags) | NOUVEAU_BO_OR, (vor), (tor)); \
} while(0)
static INLINE void
OUT_RELOCd(struct nouveau_channel *chan, struct pipe_buffer *buf,
unsigned data, unsigned flags, unsigned vor, unsigned tor)
{
OUT_RELOC(chan, buf, data, flags | NOUVEAU_BO_OR, vor, tor);
}
/* FB/TT object handle */
#define OUT_RELOCo(bo,flags) do { \
OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR, \
nv->channel->vram->handle, nv->channel->gart->handle); \
} while(0)
static INLINE void
OUT_RELOCo(struct nouveau_channel *chan, struct pipe_buffer *buf,
unsigned flags)
{
OUT_RELOC(chan, buf, 0, flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
}
/* Low 32-bits of offset */
#define OUT_RELOCl(bo,delta,flags) do { \
OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_LOW, 0, 0); \
} while(0)
static INLINE void
OUT_RELOCl(struct nouveau_channel *chan, struct pipe_buffer *buf,
unsigned delta, unsigned flags)
{
OUT_RELOC(chan, buf, delta, flags | NOUVEAU_BO_LOW, 0, 0);
}
/* High 32-bits of offset */
#define OUT_RELOCh(bo,delta,flags) do { \
OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_HIGH, 0, 0); \
} while(0)
static INLINE void
OUT_RELOCh(struct nouveau_channel *chan, struct pipe_buffer *buf,
unsigned delta, unsigned flags)
{
OUT_RELOC(chan, buf, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
}
#endif

View file

@ -42,7 +42,7 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
nv->surface_copy(nv, dx, dy, sx, sy, w, h);
}
FIRE_RING();
FIRE_RING(nv->nvc->channel);
UNLOCK_HARDWARE(nv);
if (nv->last_stamp != dPriv->lastStamp) {

View file

@ -11,7 +11,7 @@ nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count,
{
struct nouveau_context *nv = nvws->nv;
return nouveau_notifier_alloc(nv->channel, nv->next_handle++,
return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++,
count, notify);
}
@ -20,17 +20,16 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
struct nouveau_grobj **grobj)
{
struct nouveau_context *nv = nvws->nv;
struct nouveau_channel *chan = nv->nvc->channel;
int ret;
ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++,
ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++,
grclass, grobj);
if (ret)
return ret;
(*grobj)->subc = nv->next_subchannel++;
assert((*grobj)->subc <= 7);
BEGIN_RING_GR(*grobj, 0x0000, 1);
OUT_RING ((*grobj)->handle);
assert(nv->nvc->next_subchannel < 7);
BIND_RING(chan, *grobj, nv->nvc->next_subchannel++);
return 0;
}
@ -103,7 +102,7 @@ nouveau_pipe_create(struct nouveau_context *nv)
}
nvws->nv = nv;
nvws->channel = nv->channel;
nvws->channel = nv->nvc->channel;
nvws->res_init = nouveau_resource_init;
nvws->res_alloc = nouveau_resource_alloc;

View file

@ -30,6 +30,7 @@ static void
nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct pipe_surface *dst = nv->surf_dst;
struct pipe_surface *src = nv->surf_src;
unsigned dst_offset, src_offset;
@ -40,17 +41,18 @@ nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
while (h) {
int count = (h > 2047) ? 2047 : h;
BEGIN_RING(NvM2MF, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(src->buffer, src_offset, NOUVEAU_BO_VRAM |
BEGIN_RING(chan, nv->nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(chan, src->buffer, src_offset, NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART | NOUVEAU_BO_RD);
OUT_RELOCl(dst->buffer, dst_offset, NOUVEAU_BO_VRAM |
OUT_RELOCl(chan, dst->buffer, dst_offset, NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART | NOUVEAU_BO_WR);
OUT_RING (src->pitch * src->cpp);
OUT_RING (dst->pitch * dst->cpp);
OUT_RING (w * src->cpp);
OUT_RING (count);
OUT_RING (0x0101);
OUT_RING (0);
OUT_RING (chan, src->pitch * src->cpp);
OUT_RING (chan, dst->pitch * dst->cpp);
OUT_RING (chan, w * src->cpp);
OUT_RING (chan, count);
OUT_RING (chan, 0x0101);
OUT_RING (chan, 0);
h -= count;
src_offset += src->pitch * src->cpp * count;
@ -62,16 +64,19 @@ static void
nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
BEGIN_RING(NvImageBlit, 0x0300, 3);
OUT_RING ((sy << 16) | sx);
OUT_RING ((dy << 16) | dx);
OUT_RING (( h << 16) | w);
struct nouveau_channel *chan = nv->nvc->channel;
BEGIN_RING(chan, nv->nvc->NvImageBlit, 0x0300, 3);
OUT_RING (chan, (sy << 16) | sx);
OUT_RING (chan, (dy << 16) | dx);
OUT_RING (chan, ( h << 16) | w);
}
static int
nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
struct pipe_surface *src)
{
struct nouveau_channel *chan = nv->nvc->channel;
int format;
if (src->cpp != dst->cpp)
@ -81,12 +86,12 @@ nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
* to NV_MEMORY_TO_MEMORY_FORMAT in this case.
*/
if ((src->offset & 63) || (dst->offset & 63)) {
BEGIN_RING(NvM2MF,
BEGIN_RING(nv->nvc->channel, nv->nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
OUT_RELOCo(src->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
NOUVEAU_BO_WR);
OUT_RELOCo(chan, src->buffer, NOUVEAU_BO_GART |
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst->buffer, NOUVEAU_BO_GART |
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
nv->surface_copy = nv04_surface_copy_m2mf;
nv->surf_dst = dst;
@ -101,15 +106,20 @@ nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
}
nv->surface_copy = nv04_surface_copy_blit;
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (format);
OUT_RING (((dst->pitch * dst->cpp) << 16) | (src->pitch * src->cpp));
OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, format);
OUT_RING (chan, ((dst->pitch * dst->cpp) << 16) |
(src->pitch * src->cpp));
OUT_RELOCl(chan, src->buffer, src->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, dst->buffer, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
return 0;
}
@ -117,7 +127,7 @@ nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
static void
nv04_surface_copy_done(struct nouveau_context *nv)
{
FIRE_RING();
FIRE_RING(nv->nvc->channel);
}
static int
@ -125,6 +135,9 @@ nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
unsigned dx, unsigned dy, unsigned w, unsigned h,
unsigned value)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *surf2d = nv->nvc->NvCtxSurf2D;
struct nouveau_grobj *rect = nv->nvc->NvGdiRect;
int cs2d_format, gdirect_format;
if ((cs2d_format = nv04_surface_format(dst->cpp)) < 0) {
@ -137,86 +150,99 @@ nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
return 1;
}
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (cs2d_format);
OUT_RING (((dst->pitch * dst->cpp) << 16) | (dst->pitch * dst->cpp));
OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCo(chan, dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, cs2d_format);
OUT_RING (chan, ((dst->pitch * dst->cpp) << 16) |
(dst->pitch * dst->cpp));
OUT_RELOCl(chan, dst->buffer, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, dst->buffer, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING (gdirect_format);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
OUT_RING (value);
BEGIN_RING(NvGdiRect,
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING (chan, gdirect_format);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
OUT_RING (chan, value);
BEGIN_RING(chan, rect,
NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
OUT_RING ((dx << 16) | dy);
OUT_RING (( w << 16) | h);
OUT_RING (chan, (dx << 16) | dy);
OUT_RING (chan, ( w << 16) | h);
FIRE_RING(chan);
return 0;
}
int
nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
{
struct nouveau_channel *chan = nvc->channel;
unsigned class;
int ret;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, 0x39,
&nvc->NvM2MF))) {
NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
return 1;
}
BIND_RING (chan, nvc->NvM2MF, nvc->next_subchannel++);
BEGIN_RING(chan, nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
class = nvc->chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
NV10_CONTEXT_SURFACES_2D;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvCtxSurf2D))) {
NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
return 1;
}
BIND_RING (chan, nvc->NvCtxSurf2D, nvc->next_subchannel++);
BEGIN_RING(chan, nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RING (chan, nvc->channel->vram->handle);
OUT_RING (chan, nvc->channel->vram->handle);
class = nvc->chipset < 0x10 ? NV04_IMAGE_BLIT :
NV12_IMAGE_BLIT;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvImageBlit))) {
NOUVEAU_ERR("Error creating blit object: %d\n", ret);
return 1;
}
BIND_RING (chan, nvc->NvImageBlit, nvc->next_subchannel++);
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
OUT_RING (chan, nvc->NvCtxSurf2D->handle);
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
class = NV04_GDI_RECTANGLE_TEXT;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvGdiRect))) {
NOUVEAU_ERR("Error creating rect object: %d\n", ret);
return 1;
}
BIND_RING (chan, nvc->NvGdiRect, nvc->next_subchannel++);
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
OUT_RING (chan, nvc->NvCtxSurf2D->handle);
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
BEGIN_RING(chan, nvc->NvGdiRect,
NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
FIRE_RING();
return 0;
}
int
nouveau_surface_init_nv04(struct nouveau_context *nv)
{
unsigned class;
int ret;
if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, 0x39,
&nv->NvM2MF))) {
NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
return 1;
}
BIND_RING (NvM2MF, nv->next_subchannel++);
BEGIN_RING(NvM2MF, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
class = nv->chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
NV10_CONTEXT_SURFACES_2D;
if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
&nv->NvCtxSurf2D))) {
NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
return 1;
}
BIND_RING (NvCtxSurf2D, nv->next_subchannel++);
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RING (nv->channel->vram->handle);
OUT_RING (nv->channel->vram->handle);
class = nv->chipset < 0x10 ? NV04_IMAGE_BLIT :
NV12_IMAGE_BLIT;
if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
&nv->NvImageBlit))) {
NOUVEAU_ERR("Error creating blit object: %d\n", ret);
return 1;
}
BIND_RING (NvImageBlit, nv->next_subchannel++);
BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
OUT_RING (nv->NvCtxSurf2D->handle);
BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
OUT_RING (NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
class = NV04_GDI_RECTANGLE_TEXT;
if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
&nv->NvGdiRect))) {
NOUVEAU_ERR("Error creating rect object: %d\n", ret);
return 1;
}
BIND_RING (NvGdiRect, nv->next_subchannel++);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
OUT_RING (nv->NvCtxSurf2D->handle);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
OUT_RING (NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
OUT_RING (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
nv->surface_copy_prep = nv04_surface_copy_prep;
nv->surface_copy = nv04_surface_copy_blit;
nv->surface_copy_done = nv04_surface_copy_done;

View file

@ -19,6 +19,8 @@ static int
nv50_surface_copy_prep(struct nouveau_context *nv,
struct pipe_surface *dst, struct pipe_surface *src)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
int surf_format;
assert(src->cpp == dst->cpp);
@ -26,34 +28,38 @@ nv50_surface_copy_prep(struct nouveau_context *nv,
surf_format = nv50_format(dst->cpp);
assert(surf_format >= 0);
BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, eng2d, NV50_2D_DMA_IN_MEMORY0, 2);
OUT_RELOCo(chan, src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
OUT_RING (surf_format);
OUT_RING (1);
BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
OUT_RING (dst->pitch * dst->cpp);
OUT_RING (dst->pitch);
OUT_RING (dst->height);
OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
OUT_RING (0);
OUT_RING (0);
OUT_RING (dst->pitch);
OUT_RING (dst->height);
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->pitch * dst->cpp);
OUT_RING (chan, dst->pitch);
OUT_RING (chan, dst->height);
OUT_RELOCh(chan, dst->buffer, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, dst->buffer, 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->pitch);
OUT_RING (chan, dst->height);
BEGIN_RING(Nv2D, NV50_2D_SRC_FORMAT, 2);
OUT_RING (surf_format);
OUT_RING (1);
BEGIN_RING(Nv2D, NV50_2D_SRC_PITCH, 5);
OUT_RING (src->pitch * src->cpp);
OUT_RING (src->pitch);
OUT_RING (src->height);
OUT_RELOCh(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
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->pitch * src->cpp);
OUT_RING (chan, src->pitch);
OUT_RING (chan, src->height);
OUT_RELOCh(chan, src->buffer, src->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, src->buffer, src->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
return 0;
}
@ -62,27 +68,30 @@ static void
nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
BEGIN_RING(Nv2D, 0x0110, 1);
OUT_RING (0);
BEGIN_RING(Nv2D, NV50_2D_BLIT_DST_X, 12);
OUT_RING (dx);
OUT_RING (dy);
OUT_RING (w);
OUT_RING (h);
OUT_RING (0);
OUT_RING (1);
OUT_RING (0);
OUT_RING (1);
OUT_RING (0);
OUT_RING (sx);
OUT_RING (0);
OUT_RING (sy);
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
BEGIN_RING(chan, eng2d, 0x0110, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
OUT_RING (chan, dx);
OUT_RING (chan, dy);
OUT_RING (chan, w);
OUT_RING (chan, h);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
OUT_RING (chan, sx);
OUT_RING (chan, 0);
OUT_RING (chan, sy);
}
static void
nv50_surface_copy_done(struct nouveau_context *nv)
{
FIRE_RING();
FIRE_RING(nv->nvc->channel);
}
static int
@ -90,6 +99,8 @@ nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
unsigned dx, unsigned dy, unsigned w, unsigned h,
unsigned value)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
int surf_format, rect_format;
surf_format = nv50_format(dst->cpp);
@ -100,35 +111,58 @@ nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
if (rect_format < 0)
return 1;
BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY1, 1);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
OUT_RING (surf_format);
OUT_RING (1);
BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
OUT_RING (dst->pitch * dst->cpp);
OUT_RING (dst->pitch);
OUT_RING (dst->height);
OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
OUT_RING (0);
OUT_RING (0);
OUT_RING (dst->pitch);
OUT_RING (dst->height);
BEGIN_RING(chan, eng2d, NV50_2D_DMA_IN_MEMORY1, 1);
OUT_RELOCo(chan, dst->buffer, 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->pitch * dst->cpp);
OUT_RING (chan, dst->pitch);
OUT_RING (chan, dst->height);
OUT_RELOCh(chan, dst->buffer, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, dst->buffer, 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->pitch);
OUT_RING (chan, dst->height);
BEGIN_RING(Nv2D, 0x0580, 3);
OUT_RING (4);
OUT_RING (rect_format);
OUT_RING (value);
BEGIN_RING(chan, eng2d, 0x0580, 3);
OUT_RING (chan, 4);
OUT_RING (chan, rect_format);
OUT_RING (chan, value);
BEGIN_RING(Nv2D, NV50_2D_RECT_X1, 4);
OUT_RING (dx);
OUT_RING (dy);
OUT_RING (dx + w);
OUT_RING (dy + h);
BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
OUT_RING (chan, dx);
OUT_RING (chan, dy);
OUT_RING (chan, dx + w);
OUT_RING (chan, dy + h);
FIRE_RING();
FIRE_RING(chan);
return 0;
}
int
nouveau_surface_channel_create_nv50(struct nouveau_channel_context *nvc)
{
int ret;
ret = nouveau_grobj_alloc(nvc->channel, nvc->next_handle++, NV50_2D,
&nvc->Nv2D);
if (ret)
return ret;
BIND_RING (nvc->channel, nvc->Nv2D, 0);
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);
return 0;
}
@ -136,21 +170,6 @@ nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
int
nouveau_surface_init_nv50(struct nouveau_context *nv)
{
int ret;
ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, NV50_2D,
&nv->Nv2D);
if (ret)
return ret;
BIND_RING (Nv2D, 0);
BEGIN_RING(Nv2D, NV50_2D_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
OUT_RING (nv->channel->vram->handle);
OUT_RING (nv->channel->vram->handle);
BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
OUT_RING (NV50_2D_OPERATION_SRCCOPY);
nv->surface_copy_prep = nv50_surface_copy_prep;
nv->surface_copy = nv50_surface_copy;
nv->surface_copy_done = nv50_surface_copy_done;