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