void | void | ||||
nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) | nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) | ||||
{ | { | ||||
struct nouveau_channel *chan = nvc0->screen->base.channel; | |||||
struct resident *rsd; | struct resident *rsd; | ||||
struct util_dynarray *array; | struct util_dynarray *array; | ||||
unsigned ctx, i; | unsigned ctx, i; | ||||
for (i = 0; i < array->size / sizeof(struct resident); ++i) { | for (i = 0; i < array->size / sizeof(struct resident); ++i) { | ||||
rsd = util_dynarray_element(array, struct resident, i); | rsd = util_dynarray_element(array, struct resident, i); | ||||
nvc0_make_bo_resident(nvc0, rsd->bo, rsd->flags); | |||||
nouveau_bo_validate(chan, rsd->bo, rsd->flags); | |||||
} | } | ||||
} | } | ||||
nvc0_make_bo_resident(nvc0, nvc0->screen->text, NOUVEAU_BO_RD); | |||||
nvc0_make_bo_resident(nvc0, nvc0->screen->uniforms, NOUVEAU_BO_RD); | |||||
nvc0_make_bo_resident(nvc0, nvc0->screen->txc, NOUVEAU_BO_RD); | |||||
nouveau_bo_validate(chan, nvc0->screen->text, NOUVEAU_BO_RD); | |||||
nouveau_bo_validate(chan, nvc0->screen->uniforms, NOUVEAU_BO_RD); | |||||
nouveau_bo_validate(chan, nvc0->screen->txc, NOUVEAU_BO_RD); | |||||
} | } |
return (struct nvc0_surface *)ps; | return (struct nvc0_surface *)ps; | ||||
} | } | ||||
static INLINE void | |||||
nvc0_make_bo_resident(struct nvc0_context *nvc0, struct nouveau_bo *bo, | |||||
unsigned flags) | |||||
{ | |||||
nouveau_reloc_emit(nvc0->screen->base.channel, | |||||
NULL, 0, NULL, bo, 0, 0, flags, 0, 0); | |||||
} | |||||
static INLINE void | |||||
nvc0_make_buffer_resident(struct nvc0_context *nvc0, | |||||
struct nvc0_resource *res, unsigned flags) | |||||
{ | |||||
nvc0_resource_validate(res, flags); | |||||
nvc0_make_bo_resident(nvc0, res->bo, flags); | |||||
} | |||||
/* nvc0_context.c */ | /* nvc0_context.c */ | ||||
struct pipe_context *nvc0_create(struct pipe_screen *, void *); | struct pipe_context *nvc0_create(struct pipe_screen *, void *); | ||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, &screen->text); | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, &screen->text); | ||||
if (ret) | if (ret) | ||||
goto fail; | goto fail; | ||||
/* nouveau_bo_pin(dev, screen->text); */ | |||||
nouveau_resource_init(&screen->text_heap, 0, 1 << 20); | nouveau_resource_init(&screen->text_heap, 0, 1 << 20); | ||||
&screen->mp_stack_bo); | &screen->mp_stack_bo); | ||||
if (ret) | if (ret) | ||||
goto fail; | goto fail; | ||||
/* nouveau_bo_pin(dev, screen->mp_stack_bo); */ | |||||
BEGIN_RING(chan, RING_3D_(0x17bc), 3); | BEGIN_RING(chan, RING_3D_(0x17bc), 3); | ||||
OUT_RELOCh(chan, screen->mp_stack_bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR); | OUT_RELOCh(chan, screen->mp_stack_bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR); | ||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 17, &screen->txc); | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 17, &screen->txc); | ||||
if (ret) | if (ret) | ||||
goto fail; | goto fail; | ||||
/* nouveau_bo_pin(dev, screen->txc); */ | |||||
BEGIN_RING(chan, RING_3D(TIC_ADDRESS_HIGH), 3); | BEGIN_RING(chan, RING_3D(TIC_ADDRESS_HIGH), 3); | ||||
OUT_RELOCh(chan, screen->txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); | OUT_RELOCh(chan, screen->txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); | ||||
const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; | const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; | ||||
nouveau_reloc_emit(chan, NULL, 0, NULL, screen->text, 0, 0, flags, 0, 0); | |||||
nouveau_reloc_emit(chan, NULL, 0, NULL, screen->txc, 0, 0, flags, 0, 0); | |||||
nouveau_reloc_emit(chan, NULL, 0, NULL, screen->tls, 0, 0, flags, 0, 0); | |||||
nouveau_bo_validate(chan, screen->text, flags); | |||||
nouveau_bo_validate(chan, screen->txc, flags); | |||||
nouveau_bo_validate(chan, screen->tls, flags); | |||||
nouveau_bo_validate(chan, screen->mp_stack_bo, flags); | |||||
} | } | ||||
int | int |
if (flags & NOUVEAU_BO_WR) | if (flags & NOUVEAU_BO_WR) | ||||
nvc0_fence_reference(&res->fence_wr, screen->fence.current); | nvc0_fence_reference(&res->fence_wr, screen->fence.current); | ||||
nouveau_reloc_emit(screen->base.channel, | |||||
NULL, 0, NULL, res->bo, 0, 0, NOUVEAU_BO_RDWR, 0, 0); | |||||
nouveau_bo_validate(screen->base.channel, res->bo, flags); | |||||
} | } | ||||
so->pipe = *cso; | so->pipe = *cso; | ||||
SB_OUT_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); | |||||
SB_IMMED_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); | |||||
if (!cso->independent_blend_enable) { | if (!cso->independent_blend_enable) { | ||||
SB_BEGIN_3D(so, BLEND_ENABLES, 1); | SB_BEGIN_3D(so, BLEND_ENABLES, 1); | ||||
SB_DATA (so, 1); | SB_DATA (so, 1); | ||||
SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); | SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); | ||||
} else { | } else { | ||||
SB_OUT_3D (so, LOGIC_OP_ENABLE, 0); | |||||
SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0); | |||||
} | } | ||||
assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); | assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); | ||||
so->pipe = *cso; | so->pipe = *cso; | ||||
#ifndef NVC0_SCISSORS_CLIPPING | #ifndef NVC0_SCISSORS_CLIPPING | ||||
SB_OUT_3D (so, SCISSOR_ENABLE(0), cso->scissor); | |||||
SB_IMMED_3D(so, SCISSOR_ENABLE(0), cso->scissor); | |||||
#endif | #endif | ||||
SB_BEGIN_3D(so, SHADE_MODEL, 1); | SB_BEGIN_3D(so, SHADE_MODEL, 1); | ||||
SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : | SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : | ||||
NVC0_3D_SHADE_MODEL_SMOOTH); | NVC0_3D_SHADE_MODEL_SMOOTH); | ||||
SB_OUT_3D (so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); | |||||
SB_OUT_3D (so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); | |||||
SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); | |||||
SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); | |||||
SB_BEGIN_3D(so, LINE_WIDTH, 1); | SB_BEGIN_3D(so, LINE_WIDTH, 1); | ||||
SB_DATA (so, fui(cso->line_width)); | SB_DATA (so, fui(cso->line_width)); | ||||
SB_OUT_3D (so, LINE_SMOOTH_ENABLE, cso->line_smooth); | |||||
SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); | |||||
SB_BEGIN_3D(so, LINE_STIPPLE_ENABLE, 1); | SB_BEGIN_3D(so, LINE_STIPPLE_ENABLE, 1); | ||||
if (cso->line_stipple_enable) { | if (cso->line_stipple_enable) { | ||||
SB_DATA (so, 0); | SB_DATA (so, 0); | ||||
} | } | ||||
SB_OUT_3D(so, VP_POINT_SIZE_EN, cso->point_size_per_vertex); | |||||
SB_IMMED_3D(so, VP_POINT_SIZE_EN, cso->point_size_per_vertex); | |||||
if (!cso->point_size_per_vertex) { | if (!cso->point_size_per_vertex) { | ||||
SB_BEGIN_3D(so, POINT_SIZE, 1); | SB_BEGIN_3D(so, POINT_SIZE, 1); | ||||
SB_DATA (so, fui(cso->point_size)); | SB_DATA (so, fui(cso->point_size)); | ||||
} | } | ||||
SB_OUT_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); | |||||
SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); | |||||
SB_BEGIN_3D(so, POLYGON_MODE_FRONT, 1); | SB_BEGIN_3D(so, POLYGON_MODE_FRONT, 1); | ||||
SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); | SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); | ||||
SB_BEGIN_3D(so, POLYGON_MODE_BACK, 1); | SB_BEGIN_3D(so, POLYGON_MODE_BACK, 1); | ||||
SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); | SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); | ||||
SB_OUT_3D (so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); | |||||
SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); | |||||
SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); | SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); | ||||
SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); | SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); | ||||
break; | break; | ||||
} | } | ||||
SB_OUT_3D (so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); | |||||
SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); | |||||
SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); | SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); | ||||
SB_DATA (so, cso->offset_point); | SB_DATA (so, cso->offset_point); | ||||
SB_DATA (so, cso->offset_line); | SB_DATA (so, cso->offset_line); | ||||
so->pipe = *cso; | so->pipe = *cso; | ||||
SB_OUT_3D (so, DEPTH_WRITE_ENABLE, cso->depth.writemask); | |||||
SB_IMMED_3D(so, DEPTH_WRITE_ENABLE, cso->depth.writemask); | |||||
SB_BEGIN_3D(so, DEPTH_TEST_ENABLE, 1); | SB_BEGIN_3D(so, DEPTH_TEST_ENABLE, 1); | ||||
if (cso->depth.enabled) { | if (cso->depth.enabled) { | ||||
SB_DATA (so, 1); | SB_DATA (so, 1); | ||||
SB_DATA (so, cso->stencil[0].writemask); | SB_DATA (so, cso->stencil[0].writemask); | ||||
SB_DATA (so, cso->stencil[0].valuemask); | SB_DATA (so, cso->stencil[0].valuemask); | ||||
} else { | } else { | ||||
SB_OUT_3D (so, STENCIL_FRONT_ENABLE, 0); | |||||
SB_IMMED_3D(so, STENCIL_FRONT_ENABLE, 0); | |||||
} | } | ||||
if (cso->stencil[1].enabled) { | if (cso->stencil[1].enabled) { | ||||
SB_DATA (so, cso->stencil[1].writemask); | SB_DATA (so, cso->stencil[1].writemask); | ||||
SB_DATA (so, cso->stencil[1].valuemask); | SB_DATA (so, cso->stencil[1].valuemask); | ||||
} else { | } else { | ||||
SB_OUT_3D (so, STENCIL_TWO_SIDE_ENABLE, 0); | |||||
SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0); | |||||
} | } | ||||
SB_BEGIN_3D(so, ALPHA_TEST_ENABLE, 1); | SB_BEGIN_3D(so, ALPHA_TEST_ENABLE, 1); |
(so)->state[(so)->size++] = \ | (so)->state[(so)->size++] = \ | ||||
(0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) | (0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) | ||||
#define SB_OUT_3D(so, m, d) \ | |||||
#define SB_IMMED_3D(so, m, d) \ | |||||
(so)->state[(so)->size++] = \ | (so)->state[(so)->size++] = \ | ||||
(0x8 << 28) | ((d) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) | (0x8 << 28) | ((d) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) | ||||
if (nr < 9) { | if (nr < 9) { | ||||
FIRE_RING(chan); | FIRE_RING(chan); | ||||
nvc0_make_bo_resident(nvc0, dst, NOUVEAU_BO_WR); | |||||
nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR); | |||||
continue; | continue; | ||||
} | } | ||||
nr = MIN2(count, nr - 1); | nr = MIN2(count, nr - 1); |
#include "nouveau/nouveau_grobj.h" | #include "nouveau/nouveau_grobj.h" | ||||
#include "nouveau/nouveau_device.h" | #include "nouveau/nouveau_device.h" | ||||
#include "nouveau/nouveau_resource.h" | #include "nouveau/nouveau_resource.h" | ||||
#include "nouveau/nouveau_pushbuf.h" | |||||
#include "nouveau/nouveau_reloc.h" | #include "nouveau/nouveau_reloc.h" | ||||
#include "nvc0_resource.h" /* OUT_RESRC */ | #include "nvc0_resource.h" /* OUT_RESRC */ | ||||
} | } | ||||
static INLINE void | static INLINE void | ||||
WAIT_RING(struct nouveau_channel *chan, unsigned size) | |||||
nouveau_bo_validate(struct nouveau_channel *chan, | |||||
struct nouveau_bo *bo, unsigned flags) | |||||
{ | { | ||||
if (chan->cur + size > chan->end) | |||||
nouveau_pushbuf_flush(chan, size); | |||||
} | |||||
static INLINE void | |||||
OUT_RING(struct nouveau_channel *chan, uint32_t data) | |||||
{ | |||||
*(chan->cur++) = (data); | |||||
nouveau_reloc_emit(chan, NULL, 0, NULL, bo, 0, 0, flags, 0, 0); | |||||
} | } | ||||
/* incremental methods */ | /* incremental methods */ | ||||
OUT_RING (chan, (0x8 << 28) | (data << 16) | mthd); | OUT_RING (chan, (0x8 << 28) | (data << 16) | mthd); | ||||
} | } | ||||
int | |||||
nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, | |||||
unsigned wait_dwords, unsigned wait_relocs); | |||||
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); | |||||
int | |||||
nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo, | |||||
unsigned offset, unsigned length); | |||||
static INLINE int | |||||
MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs) | |||||
{ | |||||
return nouveau_pushbuf_marker_emit(chan, dwords, relocs); | |||||
} | |||||
static INLINE void | |||||
OUT_RINGf(struct nouveau_channel *chan, float data) | |||||
{ | |||||
union { uint32_t i; float f; } u; | |||||
u.f = data; | |||||
OUT_RING(chan, u.i); | |||||
} | |||||
static INLINE unsigned | |||||
AVAIL_RING(struct nouveau_channel *chan) | |||||
{ | |||||
return chan->end - chan->cur; | |||||
} | |||||
static INLINE void | |||||
OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size) | |||||
{ | |||||
memcpy(chan->cur, data, size * 4); | |||||
chan->cur += size; | |||||
} | |||||
static INLINE int | |||||
OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, | |||||
unsigned data, unsigned flags, unsigned vor, unsigned tor) | |||||
{ | |||||
return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo, | |||||
data, 0, flags, vor, tor); | |||||
} | |||||
static INLINE int | |||||
OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo, | |||||
unsigned delta, unsigned flags) | |||||
{ | |||||
return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); | |||||
} | |||||
static INLINE int | |||||
OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo, | |||||
unsigned delta, unsigned flags) | |||||
{ | |||||
return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0); | |||||
} | |||||
static INLINE int | static INLINE int | ||||
OUT_RESRCh(struct nouveau_channel *chan, struct nvc0_resource *res, | OUT_RESRCh(struct nouveau_channel *chan, struct nvc0_resource *res, | ||||
unsigned delta, unsigned flags) | unsigned delta, unsigned flags) | ||||
return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); | return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); | ||||
} | } | ||||
static INLINE void | |||||
FIRE_RING(struct nouveau_channel *chan) | |||||
{ | |||||
nouveau_pushbuf_flush(chan, 0); | |||||
} | |||||
static INLINE void | static INLINE void | ||||
BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned s) | BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned s) | ||||
{ | { |