static void * nv30_sampler_state_create(struct pipe_context *pipe, const struct pipe_sampler_state *cso) { struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; struct nv30_sampler_state *so; const float max_lod = 15.0 + (255.0 / 256.0); so = MALLOC_STRUCT(nv30_sampler_state); if (!so) return NULL; so->pipe = *cso; so->fmt = 0; so->wrap = (wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) | (wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) | (wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT); so->en = 0; so->wrap |= compare_mode(cso); so->filt = filter_mode(cso) | 0x00002000; so->bcol = (float_to_ubyte(cso->border_color.f[3]) << 24) | (float_to_ubyte(cso->border_color.f[0]) << 16) | (float_to_ubyte(cso->border_color.f[1]) << 8) | (float_to_ubyte(cso->border_color.f[2]) << 0); if (eng3d->oclass >= NV40_3D_CLASS) { unsigned aniso = cso->max_anisotropy; if (!cso->normalized_coords) so->fmt |= NV40_3D_TEX_FORMAT_RECT; if (aniso > 1) { if (aniso >= 16) so->en |= NV40_3D_TEX_ENABLE_ANISO_16X; else if (aniso >= 12) so->en |= NV40_3D_TEX_ENABLE_ANISO_12X; else if (aniso >= 10) so->en |= NV40_3D_TEX_ENABLE_ANISO_10X; else if (aniso >= 8) so->en |= NV40_3D_TEX_ENABLE_ANISO_8X; else if (aniso >= 6) so->en |= NV40_3D_TEX_ENABLE_ANISO_6X; else if (aniso >= 4) so->en |= NV40_3D_TEX_ENABLE_ANISO_4X; else so->en |= NV40_3D_TEX_ENABLE_ANISO_2X; so->wrap |= nv30_context(pipe)->config.aniso; } } else { so->en |= NV30_3D_TEX_ENABLE_ENABLE; if (cso->max_anisotropy >= 8) so->en |= NV30_3D_TEX_ENABLE_ANISO_8X; else if (cso->max_anisotropy >= 4) so->en |= NV30_3D_TEX_ENABLE_ANISO_4X; else if (cso->max_anisotropy >= 2) so->en |= NV30_3D_TEX_ENABLE_ANISO_2X; } so->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; so->max_lod = (int)(CLAMP(cso->max_lod, 0.0, max_lod) * 256.0); so->min_lod = (int)(CLAMP(cso->min_lod, 0.0, max_lod) * 256.0); return so; }
static void nv40_query_render_condition(struct pipe_context *pipe, struct pipe_query *pq, boolean condition, enum pipe_render_cond_flag mode) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; nv30->render_cond_query = pq; nv30->render_cond_mode = mode; nv30->render_cond_cond = condition; if (!pq) { BEGIN_NV04(push, SUBC_3D(0x1e98), 1); PUSH_DATA (push, 0x01000000); return; } if (mode == PIPE_RENDER_COND_WAIT || mode == PIPE_RENDER_COND_BY_REGION_WAIT) { BEGIN_NV04(push, SUBC_3D(0x0110), 1); PUSH_DATA (push, 0); } BEGIN_NV04(push, SUBC_3D(0x1e98), 1); PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start); }
static void nv30_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct nv30_context *nv30 = nv30_context(pipe); nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB); nv30->framebuffer = *fb; nv30->dirty |= NV30_NEW_FRAMEBUFFER; /* Hardware can't handle different swizzled-ness or different blocksizes * for zs and cbufs. If both are supplied and something doesn't match, * blank out the zs for now so that at least *some* rendering can occur. */ if (fb->nr_cbufs > 0 && fb->zsbuf) { struct nv30_miptree *color_mt = nv30_miptree(fb->cbufs[0]->texture); struct nv30_miptree *zeta_mt = nv30_miptree(fb->zsbuf->texture); if (color_mt->swizzled != zeta_mt->swizzled || (util_format_get_blocksize(fb->zsbuf->format) > 2) != (util_format_get_blocksize(fb->cbufs[0]->format) > 2)) { nv30->framebuffer.zsbuf = NULL; debug_printf("Mismatched color and zeta formats, ignoring zeta.\n"); } } }
boolean nv30_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); boolean idxbuf; idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize); if (FORCE_SWTNL || !nv30_state_validate(nv30)) { /*return nv30_draw_elements_swtnl(pipe, NULL, 0, mode, start, count);*/ return FALSE; } if (idxbuf) { nv30_draw_elements_vbo(pipe, mode, start, count); } else { nv30_draw_elements_inline(pipe, indexBuffer, indexSize, mode, start, count); } pipe->flush(pipe, 0, NULL); return TRUE; }
static void nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, struct pipe_constant_buffer *cb) { struct nv30_context *nv30 = nv30_context(pipe); struct pipe_resource *buf = cb ? cb->buffer : NULL; unsigned size; if (cb && cb->user_buffer) { buf = nouveau_user_buffer_create(pipe->screen, (void*)cb->user_buffer, cb->buffer_size, PIPE_BIND_CONSTANT_BUFFER); } size = 0; if (buf) size = buf->width0 / (4 * sizeof(float)); if (shader == PIPE_SHADER_VERTEX) { pipe_resource_reference(&nv30->vertprog.constbuf, buf); nv30->vertprog.constbuf_nr = size; nv30->dirty |= NV30_NEW_VERTCONST; } else if (shader == PIPE_SHADER_FRAGMENT) { pipe_resource_reference(&nv30->fragprog.constbuf, buf); nv30->fragprog.constbuf_nr = size; nv30->dirty |= NV30_NEW_FRAGCONST; } if (cb && cb->user_buffer) { pipe_resource_reference(&buf, NULL); } }
void nv30_draw_init(struct pipe_context *pipe) { struct nv30_context *nv30 = nv30_context(pipe); struct vbuf_render *render; struct draw_context *draw; struct draw_stage *stage; draw = draw_create(pipe); if (!draw) return; render = nv30_render_create(nv30); if (!render) { draw_destroy(draw); return; } stage = draw_vbuf_stage(draw, render); if (!stage) { render->destroy(render); draw_destroy(draw); return; } draw_set_render(draw, render); draw_set_rasterize_stage(draw, stage); draw_wide_line_threshold(draw, 10000000.f); draw_wide_point_threshold(draw, 10000000.f); draw_wide_point_sprites(draw, TRUE); nv30->draw = draw; }
static boolean nv30_draw_elements_inline(struct pipe_context *pipe, struct pipe_buffer *ib, unsigned ib_size, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); struct pipe_screen *pscreen = pipe->screen; void *map; map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); return FALSE; } switch (ib_size) { case 1: nv30_draw_elements_u08(nv30, map, mode, start, count); break; case 2: nv30_draw_elements_u16(nv30, map, mode, start, count); break; case 4: nv30_draw_elements_u32(nv30, map, mode, start, count); break; default: NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); break; } pipe_buffer_unmap(pscreen, ib); return TRUE; }
boolean nv30_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_channel *chan = nv30->screen->base.channel; unsigned restart = 0; nv30_vbo_set_idxbuf(nv30, NULL, 0); if (FORCE_SWTNL || !nv30_state_validate(nv30)) { /*return nv30_draw_elements_swtnl(pipe, NULL, 0, mode, start, count);*/ return FALSE; } while (count) { unsigned vc, nr; nv30_state_emit(nv30); vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, mode, start, count, &restart); if (!vc) { FIRE_RING(NULL); continue; } BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1); OUT_RING (((nr - 1) << 24) | start); start += nr; } nr = vc >> 8; while (nr) { unsigned push = nr > 2047 ? 2047 : nr; nr -= push; BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push); while (push--) { OUT_RING(((0x100 - 1) << 24) | start); start += 0x100; } } BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (0); count -= vc; start = restart; } pipe->flush(pipe, 0, NULL); return TRUE; }
static void nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; switch (q->type) { case PIPE_QUERY_TIME_ELAPSED: q->qo[0] = nv30_query_object_new(nv30->screen); if (q->qo[0]) { BEGIN_NV04(push, NV30_3D(QUERY_GET), 1); PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start); } break; case PIPE_QUERY_TIMESTAMP: return; default: BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1); PUSH_DATA (push, q->report); break; } if (q->enable) { BEGIN_NV04(push, SUBC_3D(q->enable), 1); PUSH_DATA (push, 1); } }
static void nv30_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) { struct nv30_context *nv30 = nv30_context(pipe); nv30->sample_mask = sample_mask; nv30->dirty |= NV30_NEW_SAMPLE_MASK; }
static void nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); nv30->vertprog.program = hwcso; nv30->dirty |= NV30_NEW_VERTPROG; }
static void nv30_zsa_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); nv30->zsa = hwcso; nv30->dirty |= NV30_NEW_ZSA; }
static void nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); nv30->rast = hwcso; nv30->dirty |= NV30_NEW_RASTERIZER; }
static void nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); nv30->blend = hwcso; nv30->dirty |= NV30_NEW_BLEND; }
static void nv30_vertex_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); nv30->vertex = hwcso; nv30->dirty |= NV30_NEW_VERTEX; }
static void nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, const union pipe_color_union *color, unsigned x, unsigned y, unsigned w, unsigned h) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_surface *sf = nv30_surface(ps); struct nv30_miptree *mt = nv30_miptree(ps->texture); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf_refn refn; uint32_t rt_format; rt_format = nv30_format(pipe->screen, ps->format)->hw; if (util_format_get_blocksize(ps->format) == 4) rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; else rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; if (nv30_miptree(ps->texture)->swizzled) { rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; rt_format |= util_logbase2(sf->width) << 16; rt_format |= util_logbase2(sf->height) << 24; } else { rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; } refn.bo = mt->base.bo; refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; if (nouveau_pushbuf_space(push, 16, 1, 0) || nouveau_pushbuf_refn (push, &refn, 1)) return; BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); PUSH_DATA (push, sf->width << 16); PUSH_DATA (push, sf->height << 16); PUSH_DATA (push, rt_format); BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); if (eng3d->oclass < NV40_3D_CLASS) PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); else PUSH_DATA (push, sf->pitch); PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | x); PUSH_DATA (push, (h << 16) | y); BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); PUSH_DATA (push, pack_rgba(ps->format, color->f)); PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | NV30_3D_CLEAR_BUFFERS_COLOR_G | NV30_3D_CLEAR_BUFFERS_COLOR_B | NV30_3D_CLEAR_BUFFERS_COLOR_A); nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; }
static void nv30_set_stencil_ref(struct pipe_context *pipe, const struct pipe_stencil_ref *sr) { struct nv30_context *nv30 = nv30_context(pipe); nv30->stencil_ref = *sr; nv30->dirty |= NV30_NEW_STENCIL_REF; }
static void nv30_set_blend_color(struct pipe_context *pipe, const struct pipe_blend_color *bcol) { struct nv30_context *nv30 = nv30_context(pipe); nv30->blend_colour = *bcol; nv30->dirty |= NV30_NEW_BLEND_COLOUR; }
static void nv30_set_polygon_stipple(struct pipe_context *pipe, const struct pipe_poly_stipple *stipple) { struct nv30_context *nv30 = nv30_context(pipe); nv30->stipple = *stipple; nv30->dirty |= NV30_NEW_STIPPLE; }
static void nv30_destroy(struct pipe_context *pipe) { struct nv30_context *nv30 = nv30_context(pipe); if (nv30->draw) draw_destroy(nv30->draw); FREE(nv30); }
static void nv30_set_clip_state(struct pipe_context *pipe, const struct pipe_clip_state *clip) { struct nv30_context *nv30 = nv30_context(pipe); memcpy(nv30->clip.ucp, clip->ucp, sizeof(clip->ucp)); nv30->dirty |= NV30_NEW_CLIP; }
static void nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, unsigned width, unsigned height, unsigned value) { struct nv30_context *nv30 = nv30_context(pipe); struct nv04_surface_2d *eng2d = nv30->screen->eng2d; eng2d->fill(eng2d, dest, destx, desty, width, height, value); }
void nv30_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct nv30_context *nv30 = nv30_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("nv30: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("nv30: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(nv30->blitter, &info)) { debug_printf("nv30: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion queries */ util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf); util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex); util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program); util_blitter_save_rasterizer(nv30->blitter, nv30->rast); util_blitter_save_viewport(nv30->blitter, &nv30->viewport); util_blitter_save_scissor(nv30->blitter, &nv30->scissor); util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program); util_blitter_save_blend(nv30->blitter, nv30->blend); util_blitter_save_depth_stencil_alpha(nv30->blitter, nv30->zsa); util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref); util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask); util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer); util_blitter_save_fragment_sampler_states(nv30->blitter, nv30->fragprog.num_samplers, (void**)nv30->fragprog.samplers); util_blitter_save_fragment_sampler_views(nv30->blitter, nv30->fragprog.num_textures, nv30->fragprog.textures); util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query, nv30->render_cond_mode); util_blitter_blit(nv30->blitter, &info); }
static void nv30_surface_copy(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, struct pipe_surface *src, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { struct nv30_context *nv30 = nv30_context(pipe); struct nv04_surface_2d *eng2d = nv30->screen->eng2d; eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); }
static struct pipe_transfer * nv30_miptree_transfer_new(struct pipe_context *pipe, struct pipe_resource *pt, unsigned level, unsigned usage, const struct pipe_box *box) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_device *dev = nv30->screen->base.device; struct nv30_transfer *tx; int ret; tx = CALLOC_STRUCT(nv30_transfer); if (!tx) return NULL; pipe_resource_reference(&tx->base.resource, pt); tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; tx->base.stride = util_format_get_nblocksx(pt->format, box->width) * util_format_get_blocksize(pt->format); tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) * tx->base.stride; tx->nblocksx = util_format_get_nblocksx(pt->format, box->width); tx->nblocksy = util_format_get_nblocksy(pt->format, box->height); define_rect(pt, level, box->z, box->x, box->y, tx->nblocksx, tx->nblocksy, &tx->img); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, tx->base.layer_stride, NULL, &tx->tmp.bo); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); FREE(tx); return NULL; } tx->tmp.domain = NOUVEAU_BO_GART; tx->tmp.offset = 0; tx->tmp.pitch = tx->base.stride; tx->tmp.cpp = tx->img.cpp; tx->tmp.w = tx->nblocksx; tx->tmp.h = tx->nblocksy; tx->tmp.d = 1; tx->tmp.x0 = 0; tx->tmp.y0 = 0; tx->tmp.x1 = tx->tmp.w; tx->tmp.y1 = tx->tmp.h; tx->tmp.z = 0; if (usage & PIPE_TRANSFER_READ) nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); return &tx->base; }
static void nv30_set_viewport_states(struct pipe_context *pipe, unsigned start_slot, unsigned num_viewports, const struct pipe_viewport_state *vpt) { struct nv30_context *nv30 = nv30_context(pipe); nv30->viewport = *vpt; nv30->dirty |= NV30_NEW_VIEWPORT; }
static void nv30_set_scissor_states(struct pipe_context *pipe, unsigned start_slot, unsigned num_viewports, const struct pipe_scissor_state *scissor) { struct nv30_context *nv30 = nv30_context(pipe); nv30->scissor = *scissor; nv30->dirty |= NV30_NEW_SCISSOR; }
static boolean nv30_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_channel *chan = nv30->screen->base.channel; unsigned restart = 0; while (count) { unsigned nr, vc; nv30_state_emit(nv30); vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, mode, start, count, &restart); if (!vc) { FIRE_RING(NULL); continue; } BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1); OUT_RING (((nr - 1) << 24) | start); start += nr; } nr = vc >> 8; while (nr) { unsigned push = nr > 2047 ? 2047 : nr; nr -= push; BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push); while (push--) { OUT_RING(((0x100 - 1) << 24) | start); start += 0x100; } } BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (0); count -= vc; start = restart; } return TRUE; }
static void nv30_miptree_transfer_del(struct pipe_context *pipe, struct pipe_transfer *ptx) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_transfer *tx = nv30_transfer(ptx); if (ptx->usage & PIPE_TRANSFER_WRITE) nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img); nouveau_bo_ref(NULL, &tx->tmp.bo); pipe_resource_reference(&ptx->resource, NULL); FREE(tx); }
void nv30_query_init(struct pipe_context *pipe) { struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; pipe->create_query = nv30_query_create; pipe->destroy_query = nv30_query_destroy; pipe->begin_query = nv30_query_begin; pipe->end_query = nv30_query_end; pipe->get_query_result = nv30_query_result; if (eng3d->oclass >= NV40_3D_CLASS) pipe->render_condition = nv40_query_render_condition; }