#include "nv50_screen.h"
#include "nv50_program.h"
#include "nv50_resource.h"
+#include "nv50_transfer.h"
#include "nouveau/nouveau_context.h"
#include "nouveau/nv_object.xml.h"
/* nv50_transfer.c */
void
+nv50_m2mf_transfer_rect(struct pipe_screen *pscreen,
+ const struct nv50_m2mf_rect *dst,
+ const struct nv50_m2mf_rect *src,
+ uint32_t nblocksx, uint32_t nblocksy);
+void
nv50_sifc_linear_u8(struct nouveau_context *pipe,
struct nouveau_bo *dst, unsigned offset, unsigned domain,
unsigned size, void *data);
#include "nv50_context.h"
#include "nv50_resource.h"
-#include "nv50_transfer.h"
static INLINE uint32_t
nv50_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
struct pipe_resource *,
const struct pipe_surface *templ);
+struct pipe_transfer *
+nv50_miptree_transfer_new(struct pipe_context *pcontext,
+ struct pipe_resource *pt,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box);
+void
+nv50_miptree_transfer_del(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+void *
+nv50_miptree_transfer_map(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+void
+nv50_miptree_transfer_unmap(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+
#endif /* __NVC0_RESOURCE_H__ */
struct nv50_surface *
unsigned sample_count,
unsigned bindings)
{
- if (sample_count > 1)
+ if (sample_count > 2 && sample_count != 4 && sample_count != 8)
+ return FALSE;
+ if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128)
return FALSE;
if (!util_format_is_supported(format, bindings))
struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj);
int i;
boolean emit_common_func = cso->rt[0].blend_enable;
+ uint32_t ms;
if (nv50_context(pipe)->screen->tesla->grclass >= NVA3_3D) {
SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1);
SB_DATA (so, nv50_colormask(cso->rt[0].colormask));
}
+ ms = 0;
+ if (cso->alpha_to_coverage)
+ ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
+ if (cso->alpha_to_one)
+ ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
+
+ SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
+ SB_DATA (so, ms);
+
assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
return so;
}
SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1);
SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000);
+ SB_BEGIN_3D(so, MULTISAMPLE_ENABLE, 1);
+ SB_DATA (so, cso->multisample);
+
SB_BEGIN_3D(so, LINE_WIDTH, 1);
SB_DATA (so, fui(cso->line_width));
SB_BEGIN_3D(so, LINE_SMOOTH_ENABLE, 1);
struct nouveau_channel *chan = nv50->screen->base.channel;
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
unsigned i;
+ unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
boolean serialize = FALSE;
nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME);
BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
OUT_RING (chan, sf->depth);
+ ms_mode = mt->ms_mode;
+
if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
serialize = TRUE;
mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
OUT_RING (chan, sf->height);
OUT_RING (chan, (unk << 16) | sf->depth);
+ ms_mode = mt->ms_mode;
+
if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
serialize = TRUE;
mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
OUT_RING (chan, 0);
}
+ BEGIN_RING(chan, RING_3D(MULTISAMPLE_MODE), 1);
+ OUT_RING (chan, ms_mode);
+
BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
OUT_RING (chan, fb->width << 16);
OUT_RING (chan, fb->height << 16);
OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
}
+static void
+nv50_validate_sample_mask(struct nv50_context *nv50)
+{
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+
+ unsigned mask[4] =
+ {
+ nv50->sample_mask & 0xffff,
+ nv50->sample_mask & 0xffff,
+ nv50->sample_mask & 0xffff,
+ nv50->sample_mask & 0xffff
+ };
+
+ BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4);
+ OUT_RING (chan, mask[0]);
+ OUT_RING (chan, mask[1]);
+ OUT_RING (chan, mask[2]);
+ OUT_RING (chan, mask[3]);
+}
+
static void
nv50_switch_pipe_context(struct nv50_context *ctx_to)
{
{ nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
{ nv50_validate_blend, NV50_NEW_BLEND },
{ nv50_validate_zsa, NV50_NEW_ZSA },
+ { nv50_validate_sample_mask, NV50_NEW_SAMPLE_MASK },
{ nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
{ nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
{ nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
struct nv50_blend_stateobj {
struct pipe_blend_state pipe;
int size;
- uint32_t state[82]; // TODO: allocate less if !independent_blend_enable
+ uint32_t state[84]; // TODO: allocate less if !independent_blend_enable
};
struct nv50_rasterizer_stateobj {
struct pipe_rasterizer_state pipe;
int size;
- uint32_t state[42];
+ uint32_t state[44];
};
struct nv50_zsa_stateobj {
return 1;
}
- width = u_minify(mt->base.base.width0, level);
- height = u_minify(mt->base.base.height0, level);
+ width = u_minify(mt->base.base.width0, level) << mt->ms_x;
+ height = u_minify(mt->base.base.height0, level) << mt->ms_y;
offset = mt->level[level].offset;
if (!mt->layout_3d) {
unsigned sx, unsigned sy, unsigned sz,
unsigned w, unsigned h)
{
+ static const uint32_t duvdxy[5] =
+ {
+ 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
+ };
+
int ret;
+ uint32_t ctrl;
ret = MARK_RING(chan, 2 * 16 + 32, 4);
if (ret)
if (ret)
return ret;
- /* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */
+ /* NOTE: 2D engine doesn't work for MS8 */
+ if (src->ms_x)
+ ctrl = 0x11;
+
+ /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1);
- OUT_RING (chan, 0);
+ OUT_RING (chan, ctrl);
BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4);
- OUT_RING (chan, dx);
- OUT_RING (chan, dy);
- OUT_RING (chan, w);
- OUT_RING (chan, h);
+ OUT_RING (chan, dx << dst->ms_x);
+ OUT_RING (chan, dy << dst->ms_y);
+ OUT_RING (chan, w << dst->ms_x);
+ OUT_RING (chan, h << dst->ms_y);
BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f);
BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4);
OUT_RING (chan, 0);
- OUT_RING (chan, sx);
+ OUT_RING (chan, sx << src->ms_x);
OUT_RING (chan, 0);
- OUT_RING (chan, sy);
+ OUT_RING (chan, sy << src->ms_y);
return 0;
}
return;
}
+ nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
+
+ if (src->format == dst->format && src->nr_samples == dst->nr_samples) {
+ struct nv50_m2mf_rect drect, srect;
+ unsigned i;
+ unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
+ unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
+
+ nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
+ nv50_m2mf_rect_setup(&srect, src, src_level,
+ src_box->x, src_box->y, src_box->z);
+
+ for (i = 0; i < src_box->depth; ++i) {
+ nv50_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny);
+
+ if (nv50_miptree(dst)->layout_3d)
+ drect.z++;
+ else
+ drect.base += nv50_miptree(dst)->layer_stride;
+
+ if (nv50_miptree(src)->layout_3d)
+ srect.z++;
+ else
+ srect.base += nv50_miptree(src)->layer_stride;
+ }
+ return;
+ }
+
assert((src->format == dst->format) ||
(nv50_2d_format_faithful(src->format) &&
nv50_2d_format_faithful(dst->format)));
else
tic[3] = 0x00300000;
- tic[4] = (1 << 31) | mt->base.base.width0;
+ tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
- tic[5] = mt->base.base.height0 & 0xffff;
+ tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
tic[5] |= depth << 16;
tic[5] |= mt->base.base.last_level << 28;
- tic[6] = 0x03000000;
+ tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
#include "util/u_format.h"
#include "nv50_context.h"
-#include "nv50_transfer.h"
#include "nv50_defs.xml.h"
uint32_t nblocksy;
};
-static void
+void
+nv50_m2mf_rect_setup(struct nv50_m2mf_rect *rect,
+ struct pipe_resource *restrict res, unsigned l,
+ unsigned x, unsigned y, unsigned z)
+{
+ struct nv50_miptree *mt = nv50_miptree(res);
+ const unsigned w = u_minify(res->width0, l);
+ const unsigned h = u_minify(res->height0, l);
+
+ rect->bo = mt->base.bo;
+ rect->domain = mt->base.domain;
+ rect->base = mt->level[l].offset;
+ rect->pitch = mt->level[l].pitch;
+ if (util_format_is_plain(res->format)) {
+ rect->width = w << mt->ms_x;
+ rect->height = h << mt->ms_y;
+ rect->x = x << mt->ms_x;
+ rect->y = y << mt->ms_y;
+ } else {
+ rect->width = util_format_get_nblocksx(res->format, w);
+ rect->height = util_format_get_nblocksy(res->format, h);
+ rect->x = util_format_get_nblocksx(res->format, x);
+ rect->y = util_format_get_nblocksy(res->format, y);
+ }
+ rect->tile_mode = mt->level[l].tile_mode;
+ rect->cpp = util_format_get_blocksize(res->format);
+
+ if (mt->layout_3d) {
+ rect->z = z;
+ rect->depth = u_minify(res->depth0, l);
+ } else {
+ rect->base += z * mt->layer_stride;
+ rect->z = 0;
+ rect->depth = 1;
+ }
+}
+
+void
nv50_m2mf_transfer_rect(struct pipe_screen *pscreen,
const struct nv50_m2mf_rect *dst,
const struct nv50_m2mf_rect *src,
struct nv50_context *nv50 = nv50_context(pctx);
struct pipe_screen *pscreen = pctx->screen;
struct nouveau_device *dev = nv50->screen->base.device;
- struct nv50_miptree *mt = nv50_miptree(res);
- struct nv50_miptree_level *lvl = &mt->level[level];
+ const struct nv50_miptree *mt = nv50_miptree(res);
struct nv50_transfer *tx;
uint32_t size;
- uint32_t w, h, d, z, layer;
int ret;
if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
return NULL;
- if (mt->layout_3d) {
- z = box->z;
- d = u_minify(res->depth0, level);
- layer = 0;
- } else {
- z = 0;
- d = 1;
- layer = box->z;
- }
-
tx = CALLOC_STRUCT(nv50_transfer);
if (!tx)
return NULL;
tx->base.usage = usage;
tx->base.box = *box;
- tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
- tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
+ if (util_format_is_plain(res->format)) {
+ tx->nblocksx = box->width << mt->ms_x;
+ tx->nblocksy = box->height << mt->ms_x;
+ } else {
+ tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
+ tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
+ }
tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
tx->base.layer_stride = tx->nblocksy * tx->base.stride;
- w = u_minify(res->width0, level);
- h = u_minify(res->height0, level);
-
- tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format);
-
- tx->rect[0].bo = mt->base.bo;
- tx->rect[0].base = lvl->offset + layer * mt->layer_stride;
- tx->rect[0].tile_mode = lvl->tile_mode;
- tx->rect[0].x = util_format_get_nblocksx(res->format, box->x);
- tx->rect[0].y = util_format_get_nblocksy(res->format, box->y);
- tx->rect[0].z = z;
- tx->rect[0].width = util_format_get_nblocksx(res->format, w);
- tx->rect[0].height = util_format_get_nblocksy(res->format, h);
- tx->rect[0].depth = d;
- tx->rect[0].pitch = lvl->pitch;
- tx->rect[0].domain = NOUVEAU_BO_VRAM;
+ nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z);
size = tx->base.layer_stride;
return NULL;
}
+ tx->rect[1].cpp = tx->rect[0].cpp;
tx->rect[1].width = tx->nblocksx;
tx->rect[1].height = tx->nblocksy;
tx->rect[1].depth = 1;
if (usage & PIPE_TRANSFER_READ) {
unsigned base = tx->rect[0].base;
+ unsigned z = tx->rect[0].z;
unsigned i;
for (i = 0; i < box->depth; ++i) {
nv50_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0],
#include "pipe/p_state.h"
-struct pipe_transfer *
-nv50_miptree_transfer_new(struct pipe_context *pcontext,
- struct pipe_resource *pt,
- unsigned level,
- unsigned usage,
- const struct pipe_box *box);
-void
-nv50_miptree_transfer_del(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-void *
-nv50_miptree_transfer_map(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-void
-nv50_miptree_transfer_unmap(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-
struct nv50_m2mf_rect {
struct nouveau_bo *bo;
uint32_t base;
uint16_t cpp;
};
+void
+nv50_m2mf_rect_setup(struct nv50_m2mf_rect *rect,
+ struct pipe_resource *restrict res, unsigned l,
+ unsigned x, unsigned y, unsigned z);
+
#endif
#define NVC0_3D_TFB_ENABLE 0x00000744
+#define NVC0_3D_SAMPLE_SHADING 0x00000754
+#define NVC0_3D_SAMPLE_SHADING_MIN_SAMPLES__MASK 0x0000000f
+#define NVC0_3D_SAMPLE_SHADING_MIN_SAMPLES__SHIFT 0
+#define NVC0_3D_SAMPLE_SHADING_ENABLE 0x00000010
+
#define NVC0_3D_LOCAL_BASE 0x0000077c
#define NVC0_3D_LOCAL_ADDRESS_HIGH 0x00000790
#include "nvc0_program.h"
#include "nvc0_resource.h"
+#include "nv50/nv50_transfer.h"
+
#include "nouveau/nouveau_context.h"
#include "nvc0_3ddefs.xml.h"
/* nvc0_transfer.c */
void
+nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen,
+ const struct nv50_m2mf_rect *dst,
+ const struct nv50_m2mf_rect *src,
+ uint32_t nblocksx, uint32_t nblocksy);
+void
nvc0_m2mf_push_linear(struct nouveau_context *nv,
struct nouveau_bo *dst, unsigned offset, unsigned domain,
unsigned size, void *data);
#include "nvc0_context.h"
#include "nvc0_resource.h"
-#include "nvc0_transfer.h"
uint32_t
nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
unsigned
nvc0_mt_zslice_offset(const struct nv50_miptree *, unsigned l, unsigned z);
+struct pipe_transfer *
+nvc0_miptree_transfer_new(struct pipe_context *pcontext,
+ struct pipe_resource *pt,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box);
+void
+nvc0_miptree_transfer_del(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+void *
+nvc0_miptree_transfer_map(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+void
+nvc0_miptree_transfer_unmap(struct pipe_context *pcontext,
+ struct pipe_transfer *ptx);
+
#endif
unsigned sample_count,
unsigned bindings)
{
- if (sample_count > 1)
+ if (sample_count > 2 && sample_count != 4 && sample_count != 8)
return FALSE;
if (!util_format_is_supported(format, bindings))
{
struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj);
int i;
+ uint32_t ms;
so->pipe = *cso;
SB_DATA(so, nvc0_colormask(cso->rt[i].colormask));
}
+ ms = 0;
+ if (cso->alpha_to_coverage)
+ ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
+ if (cso->alpha_to_one)
+ ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
+
+ SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
+ SB_DATA (so, ms);
+
assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
return so;
}
SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1);
SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000);
+ SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample);
+
SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth);
if (cso->line_smooth)
SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1);
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
unsigned i;
+ unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
boolean serialize = FALSE;
nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME);
OUT_RING (chan, mt->layer_stride >> 2);
OUT_RING (chan, sf->base.u.tex.first_layer);
+ ms_mode = mt->ms_mode;
+
if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
serialize = TRUE;
mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
BEGIN_RING(chan, RING_3D(ZETA_BASE_LAYER), 1);
OUT_RING (chan, sf->base.u.tex.first_layer);
+ ms_mode = mt->ms_mode;
+
if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
serialize = TRUE;
mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
OUT_RING (chan, 0);
}
+ IMMED_RING(chan, RING_3D(MULTISAMPLE_MODE), ms_mode);
+
if (serialize) {
BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
OUT_RING (chan, 0);
}
}
+static void
+nvc0_validate_sample_mask(struct nvc0_context *nvc0)
+{
+ struct nouveau_channel *chan = nvc0->screen->base.channel;
+
+ unsigned mask[4] =
+ {
+ nvc0->sample_mask & 0xffff,
+ nvc0->sample_mask & 0xffff,
+ nvc0->sample_mask & 0xffff,
+ nvc0->sample_mask & 0xffff
+ };
+
+ BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4);
+ OUT_RING (chan, mask[0]);
+ OUT_RING (chan, mask[1]);
+ OUT_RING (chan, mask[2]);
+ OUT_RING (chan, mask[3]);
+ BEGIN_RING(chan, RING_3D(SAMPLE_SHADING), 1);
+ OUT_RING (chan, 0x01);
+}
+
static void
nvc0_validate_derived_1(struct nvc0_context *nvc0)
{
{ nvc0_validate_fb, NVC0_NEW_FRAMEBUFFER },
{ nvc0_validate_blend, NVC0_NEW_BLEND },
{ nvc0_validate_zsa, NVC0_NEW_ZSA },
+ { nvc0_validate_sample_mask, NVC0_NEW_SAMPLE_MASK },
{ nvc0_validate_rasterizer, NVC0_NEW_RASTERIZER },
{ nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR },
{ nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF },
struct nvc0_blend_stateobj {
struct pipe_blend_state pipe;
int size;
- uint32_t state[70];
+ uint32_t state[72];
};
struct nvc0_rasterizer_stateobj {
struct pipe_rasterizer_state pipe;
int size;
- uint32_t state[38];
+ uint32_t state[39];
};
struct nvc0_zsa_stateobj {
#include "nvc0_context.h"
#include "nvc0_resource.h"
-#include "nvc0_transfer.h"
#include "nv50/nv50_defs.xml.h"
return 1;
}
- width = u_minify(mt->base.base.width0, level);
- height = u_minify(mt->base.base.height0, level);
+ width = u_minify(mt->base.base.width0, level) << mt->ms_x;
+ height = u_minify(mt->base.base.height0, level) << mt->ms_y;
depth = u_minify(mt->base.base.depth0, level);
/* layer has to be < depth, and depth > tile depth / 2 */
unsigned sx, unsigned sy, unsigned sz,
unsigned w, unsigned h)
{
+ static const uint32_t duvdxy[5] =
+ {
+ 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
+ };
+
int ret;
+ uint32_t ctrl = 0x00;
ret = MARK_RING(chan, 2 * 16 + 32, 4);
if (ret)
if (ret)
return ret;
- /* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */
+ /* NOTE: 2D engine doesn't work for MS8 */
+ if (src->ms_x)
+ ctrl = 0x11;
+
+ /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1);
- OUT_RING (chan, 0);
+ OUT_RING (chan, ctrl);
BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4);
- OUT_RING (chan, dx);
- OUT_RING (chan, dy);
- OUT_RING (chan, w);
- OUT_RING (chan, h);
+ OUT_RING (chan, dx << dst->ms_x);
+ OUT_RING (chan, dy << dst->ms_y);
+ OUT_RING (chan, w << dst->ms_x);
+ OUT_RING (chan, h << dst->ms_y);
BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000);
+ OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f);
BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4);
OUT_RING (chan, 0);
- OUT_RING (chan, sx);
+ OUT_RING (chan, sx << src->ms_x);
OUT_RING (chan, 0);
- OUT_RING (chan, sy);
+ OUT_RING (chan, sy << src->ms_x);
return 0;
}
-static void
-nvc0_setup_m2mf_rect(struct nvc0_m2mf_rect *rect,
- struct pipe_resource *restrict res, unsigned l,
- unsigned x, unsigned y, unsigned z)
-{
- struct nv50_miptree *mt = nv50_miptree(res);
- const unsigned w = u_minify(res->width0, l);
- const unsigned h = u_minify(res->height0, l);
-
- rect->bo = mt->base.bo;
- rect->domain = mt->base.domain;
- rect->base = mt->level[l].offset;
- rect->pitch = mt->level[l].pitch;
- if (util_format_is_plain(res->format)) {
- rect->width = w;
- rect->height = h;
- rect->x = x;
- rect->y = y;
- } else {
- rect->width = util_format_get_nblocksx(res->format, w);
- rect->height = util_format_get_nblocksy(res->format, h);
- rect->x = util_format_get_nblocksx(res->format, x);
- rect->y = util_format_get_nblocksy(res->format, y);
- }
- rect->tile_mode = mt->level[l].tile_mode;
- rect->cpp = util_format_get_blocksize(res->format);
-
- if (mt->layout_3d) {
- rect->z = z;
- rect->depth = u_minify(res->depth0, l);
- } else {
- rect->base += z * mt->layer_stride;
- rect->z = 0;
- rect->depth = 1;
- }
-}
-
static void
nvc0_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dst, unsigned dst_level,
nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
- if (src->format == dst->format) {
- struct nvc0_m2mf_rect drect, srect;
+ if (src->format == dst->format && src->nr_samples == dst->nr_samples) {
+ struct nv50_m2mf_rect drect, srect;
unsigned i;
unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
- nvc0_setup_m2mf_rect(&drect, dst, dst_level, dstx, dsty, dstz);
- nvc0_setup_m2mf_rect(&srect, src, src_level,
+ nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
+ nv50_m2mf_rect_setup(&srect, src, src_level,
src_box->x, src_box->y, src_box->z);
for (i = 0; i < src_box->depth; ++i) {
depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY ||
+ /* mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS || */
mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) {
/* there doesn't seem to be a base layer field in TIC */
tic[1] = view->pipe.u.tex.first_layer * mt->layer_stride;
case PIPE_TEXTURE_1D:
tic[2] |= NV50_TIC_2_TARGET_1D;
break;
+/* case PIPE_TEXTURE_2D_MS: */
case PIPE_TEXTURE_2D:
tic[2] |= NV50_TIC_2_TARGET_2D;
break;
case PIPE_TEXTURE_1D_ARRAY:
tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
break;
+/* case PIPE_TEXTURE_2D_ARRAY_MS: */
case PIPE_TEXTURE_2D_ARRAY:
tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
break;
else
tic[3] = 0x00300000;
- tic[4] = (1 << 31) | mt->base.base.width0;
+ tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
- tic[5] = mt->base.base.height0 & 0xffff;
+ tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
tic[5] |= depth << 16;
tic[5] |= mt->base.base.last_level << 28;
- tic[6] = 0x03000000;
+ tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
+ /*
+ if (mt->base.base.target == PIPE_TEXTURE_2D_MS ||
+ mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS)
+ tic[7] |= mt->ms_mode << 12;
+ */
+
return &view->pipe;
}
#include "util/u_format.h"
#include "nvc0_context.h"
-#include "nvc0_transfer.h"
#include "nv50/nv50_defs.xml.h"
struct nvc0_transfer {
struct pipe_transfer base;
- struct nvc0_m2mf_rect rect[2];
+ struct nv50_m2mf_rect rect[2];
uint32_t nblocksx;
uint16_t nblocksy;
uint16_t nlayers;
void
nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen,
- const struct nvc0_m2mf_rect *dst,
- const struct nvc0_m2mf_rect *src,
+ const struct nv50_m2mf_rect *dst,
+ const struct nv50_m2mf_rect *src,
uint32_t nblocksx, uint32_t nblocksy)
{
struct nouveau_channel *chan = nouveau_screen(pscreen)->channel;
}
}
+#if 0
static void
nvc0_m2mf_push_rect(struct pipe_screen *pscreen,
- const struct nvc0_m2mf_rect *dst,
+ const struct nv50_m2mf_rect *dst,
const void *data,
unsigned nblocksx, unsigned nblocksy)
{
nblocksy -= line_count;
}
}
+#endif
struct pipe_transfer *
nvc0_miptree_transfer_new(struct pipe_context *pctx,
struct pipe_screen *pscreen = pctx->screen;
struct nouveau_device *dev = nvc0->screen->base.device;
struct nv50_miptree *mt = nv50_miptree(res);
- struct nv50_miptree_level *lvl = &mt->level[level];
struct nvc0_transfer *tx;
uint32_t size;
- uint32_t w, h, d, z, layer;
int ret;
if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
if (!tx)
return NULL;
- if (mt->layout_3d) {
- z = box->z;
- d = u_minify(res->depth0, level);
- layer = 0;
- } else {
- z = 0;
- d = 1;
- layer = box->z;
- }
- tx->nlayers = box->depth;
-
pipe_resource_reference(&tx->base.resource, res);
tx->base.level = level;
tx->base.usage = usage;
tx->base.box = *box;
- tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
- tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
+ if (util_format_is_plain(res->format)) {
+ tx->nblocksx = box->width << mt->ms_x;
+ tx->nblocksy = box->height << mt->ms_y;
+ } else {
+ tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
+ tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
+ }
+ tx->nlayers = box->depth;
tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
tx->base.layer_stride = tx->nblocksy * tx->base.stride;
- w = u_minify(res->width0, level);
- h = u_minify(res->height0, level);
-
- tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format);
-
- tx->rect[0].bo = mt->base.bo;
- tx->rect[0].base = lvl->offset + layer * mt->layer_stride;
- tx->rect[0].tile_mode = lvl->tile_mode;
- tx->rect[0].x = util_format_get_nblocksx(res->format, box->x);
- tx->rect[0].y = util_format_get_nblocksy(res->format, box->y);
- tx->rect[0].z = z;
- tx->rect[0].width = util_format_get_nblocksx(res->format, w);
- tx->rect[0].height = util_format_get_nblocksy(res->format, h);
- tx->rect[0].depth = d;
- tx->rect[0].pitch = lvl->pitch;
- tx->rect[0].domain = NOUVEAU_BO_VRAM;
+ nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z);
size = tx->base.layer_stride;
return NULL;
}
+ tx->rect[1].cpp = tx->rect[0].cpp;
tx->rect[1].width = tx->nblocksx;
tx->rect[1].height = tx->nblocksy;
tx->rect[1].depth = 1;
if (usage & PIPE_TRANSFER_READ) {
unsigned base = tx->rect[0].base;
+ unsigned z = tx->rect[0].z;
unsigned i;
for (i = 0; i < tx->nlayers; ++i) {
nvc0_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0],
+++ /dev/null
-
-#ifndef __NVC0_TRANSFER_H__
-#define __NVC0_TRANSFER_H__
-
-#include "pipe/p_state.h"
-
-struct pipe_transfer *
-nvc0_miptree_transfer_new(struct pipe_context *pcontext,
- struct pipe_resource *pt,
- unsigned level,
- unsigned usage,
- const struct pipe_box *box);
-void
-nvc0_miptree_transfer_del(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-void *
-nvc0_miptree_transfer_map(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-void
-nvc0_miptree_transfer_unmap(struct pipe_context *pcontext,
- struct pipe_transfer *ptx);
-
-struct nvc0_m2mf_rect {
- struct nouveau_bo *bo;
- uint32_t base;
- unsigned domain;
- uint32_t pitch;
- uint32_t width;
- uint32_t x;
- uint32_t height;
- uint32_t y;
- uint16_t depth;
- uint16_t z;
- uint16_t tile_mode;
- uint16_t cpp;
-};
-
-void
-nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen,
- const struct nvc0_m2mf_rect *dst,
- const struct nvc0_m2mf_rect *src,
- uint32_t nblocksx, uint32_t nblocksy);
-
-#endif