1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2012 Red Hat Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * Authors: Ben Skeggs 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "pipe/p_context.h" 27bf215546Sopenharmony_ci#include "pipe/p_state.h" 28bf215546Sopenharmony_ci#include "util/u_inlines.h" 29bf215546Sopenharmony_ci#include "util/format/u_format.h" 30bf215546Sopenharmony_ci#include "translate/translate.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "nv_object.xml.h" 33bf215546Sopenharmony_ci#include "nv30/nv30-40_3d.xml.h" 34bf215546Sopenharmony_ci#include "nv30/nv30_context.h" 35bf215546Sopenharmony_ci#include "nv30/nv30_resource.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistruct push_context { 38bf215546Sopenharmony_ci struct nouveau_pushbuf *push; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci const void *idxbuf; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci float edgeflag; 43bf215546Sopenharmony_ci int edgeflag_attr; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci uint32_t vertex_words; 46bf215546Sopenharmony_ci uint32_t packet_vertex_limit; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci struct translate *translate; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci bool primitive_restart; 51bf215546Sopenharmony_ci uint32_t prim; 52bf215546Sopenharmony_ci uint32_t restart_index; 53bf215546Sopenharmony_ci}; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic inline unsigned 56bf215546Sopenharmony_ciprim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci unsigned i; 59bf215546Sopenharmony_ci for (i = 0; i < push; ++i) 60bf215546Sopenharmony_ci if (elts[i] == index) 61bf215546Sopenharmony_ci break; 62bf215546Sopenharmony_ci return i; 63bf215546Sopenharmony_ci} 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_cistatic inline unsigned 66bf215546Sopenharmony_ciprim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci unsigned i; 69bf215546Sopenharmony_ci for (i = 0; i < push; ++i) 70bf215546Sopenharmony_ci if (elts[i] == index) 71bf215546Sopenharmony_ci break; 72bf215546Sopenharmony_ci return i; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_cistatic inline unsigned 76bf215546Sopenharmony_ciprim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci unsigned i; 79bf215546Sopenharmony_ci for (i = 0; i < push; ++i) 80bf215546Sopenharmony_ci if (elts[i] == index) 81bf215546Sopenharmony_ci break; 82bf215546Sopenharmony_ci return i; 83bf215546Sopenharmony_ci} 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cistatic void 86bf215546Sopenharmony_ciemit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci uint8_t *elts = (uint8_t *)ctx->idxbuf + start; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci while (count) { 91bf215546Sopenharmony_ci unsigned push = MIN2(count, ctx->packet_vertex_limit); 92bf215546Sopenharmony_ci unsigned size, nr; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci nr = push; 95bf215546Sopenharmony_ci if (ctx->primitive_restart) 96bf215546Sopenharmony_ci nr = prim_restart_search_i08(elts, push, ctx->restart_index); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci size = ctx->vertex_words * nr; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci ctx->translate->run_elts8(ctx->translate, elts, nr, 0, 0, ctx->push->cur); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci ctx->push->cur += size; 105bf215546Sopenharmony_ci count -= nr; 106bf215546Sopenharmony_ci elts += nr; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci if (nr != push) { 109bf215546Sopenharmony_ci BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1); 110bf215546Sopenharmony_ci PUSH_DATA (ctx->push, ctx->restart_index); 111bf215546Sopenharmony_ci count--; 112bf215546Sopenharmony_ci elts++; 113bf215546Sopenharmony_ci } 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic void 118bf215546Sopenharmony_ciemit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci uint16_t *elts = (uint16_t *)ctx->idxbuf + start; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci while (count) { 123bf215546Sopenharmony_ci unsigned push = MIN2(count, ctx->packet_vertex_limit); 124bf215546Sopenharmony_ci unsigned size, nr; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci nr = push; 127bf215546Sopenharmony_ci if (ctx->primitive_restart) 128bf215546Sopenharmony_ci nr = prim_restart_search_i16(elts, push, ctx->restart_index); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci size = ctx->vertex_words * nr; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci ctx->translate->run_elts16(ctx->translate, elts, nr, 0, 0, ctx->push->cur); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci ctx->push->cur += size; 137bf215546Sopenharmony_ci count -= nr; 138bf215546Sopenharmony_ci elts += nr; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci if (nr != push) { 141bf215546Sopenharmony_ci BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1); 142bf215546Sopenharmony_ci PUSH_DATA (ctx->push, ctx->restart_index); 143bf215546Sopenharmony_ci count--; 144bf215546Sopenharmony_ci elts++; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_cistatic void 150bf215546Sopenharmony_ciemit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci uint32_t *elts = (uint32_t *)ctx->idxbuf + start; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci while (count) { 155bf215546Sopenharmony_ci unsigned push = MIN2(count, ctx->packet_vertex_limit); 156bf215546Sopenharmony_ci unsigned size, nr; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci nr = push; 159bf215546Sopenharmony_ci if (ctx->primitive_restart) 160bf215546Sopenharmony_ci nr = prim_restart_search_i32(elts, push, ctx->restart_index); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci size = ctx->vertex_words * nr; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci ctx->translate->run_elts(ctx->translate, elts, nr, 0, 0, ctx->push->cur); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci ctx->push->cur += size; 169bf215546Sopenharmony_ci count -= nr; 170bf215546Sopenharmony_ci elts += nr; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (nr != push) { 173bf215546Sopenharmony_ci BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1); 174bf215546Sopenharmony_ci PUSH_DATA (ctx->push, ctx->restart_index); 175bf215546Sopenharmony_ci count--; 176bf215546Sopenharmony_ci elts++; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic void 182bf215546Sopenharmony_ciemit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count) 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci while (count) { 185bf215546Sopenharmony_ci unsigned push = MIN2(count, ctx->packet_vertex_limit); 186bf215546Sopenharmony_ci unsigned size = ctx->vertex_words * push; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci ctx->translate->run(ctx->translate, start, push, 0, 0, ctx->push->cur); 191bf215546Sopenharmony_ci ctx->push->cur += size; 192bf215546Sopenharmony_ci count -= push; 193bf215546Sopenharmony_ci start += push; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_civoid 198bf215546Sopenharmony_cinv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info, 199bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 200bf215546Sopenharmony_ci{ 201bf215546Sopenharmony_ci struct push_context ctx; 202bf215546Sopenharmony_ci unsigned i, index_size; 203bf215546Sopenharmony_ci bool apply_bias = info->index_size && draw->index_bias; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci ctx.push = nv30->base.pushbuf; 206bf215546Sopenharmony_ci ctx.translate = nv30->vertex->translate; 207bf215546Sopenharmony_ci ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max; 208bf215546Sopenharmony_ci ctx.vertex_words = nv30->vertex->vtx_size; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci for (i = 0; i < nv30->num_vtxbufs; ++i) { 211bf215546Sopenharmony_ci uint8_t *data; 212bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i]; 213bf215546Sopenharmony_ci struct nv04_resource *res = nv04_resource(vb->buffer.resource); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (!vb->buffer.resource) { 216bf215546Sopenharmony_ci continue; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci data = nouveau_resource_map_offset(&nv30->base, res, 220bf215546Sopenharmony_ci vb->buffer_offset, NOUVEAU_BO_RD); 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci if (apply_bias) 223bf215546Sopenharmony_ci data += draw->index_bias * vb->stride; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci if (info->index_size) { 229bf215546Sopenharmony_ci if (!info->has_user_indices) 230bf215546Sopenharmony_ci ctx.idxbuf = nouveau_resource_map_offset(&nv30->base, 231bf215546Sopenharmony_ci nv04_resource(info->index.resource), draw->start * info->index_size, 232bf215546Sopenharmony_ci NOUVEAU_BO_RD); 233bf215546Sopenharmony_ci else 234bf215546Sopenharmony_ci ctx.idxbuf = (char*)info->index.user + draw->start * info->index_size; 235bf215546Sopenharmony_ci if (!ctx.idxbuf) { 236bf215546Sopenharmony_ci nv30_state_release(nv30); 237bf215546Sopenharmony_ci return; 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci index_size = info->index_size; 240bf215546Sopenharmony_ci ctx.primitive_restart = info->primitive_restart; 241bf215546Sopenharmony_ci ctx.restart_index = info->restart_index; 242bf215546Sopenharmony_ci } else { 243bf215546Sopenharmony_ci ctx.idxbuf = NULL; 244bf215546Sopenharmony_ci index_size = 0; 245bf215546Sopenharmony_ci ctx.primitive_restart = false; 246bf215546Sopenharmony_ci ctx.restart_index = 0; 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) { 250bf215546Sopenharmony_ci BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2); 251bf215546Sopenharmony_ci PUSH_DATA (ctx.push, info->primitive_restart); 252bf215546Sopenharmony_ci PUSH_DATA (ctx.push, info->restart_index); 253bf215546Sopenharmony_ci nv30->state.prim_restart = info->primitive_restart; 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci ctx.prim = nv30_prim_gl(info->mode); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci PUSH_RESET(ctx.push, BUFCTX_IDXBUF); 259bf215546Sopenharmony_ci BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); 260bf215546Sopenharmony_ci PUSH_DATA (ctx.push, ctx.prim); 261bf215546Sopenharmony_ci switch (index_size) { 262bf215546Sopenharmony_ci case 0: 263bf215546Sopenharmony_ci emit_vertices_seq(&ctx, draw->start, draw->count); 264bf215546Sopenharmony_ci break; 265bf215546Sopenharmony_ci case 1: 266bf215546Sopenharmony_ci emit_vertices_i08(&ctx, draw->start, draw->count); 267bf215546Sopenharmony_ci break; 268bf215546Sopenharmony_ci case 2: 269bf215546Sopenharmony_ci emit_vertices_i16(&ctx, draw->start, draw->count); 270bf215546Sopenharmony_ci break; 271bf215546Sopenharmony_ci case 4: 272bf215546Sopenharmony_ci emit_vertices_i32(&ctx, draw->start, draw->count); 273bf215546Sopenharmony_ci break; 274bf215546Sopenharmony_ci default: 275bf215546Sopenharmony_ci assert(0); 276bf215546Sopenharmony_ci break; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); 279bf215546Sopenharmony_ci PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (info->index_size && !info->has_user_indices) 282bf215546Sopenharmony_ci nouveau_resource_unmap(nv04_resource(info->index.resource)); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci for (i = 0; i < nv30->num_vtxbufs; ++i) { 285bf215546Sopenharmony_ci if (nv30->vtxbuf[i].buffer.resource) { 286bf215546Sopenharmony_ci nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer.resource)); 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci nv30_state_release(nv30); 291bf215546Sopenharmony_ci} 292