#include "util/u_inlines.h"
#include "util/u_pack_color.h"
#include "util/u_format.h"
+#include "util/u_math.h"
#include "util/u_surface.h"
#include "tgsi/tgsi_ureg.h"
#include "nv50/nv50_context.h"
#include "nv50/nv50_resource.h"
-#include "nv50/nv50_defs.xml.h"
-#include "nv50/nv50_texture.xml.h"
+#include "nv50/g80_defs.xml.h"
+#include "nv50/g80_texture.xml.h"
/* these are used in nv50_blit.h */
#define NV50_ENG2D_SUPPORTED_FORMATS 0xff0843e080608409ULL
switch (util_format_get_blocksize(format)) {
case 1:
- return NV50_SURFACE_FORMAT_R8_UNORM;
+ return G80_SURFACE_FORMAT_R8_UNORM;
case 2:
- return NV50_SURFACE_FORMAT_R16_UNORM;
+ return G80_SURFACE_FORMAT_R16_UNORM;
case 4:
- return NV50_SURFACE_FORMAT_BGRA8_UNORM;
+ return G80_SURFACE_FORMAT_BGRA8_UNORM;
+ case 8:
+ return G80_SURFACE_FORMAT_RGBA16_FLOAT;
+ case 16:
+ return G80_SURFACE_FORMAT_RGBA32_FLOAT;
default:
return 0;
}
nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
if (m2mf) {
+ struct nv50_miptree *src_mt = nv50_miptree(src);
+ struct nv50_miptree *dst_mt = nv50_miptree(dst);
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);
+ unsigned nx = util_format_get_nblocksx(src->format, src_box->width)
+ << src_mt->ms_x;
+ unsigned ny = util_format_get_nblocksy(src->format, src_box->height)
+ << src_mt->ms_y;
nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
nv50_m2mf_rect_setup(&srect, src, src_level,
for (i = 0; i < src_box->depth; ++i) {
nv50_m2mf_transfer_rect(nv50, &drect, &srect, nx, ny);
- if (nv50_miptree(dst)->layout_3d)
+ if (dst_mt->layout_3d)
drect.z++;
else
- drect.base += nv50_miptree(dst)->layer_stride;
+ drect.base += dst_mt->layer_stride;
- if (nv50_miptree(src)->layout_3d)
+ if (src_mt->layout_3d)
srect.z++;
else
- srect.base += nv50_miptree(src)->layer_stride;
+ srect.base += src_mt->layer_stride;
}
return;
}
static void
nv50_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
- const union pipe_color_union *color,
+ const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct nouveau_bo *bo = mt->base.bo;
unsigned z;
+ assert(dst->texture->target != PIPE_BUFFER);
+
BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);
PUSH_DATAf(push, color->f[0]);
PUSH_DATAf(push, color->f[1]);
else
PUSH_DATA(push, 512);
+ BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
+ PUSH_DATA (push, mt->ms_mode);
+
if (!nouveau_bo_memtype(bo)) {
BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
PUSH_DATA (push, 0);
PUSH_DATA (push, (width << 16) | dstx);
PUSH_DATA (push, (height << 16) | dsty);
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);
+
BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth);
for (z = 0; z < sf->depth; ++z) {
PUSH_DATA (push, 0x3c |
(z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));
}
- nv50->dirty |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, nv50->cond_condmode);
+
+ nv50->dirty_3d |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
}
static void
uint32_t mode = 0;
unsigned z;
+ assert(dst->texture->target != PIPE_BUFFER);
assert(nouveau_bo_memtype(bo)); /* ZETA cannot be linear */
if (clear_flags & PIPE_CLEAR_DEPTH) {
BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
PUSH_DATA (push, 512);
+ BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
+ PUSH_DATA (push, mt->ms_mode);
+
BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
PUSH_DATA (push, (width << 16) | dstx);
PUSH_DATA (push, (height << 16) | dsty);
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);
+
BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth);
for (z = 0; z < sf->depth; ++z) {
PUSH_DATA (push, mode |
(z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));
}
- nv50->dirty |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, nv50->cond_condmode);
+
+ nv50->dirty_3d |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
+}
+
+void
+nv50_clear_texture(struct pipe_context *pipe,
+ struct pipe_resource *res,
+ unsigned level,
+ const struct pipe_box *box,
+ const void *data)
+{
+ struct pipe_surface tmpl = {{0}}, *sf;
+
+ tmpl.format = res->format;
+ tmpl.u.tex.first_layer = box->z;
+ tmpl.u.tex.last_layer = box->z + box->depth - 1;
+ tmpl.u.tex.level = level;
+ sf = pipe->create_surface(pipe, res, &tmpl);
+ if (!sf)
+ return;
+
+ if (util_format_is_depth_or_stencil(res->format)) {
+ float depth = 0;
+ uint8_t stencil = 0;
+ unsigned clear = 0;
+ const struct util_format_description *desc =
+ util_format_description(res->format);
+
+ if (util_format_has_depth(desc)) {
+ clear |= PIPE_CLEAR_DEPTH;
+ desc->unpack_z_float(&depth, 0, data, 0, 1, 1);
+ }
+ if (util_format_has_stencil(desc)) {
+ clear |= PIPE_CLEAR_STENCIL;
+ desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
+ }
+ pipe->clear_depth_stencil(pipe, sf, clear, depth, stencil,
+ box->x, box->y, box->width, box->height);
+ } else {
+ union pipe_color_union color;
+
+ switch (util_format_get_blocksizebits(res->format)) {
+ case 128:
+ sf->format = PIPE_FORMAT_R32G32B32A32_UINT;
+ memcpy(&color.ui, data, 128 / 8);
+ break;
+ case 64:
+ sf->format = PIPE_FORMAT_R32G32_UINT;
+ memcpy(&color.ui, data, 64 / 8);
+ memset(&color.ui[2], 0, 64 / 8);
+ break;
+ case 32:
+ sf->format = PIPE_FORMAT_R32_UINT;
+ memcpy(&color.ui, data, 32 / 8);
+ memset(&color.ui[1], 0, 96 / 8);
+ break;
+ case 16:
+ sf->format = PIPE_FORMAT_R16_UINT;
+ color.ui[0] = util_cpu_to_le32(
+ util_le16_to_cpu(*(unsigned short *)data));
+ memset(&color.ui[1], 0, 96 / 8);
+ break;
+ case 8:
+ sf->format = PIPE_FORMAT_R8_UINT;
+ color.ui[0] = util_cpu_to_le32(*(unsigned char *)data);
+ memset(&color.ui[1], 0, 96 / 8);
+ break;
+ default:
+ assert(!"Unknown texel element size");
+ return;
+ }
+
+ pipe->clear_render_target(pipe, sf, &color,
+ box->x, box->y, box->width, box->height);
+ }
+ pipe->surface_destroy(pipe, sf);
}
void
uint32_t mode = 0;
/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
- if (!nv50_state_validate(nv50, NV50_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
+ if (!nv50_state_validate(nv50, NV50_NEW_FRAMEBUFFER))
return;
/* We have to clear ALL of the layers, not up to the min number of layers
if (mode) {
int zs_layers = 0, color0_layers = 0;
if (fb->cbufs[0] && (mode & 0x3c))
- color0_layers = fb->cbufs[0]->u.tex.last_layer -
- fb->cbufs[0]->u.tex.first_layer + 1;
+ color0_layers = nv50_surface(fb->cbufs[0])->depth;
if (fb->zsbuf && (mode & ~0x3c))
- zs_layers = fb->zsbuf->u.tex.last_layer -
- fb->zsbuf->u.tex.first_layer + 1;
+ zs_layers = nv50_surface(fb->zsbuf)->depth;
for (j = 0; j < MIN2(zs_layers, color0_layers); j++) {
BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);
struct pipe_surface *sf = fb->cbufs[i];
if (!sf || !(buffers & (PIPE_CLEAR_COLOR0 << i)))
continue;
- for (j = 0; j <= sf->u.tex.last_layer - sf->u.tex.first_layer; j++) {
+ for (j = 0; j < nv50_surface(sf)->depth; j++) {
BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);
PUSH_DATA (push, (i << 6) | 0x3c |
(j << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));
PUSH_DATA (push, nv50->rt_array_mode);
}
+static void
+nv50_clear_buffer_push(struct pipe_context *pipe,
+ struct pipe_resource *res,
+ unsigned offset, unsigned size,
+ const void *data, int data_size)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_pushbuf *push = nv50->base.pushbuf;
+ struct nv04_resource *buf = nv04_resource(res);
+ unsigned count = (size + 3) / 4;
+ unsigned xcoord = offset & 0xff;
+ unsigned tmp, i;
+
+ if (data_size == 1) {
+ tmp = *(unsigned char *)data;
+ tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp;
+ data = &tmp;
+ data_size = 4;
+ } else if (data_size == 2) {
+ tmp = *(unsigned short *)data;
+ tmp = (tmp << 16) | tmp;
+ data = &tmp;
+ data_size = 4;
+ }
+
+ unsigned data_words = data_size / 4;
+
+ nouveau_bufctx_refn(nv50->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR);
+ nouveau_pushbuf_bufctx(push, nv50->bufctx);
+ nouveau_pushbuf_validate(push);
+
+ offset &= ~0xff;
+
+ BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
+ PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
+ PUSH_DATA (push, 1);
+ BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
+ PUSH_DATA (push, 262144);
+ PUSH_DATA (push, 65536);
+ PUSH_DATA (push, 1);
+ PUSH_DATAh(push, buf->address + offset);
+ PUSH_DATA (push, buf->address + offset);
+ BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
+ BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
+ PUSH_DATA (push, size);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, xcoord);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, 0);
+
+ while (count) {
+ unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words;
+ unsigned nr = nr_data * data_words;
+
+ BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);
+ for (i = 0; i < nr_data; i++)
+ PUSH_DATAp(push, data, data_words);
+
+ count -= nr;
+ }
+
+ if (buf->mm) {
+ nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);
+ nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);
+ }
+
+ nouveau_bufctx_reset(nv50->bufctx, 0);
+}
+
static void
nv50_clear_buffer(struct pipe_context *pipe,
struct pipe_resource *res,
assert(size % data_size == 0);
+ if (offset & 0xff) {
+ unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset);
+ assert(fixup_size % data_size == 0);
+ nv50_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size);
+ offset += fixup_size;
+ size -= fixup_size;
+ if (!size)
+ return;
+ }
+
elements = size / data_size;
height = (elements + 8191) / 8192;
width = elements / height;
+ if (height > 1)
+ width &= ~0xff;
+ assert(width > 0);
BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);
PUSH_DATAf(push, color.f[0]);
BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
PUSH_DATA (push, 1);
BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);
- PUSH_DATAh(push, buf->bo->offset + buf->offset + offset);
- PUSH_DATA (push, buf->bo->offset + buf->offset + offset);
+ PUSH_DATAh(push, buf->address + offset);
+ PUSH_DATA (push, buf->address + offset);
PUSH_DATA (push, nv50_format_table[dst_fmt].rt);
PUSH_DATA (push, 0);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);
- PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | (width * data_size));
+ PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | align(width * data_size, 0x100));
PUSH_DATA (push, height);
BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
+ PUSH_DATA (push, 0);
/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
PUSH_DATA (push, (width << 16));
PUSH_DATA (push, (height << 16));
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);
+
BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);
PUSH_DATA (push, 0x3c);
+ BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
+ PUSH_DATA (push, nv50->cond_condmode);
+
+ if (buf->mm) {
+ nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);
+ nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);
+ }
+
if (width * height != elements) {
offset += width * height * data_size;
width = elements - width * height;
- height = 1;
- BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 2);
- PUSH_DATAh(push, buf->bo->offset + buf->offset + offset);
- PUSH_DATA (push, buf->bo->offset + buf->offset + offset);
- BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);
- PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | (width * data_size));
- PUSH_DATA (push, height);
- BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);
- PUSH_DATA (push, 0x3c);
+ nv50_clear_buffer_push(pipe, res, offset, width * data_size,
+ data, data_size);
}
- nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);
- nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);
-
- nv50->dirty |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
+ nv50->dirty_3d |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
}
/* =============================== BLIT CODE ===================================
struct pipe_sampler_view *texture[2];
struct nv50_tsc_entry *sampler[2];
unsigned min_samples;
- uint32_t dirty;
+ uint32_t dirty_3d;
} saved;
struct nv50_rasterizer_stateobj rast;
};
blit->sampler[0].id = -1;
- blit->sampler[0].tsc[0] = NV50_TSC_0_SRGB_CONVERSION_ALLOWED |
- (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPS__SHIFT) |
- (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPT__SHIFT) |
- (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPR__SHIFT);
+ blit->sampler[0].tsc[0] = G80_TSC_0_SRGB_CONVERSION |
+ (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_U__SHIFT) |
+ (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_V__SHIFT) |
+ (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_P__SHIFT);
blit->sampler[0].tsc[1] =
- NV50_TSC_1_MAGF_NEAREST | NV50_TSC_1_MINF_NEAREST | NV50_TSC_1_MIPF_NONE;
+ G80_TSC_1_MAG_FILTER_NEAREST |
+ G80_TSC_1_MIN_FILTER_NEAREST |
+ G80_TSC_1_MIP_FILTER_NONE;
/* clamp to edge, min/max lod = 0, bilinear filtering */
blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0];
blit->sampler[1].tsc[1] =
- NV50_TSC_1_MAGF_LINEAR | NV50_TSC_1_MINF_LINEAR | NV50_TSC_1_MIPF_NONE;
+ G80_TSC_1_MAG_FILTER_LINEAR |
+ G80_TSC_1_MIN_FILTER_LINEAR |
+ G80_TSC_1_MIP_FILTER_NONE;
}
unsigned
/* zsa state */
BEGIN_NV04(push, NV50_3D(DEPTH_TEST_ENABLE), 1);
PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV50_3D(DEPTH_BOUNDS_EN), 1);
+ PUSH_DATA (push, 0);
BEGIN_NV04(push, NV50_3D(STENCIL_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV50_3D(ALPHA_TEST_ENABLE), 1);
nv50->min_samples = 1;
- ctx->saved.dirty = nv50->dirty;
+ ctx->saved.dirty_3d = nv50->dirty_3d;
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
- nv50->dirty =
+ nv50->dirty_3d =
NV50_NEW_FRAMEBUFFER | NV50_NEW_MIN_SAMPLES |
NV50_NEW_VERTPROG | NV50_NEW_FRAGPROG | NV50_NEW_GMTYPROG |
NV50_NEW_TEXTURES | NV50_NEW_SAMPLERS;
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
- nv50->dirty = blit->saved.dirty |
+ nv50->dirty_3d = blit->saved.dirty_3d |
(NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR | NV50_NEW_SAMPLE_MASK |
NV50_NEW_RASTERIZER | NV50_NEW_ZSA | NV50_NEW_BLEND |
NV50_NEW_TEXTURES | NV50_NEW_SAMPLERS |
nv50_blitctx_prepare_state(blit);
- nv50_state_validate(nv50, ~0, 36);
+ nv50_state_validate(nv50, ~0);
x_range = (float)info->src.box.width / (float)info->dst.box.width;
y_range = (float)info->src.box.height / (float)info->dst.box.height;
}
}
+ pipe_mutex_destroy(blitter->mutex);
FREE(blitter);
}
pipe->resource_copy_region = nv50_resource_copy_region;
pipe->blit = nv50_blit;
pipe->flush_resource = nv50_flush_resource;
+ pipe->clear_texture = nv50_clear_texture;
pipe->clear_render_target = nv50_clear_render_target;
pipe->clear_depth_stencil = nv50_clear_depth_stencil;
pipe->clear_buffer = nv50_clear_buffer;