Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_push.c
4574 views
/*1* Copyright 2012 Red Hat Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21* Authors: Ben Skeggs22*23*/2425#include "pipe/p_context.h"26#include "pipe/p_state.h"27#include "util/u_inlines.h"28#include "util/format/u_format.h"29#include "translate/translate.h"3031#include "nv_object.xml.h"32#include "nv30/nv30-40_3d.xml.h"33#include "nv30/nv30_context.h"34#include "nv30/nv30_resource.h"3536struct push_context {37struct nouveau_pushbuf *push;3839const void *idxbuf;4041float edgeflag;42int edgeflag_attr;4344uint32_t vertex_words;45uint32_t packet_vertex_limit;4647struct translate *translate;4849bool primitive_restart;50uint32_t prim;51uint32_t restart_index;52};5354static inline unsigned55prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)56{57unsigned i;58for (i = 0; i < push; ++i)59if (elts[i] == index)60break;61return i;62}6364static inline unsigned65prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)66{67unsigned i;68for (i = 0; i < push; ++i)69if (elts[i] == index)70break;71return i;72}7374static inline unsigned75prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)76{77unsigned i;78for (i = 0; i < push; ++i)79if (elts[i] == index)80break;81return i;82}8384static void85emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)86{87uint8_t *elts = (uint8_t *)ctx->idxbuf + start;8889while (count) {90unsigned push = MIN2(count, ctx->packet_vertex_limit);91unsigned size, nr;9293nr = push;94if (ctx->primitive_restart)95nr = prim_restart_search_i08(elts, push, ctx->restart_index);9697size = ctx->vertex_words * nr;9899BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);100101ctx->translate->run_elts8(ctx->translate, elts, nr, 0, 0, ctx->push->cur);102103ctx->push->cur += size;104count -= nr;105elts += nr;106107if (nr != push) {108BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);109PUSH_DATA (ctx->push, ctx->restart_index);110count--;111elts++;112}113}114}115116static void117emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)118{119uint16_t *elts = (uint16_t *)ctx->idxbuf + start;120121while (count) {122unsigned push = MIN2(count, ctx->packet_vertex_limit);123unsigned size, nr;124125nr = push;126if (ctx->primitive_restart)127nr = prim_restart_search_i16(elts, push, ctx->restart_index);128129size = ctx->vertex_words * nr;130131BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);132133ctx->translate->run_elts16(ctx->translate, elts, nr, 0, 0, ctx->push->cur);134135ctx->push->cur += size;136count -= nr;137elts += nr;138139if (nr != push) {140BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);141PUSH_DATA (ctx->push, ctx->restart_index);142count--;143elts++;144}145}146}147148static void149emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)150{151uint32_t *elts = (uint32_t *)ctx->idxbuf + start;152153while (count) {154unsigned push = MIN2(count, ctx->packet_vertex_limit);155unsigned size, nr;156157nr = push;158if (ctx->primitive_restart)159nr = prim_restart_search_i32(elts, push, ctx->restart_index);160161size = ctx->vertex_words * nr;162163BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);164165ctx->translate->run_elts(ctx->translate, elts, nr, 0, 0, ctx->push->cur);166167ctx->push->cur += size;168count -= nr;169elts += nr;170171if (nr != push) {172BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);173PUSH_DATA (ctx->push, ctx->restart_index);174count--;175elts++;176}177}178}179180static void181emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)182{183while (count) {184unsigned push = MIN2(count, ctx->packet_vertex_limit);185unsigned size = ctx->vertex_words * push;186187BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);188189ctx->translate->run(ctx->translate, start, push, 0, 0, ctx->push->cur);190ctx->push->cur += size;191count -= push;192start += push;193}194}195196void197nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info,198const struct pipe_draw_start_count_bias *draw)199{200struct push_context ctx;201unsigned i, index_size;202bool apply_bias = info->index_size && draw->index_bias;203204ctx.push = nv30->base.pushbuf;205ctx.translate = nv30->vertex->translate;206ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max;207ctx.vertex_words = nv30->vertex->vtx_size;208209for (i = 0; i < nv30->num_vtxbufs; ++i) {210uint8_t *data;211struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i];212struct nv04_resource *res = nv04_resource(vb->buffer.resource);213214if (!vb->buffer.resource) {215continue;216}217218data = nouveau_resource_map_offset(&nv30->base, res,219vb->buffer_offset, NOUVEAU_BO_RD);220221if (apply_bias)222data += draw->index_bias * vb->stride;223224ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);225}226227if (info->index_size) {228if (!info->has_user_indices)229ctx.idxbuf = nouveau_resource_map_offset(&nv30->base,230nv04_resource(info->index.resource), draw->start * info->index_size,231NOUVEAU_BO_RD);232else233ctx.idxbuf = (char*)info->index.user + draw->start * info->index_size;234if (!ctx.idxbuf) {235nv30_state_release(nv30);236return;237}238index_size = info->index_size;239ctx.primitive_restart = info->primitive_restart;240ctx.restart_index = info->restart_index;241} else {242ctx.idxbuf = NULL;243index_size = 0;244ctx.primitive_restart = false;245ctx.restart_index = 0;246}247248if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {249BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2);250PUSH_DATA (ctx.push, info->primitive_restart);251PUSH_DATA (ctx.push, info->restart_index);252nv30->state.prim_restart = info->primitive_restart;253}254255ctx.prim = nv30_prim_gl(info->mode);256257PUSH_RESET(ctx.push, BUFCTX_IDXBUF);258BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);259PUSH_DATA (ctx.push, ctx.prim);260switch (index_size) {261case 0:262emit_vertices_seq(&ctx, draw->start, draw->count);263break;264case 1:265emit_vertices_i08(&ctx, draw->start, draw->count);266break;267case 2:268emit_vertices_i16(&ctx, draw->start, draw->count);269break;270case 4:271emit_vertices_i32(&ctx, draw->start, draw->count);272break;273default:274assert(0);275break;276}277BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);278PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP);279280if (info->index_size && !info->has_user_indices)281nouveau_resource_unmap(nv04_resource(info->index.resource));282283for (i = 0; i < nv30->num_vtxbufs; ++i) {284if (nv30->vtxbuf[i].buffer.resource) {285nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer.resource));286}287}288289nv30_state_release(nv30);290}291292293