static boolean nv40_draw_elements_inline(struct pipe_context *pipe, struct pipe_buffer *ib, unsigned ib_size, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); struct pipe_winsys *ws = pipe->winsys; void *map; map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); return FALSE; } switch (ib_size) { case 1: nv40_draw_elements_u08(nv40, map, mode, start, count); break; case 2: nv40_draw_elements_u16(nv40, map, mode, start, count); break; case 4: nv40_draw_elements_u32(nv40, map, mode, start, count); break; default: NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); break; } ws->buffer_unmap(ws, ib); return TRUE; }
static boolean nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, boolean wait, uint64_t *result) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); struct nouveau_winsys *nvws = nv40->nvws; assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); if (!q->ready) { unsigned status; status = nvws->notifier_status(nv40->screen->query, q->object->start); if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { if (wait == FALSE) return FALSE; nvws->notifier_wait(nv40->screen->query, q->object->start, NV_NOTIFY_STATE_STATUS_COMPLETED, 0); } q->result = nvws->notifier_retval(nv40->screen->query, q->object->start); q->ready = TRUE; nvws->res_free(&q->object); } *result = q->result; return TRUE; }
static void nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); /* Happens when end_query() is called, then another begin_query() * without querying the result in-between. For now we'll wait for * the existing query to notify completion, but it could be better. */ if (q->object) { uint64_t tmp; pipe->get_query_result(pipe, pq, 1, &tmp); } if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) assert(0); nv40->nvws->notifier_reset(nv40->screen->query, q->object->start); BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1); OUT_RING (1); BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1); OUT_RING (1); q->ready = FALSE; }
boolean nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); struct nouveau_channel *chan = nv40->nvws->channel; unsigned restart; nv40_vbo_set_idxbuf(nv40, NULL, 0); if (FORCE_SWTNL || !nv40_state_validate(nv40)) { return nv40_draw_elements_swtnl(pipe, NULL, 0, mode, start, count); } while (count) { unsigned vc, nr; nv40_state_emit(nv40); vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, mode, start, count, &restart); if (!vc) { FIRE_RING(NULL); continue; } BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); OUT_RING (nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { BEGIN_RING(curie, NV40TCL_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(curie, NV40TCL_VB_VERTEX_BATCH, push); while (push--) { OUT_RING(((0x100 - 1) << 24) | start); start += 0x100; } } BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); OUT_RING (0); count -= vc; start = restart; } pipe->flush(pipe, 0, NULL); return TRUE; }
static void nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); nv40->fragprog = hwcso; nv40->dirty |= NV40_NEW_FRAGPROG; }
static void nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); nv40->blend = hwcso; nv40->dirty |= NV40_NEW_BLEND; }
static void nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); nv40->zsa = hwcso; nv40->dirty |= NV40_NEW_ZSA; }
static void nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); nv40->vertprog = hwcso; nv40->dirty |= NV40_NEW_VERTPROG; nv40->draw_dirty |= NV40_NEW_VERTPROG; }
static void nv40_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) { struct nv40_context *nv40 = nv40_context(pipe); nv40->edgeflags = bitfield; nv40->dirty |= NV40_NEW_ARRAYS; nv40->draw_dirty |= NV40_NEW_ARRAYS; }
static void nv40_set_scissor_state(struct pipe_context *pipe, const struct pipe_scissor_state *s) { struct nv40_context *nv40 = nv40_context(pipe); nv40->scissor = *s; nv40->dirty |= NV40_NEW_SCISSOR; }
static void nv40_set_polygon_stipple(struct pipe_context *pipe, const struct pipe_poly_stipple *stipple) { struct nv40_context *nv40 = nv40_context(pipe); memcpy(nv40->stipple, stipple->stipple, 4 * 32); nv40->dirty |= NV40_NEW_STIPPLE; }
static void nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); nv40->rasterizer = hwcso; nv40->dirty |= NV40_NEW_RAST; nv40->draw_dirty |= NV40_NEW_RAST; }
static void nv40_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct nv40_context *nv40 = nv40_context(pipe); nv40->framebuffer = *fb; nv40->dirty |= NV40_NEW_FB; }
static void nv40_set_blend_color(struct pipe_context *pipe, const struct pipe_blend_color *bcol) { struct nv40_context *nv40 = nv40_context(pipe); nv40->blend_colour = *bcol; nv40->dirty |= NV40_NEW_BCOL; }
static void nv40_set_clip_state(struct pipe_context *pipe, const struct pipe_clip_state *clip) { struct nv40_context *nv40 = nv40_context(pipe); nv40->clip = *clip; nv40->dirty |= NV40_NEW_UCP; nv40->draw_dirty |= NV40_NEW_UCP; }
static void nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); if (q->object) nv40->nvws->res_free(&q->object); FREE(q); }
static void nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_fragment_program *fp = hwcso; nv40_fragprog_destroy(nv40, fp); FREE((void*)fp->pipe.tokens); FREE(fp); }
static void nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, unsigned width, unsigned height, unsigned value) { struct nv40_context *nv40 = nv40_context(pipe); struct nv04_surface_2d *eng2d = nv40->screen->eng2d; eng2d->fill(eng2d, dest, destx, desty, width, height, value); }
static void nv40_set_viewport_state(struct pipe_context *pipe, const struct pipe_viewport_state *vpt) { struct nv40_context *nv40 = nv40_context(pipe); nv40->viewport = *vpt; nv40->dirty |= NV40_NEW_VIEWPORT; nv40->draw_dirty |= NV40_NEW_VIEWPORT; }
static void nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); BEGIN_RING(curie, NV40TCL_QUERY_GET, 1); OUT_RING ((0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) | ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT)); FIRE_RING(NULL); }
static void nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_vertex_program *vp = hwcso; draw_delete_vertex_shader(nv40->draw, vp->draw); nv40_vertprog_destroy(nv40, vp); FREE((void*)vp->pipe.tokens); FREE(vp); }
static void * nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *cso) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); struct nouveau_stateobj *so = so_new(32, 0); struct nouveau_grobj *curie = nv40->screen->curie; so_method(so, curie, NV40TCL_DEPTH_FUNC, 3); so_data (so, nvgl_comparison_op(cso->depth.func)); so_data (so, cso->depth.writemask ? 1 : 0); so_data (so, cso->depth.enabled ? 1 : 0); so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3); so_data (so, cso->alpha.enabled ? 1 : 0); so_data (so, nvgl_comparison_op(cso->alpha.func)); so_data (so, float_to_ubyte(cso->alpha.ref_value)); if (cso->stencil[0].enabled) { so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 8); so_data (so, cso->stencil[0].enabled ? 1 : 0); so_data (so, cso->stencil[0].writemask); so_data (so, nvgl_comparison_op(cso->stencil[0].func)); so_data (so, cso->stencil[0].ref_value); so_data (so, cso->stencil[0].valuemask); so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); } else { so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); so_data (so, 0); } if (cso->stencil[1].enabled) { so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 8); so_data (so, cso->stencil[1].enabled ? 1 : 0); so_data (so, cso->stencil[1].writemask); so_data (so, nvgl_comparison_op(cso->stencil[1].func)); so_data (so, cso->stencil[1].ref_value); so_data (so, cso->stencil[1].valuemask); so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); } else { so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1); so_data (so, 0); } so_ref(so, &zsaso->so); so_ref(NULL, &so); zsaso->pipe = *cso; return (void *)zsaso; }
static void nv40_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 nv40_context *nv40 = nv40_context(pipe); struct nv04_surface_2d *eng2d = nv40->screen->eng2d; eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); }
static void nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_element *ve) { struct nv40_context *nv40 = nv40_context(pipe); memcpy(nv40->vtxelt, ve, sizeof(*ve) * count); nv40->vtxelt_nr = count; nv40->dirty |= NV40_NEW_ARRAYS; nv40->draw_dirty |= NV40_NEW_ARRAYS; }
static void nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *vb) { struct nv40_context *nv40 = nv40_context(pipe); memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count); nv40->vtxbuf_nr = count; nv40->dirty |= NV40_NEW_ARRAYS; nv40->draw_dirty |= NV40_NEW_ARRAYS; }
static boolean nv40_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); struct nouveau_channel *chan = nv40->nvws->channel; unsigned restart; while (count) { unsigned nr, vc; nv40_state_emit(nv40); vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, mode, start, count, &restart); if (!vc) { FIRE_RING(NULL); continue; } BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); OUT_RING (nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { BEGIN_RING(curie, NV40TCL_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(curie, NV40TCL_VB_INDEX_BATCH, push); while (push--) { OUT_RING(((0x100 - 1) << 24) | start); start += 0x100; } } BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); OUT_RING (0); count -= vc; start = restart; } return TRUE; }
static void * nv40_vp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_vertex_program *vp; vp = CALLOC(1, sizeof(struct nv40_vertex_program)); vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe); return (void *)vp; }
static void nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const struct pipe_constant_buffer *buf ) { struct nv40_context *nv40 = nv40_context(pipe); nv40->constbuf[shader] = buf->buffer; nv40->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); if (shader == PIPE_SHADER_VERTEX) { nv40->dirty |= NV40_NEW_VERTPROG; } else if (shader == PIPE_SHADER_FRAGMENT) { nv40->dirty |= NV40_NEW_FRAGPROG; } }
static void * nv40_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) { struct nv40_context *nv40 = nv40_context(pipe); struct nouveau_grobj *curie = nv40->screen->curie; struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(16, 0); if (cso->blend_enable) { so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); so_data (so, 1); so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | nvgl_blend_func(cso->rgb_src_factor)); so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | nvgl_blend_func(cso->rgb_dst_factor)); so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); so_data (so, nvgl_blend_eqn(cso->alpha_func) << 16 | nvgl_blend_eqn(cso->rgb_func)); } else { so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); so_data (so, 0); } so_method(so, curie, NV40TCL_COLOR_MASK, 1); so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); if (cso->logicop_enable) { so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); so_data (so, 1); so_data (so, nvgl_logicop_func(cso->logicop_func)); } else { so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1); so_data (so, 0); } so_method(so, curie, NV40TCL_DITHER_ENABLE, 1); so_data (so, cso->dither ? 1 : 0); so_ref(so, &bso->so); so_ref(NULL, &so); bso->pipe = *cso; return (void *)bso; }
static void nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) { struct nv40_context *nv40 = nv40_context(pipe); unsigned unit; for (unit = 0; unit < nr; unit++) { nv40->tex_sampler[unit] = sampler[unit]; nv40->dirty_samplers |= (1 << unit); } for (unit = nr; unit < nv40->nr_samplers; unit++) { nv40->tex_sampler[unit] = NULL; nv40->dirty_samplers |= (1 << unit); } nv40->nr_samplers = nr; nv40->dirty |= NV40_NEW_SAMPLER; }