1a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs/*
2a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * Copyright 2012 Red Hat Inc.
3a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs *
4a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
5a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * copy of this software and associated documentation files (the "Software"),
6a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * to deal in the Software without restriction, including without limitation
7a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the
9a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * Software is furnished to do so, subject to the following conditions:
10a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs *
11a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * The above copyright notice and this permission notice shall be included in
12a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * all copies or substantial portions of the Software.
13a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs *
14a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * SOFTWARE.
21a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs *
22a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs * Authors: Ben Skeggs
23a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs *
24a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs */
25a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
26a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "util/u_format.h"
27a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "util/u_inlines.h"
28a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "translate/translate.h"
29a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
30a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "nouveau/nouveau_fence.h"
31a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "nouveau/nv_object.xml.h"
32a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "nv30-40_3d.xml.h"
33a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "nv30_context.h"
34a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#include "nv30_format.h"
35a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
36a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
37a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_emit_vtxattr(struct nv30_context *nv30, struct pipe_vertex_buffer *vb,
38a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                  struct pipe_vertex_element *ve, unsigned attr)
39a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
40a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   const unsigned nc = util_format_get_nr_components(ve->src_format);
41a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
42a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv04_resource *res = nv04_resource(vb->buffer);
43a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   const void *data;
44a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   float v[4];
45a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
46a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset +
47a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                                      ve->src_offset, NOUVEAU_BO_RD);
48a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
49a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   util_format_read_4f(ve->src_format, v, 0, data, 0, 0, 0, 1, 1);
50a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
51a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   switch (nc) {
52a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   case 4:
53a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTX_ATTR_4F(attr)), 4);
54a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[0]);
55a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[1]);
56a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[2]);
57a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[3]);
58a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      break;
59a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   case 3:
60a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(attr)), 3);
61a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[0]);
62a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[1]);
63a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[2]);
64a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      break;
65a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   case 2:
66a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTX_ATTR_2F(attr)), 2);
67a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[0]);
68a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[1]);
69a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      break;
70a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   case 1:
71a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTX_ATTR_1F(attr)), 1);
72a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAf(push, v[0]);
73a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      break;
74a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   default:
75a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      assert(0);
76a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      break;
77a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
78a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
79a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
80a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic INLINE void
81a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vbuf_range(struct nv30_context *nv30, int vbi,
82a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                uint32_t *base, uint32_t *size)
83a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
84a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   assert(nv30->vbo_max_index != ~0);
85a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   *base = nv30->vbo_min_index * nv30->vtxbuf[vbi].stride;
86a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   *size = (nv30->vbo_max_index -
87a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30->vbo_min_index + 1) * nv30->vtxbuf[vbi].stride;
88a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
89a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
90a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
91a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_prevalidate_vbufs(struct nv30_context *nv30)
92a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
93a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct pipe_vertex_buffer *vb;
94a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv04_resource *buf;
95a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   int i;
96a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   uint32_t base, size;
97a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
98a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->vbo_fifo = nv30->vbo_user = 0;
99a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
100a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   for (i = 0; i < nv30->num_vtxbufs; i++) {
101a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      vb = &nv30->vtxbuf[i];
10289155ba71d9d3bb8f8b6ea095f75eaf38122e09cChristoph Bumiller      if (!vb->stride || !vb->buffer) /* NOTE: user_buffer not implemented */
103a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         continue;
104a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      buf = nv04_resource(vb->buffer);
105a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
106a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      /* NOTE: user buffers with temporary storage count as mapped by GPU */
107a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (!nouveau_resource_mapped_by_gpu(vb->buffer)) {
108a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (nv30->vbo_push_hint) {
109a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30->vbo_fifo = ~0;
110a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            continue;
111a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         } else {
112a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) {
113a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               nv30->vbo_user |= 1 << i;
114a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               assert(vb->stride > vb->buffer_offset);
115a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               nv30_vbuf_range(nv30, i, &base, &size);
116a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               nouveau_user_buffer_upload(&nv30->base, buf, base, size);
117a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            } else {
118a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               nouveau_buffer_migrate(&nv30->base, buf, NOUVEAU_BO_GART);
119a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            }
120a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30->base.vbo_dirty = TRUE;
121a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         }
122a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
123a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
124a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
125a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
126a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
127a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_update_user_vbufs(struct nv30_context *nv30)
128a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
129a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
130a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   uint32_t base, offset, size;
131a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   int i;
132a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   uint32_t written = 0;
133a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
134a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   for (i = 0; i < nv30->vertex->num_elements; i++) {
135a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      struct pipe_vertex_element *ve = &nv30->vertex->pipe[i];
136a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      const int b = ve->vertex_buffer_index;
137a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b];
138a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      struct nv04_resource *buf = nv04_resource(vb->buffer);
139a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
140a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (!(nv30->vbo_user & (1 << b)))
141a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         continue;
142a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
143a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (!vb->stride) {
144a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         nv30_emit_vtxattr(nv30, vb, ve, i);
145a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         continue;
146a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
147a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_vbuf_range(nv30, b, &base, &size);
148a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
149a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (!(written & (1 << b))) {
150a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         written |= 1 << b;
151a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         nouveau_user_buffer_upload(&nv30->base, buf, base, size);
152a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
153a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
154a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      offset = vb->buffer_offset + ve->src_offset;
155a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
156a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
157a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset,
158a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
159a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       0, NV30_3D_VTXBUF_DMA1);
160a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
161a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->base.vbo_dirty = TRUE;
162a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
163a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
164a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic INLINE void
165a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_release_user_vbufs(struct nv30_context *nv30)
166a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
167a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   uint32_t vbo_user = nv30->vbo_user;
168a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
169a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (vbo_user) {
170a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      int i = ffs(vbo_user) - 1;
171a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      vbo_user &= ~(1 << i);
172a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
173a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nouveau_buffer_release_gpu_storage(nv04_resource(nv30->vtxbuf[i].buffer));
174a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
175a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
176a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXTMP);
177a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
178a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
179a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsvoid
180a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vbo_validate(struct nv30_context *nv30)
181a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
182a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
183a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv30_vertex_stateobj *vertex = nv30->vertex;
184a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct pipe_vertex_element *ve;
185a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct pipe_vertex_buffer *vb;
186a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   unsigned i, redefine;
187a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
188a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
189a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (!nv30->vertex || nv30->draw_flags)
190a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      return;
191a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
192a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (unlikely(vertex->need_conversion)) {
193a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30->vbo_fifo = ~0;
194a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30->vbo_user = 0;
195a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   } else {
196a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_prevalidate_vbufs(nv30);
197a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
198a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
199a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (!PUSH_SPACE(push, 128))
200a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      return;
201a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
202a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts);
203a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine);
204a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
205a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   for (i = 0; i < vertex->num_elements; i++) {
206a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      ve = &vertex->pipe[i];
207a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      vb = &nv30->vtxbuf[ve->vertex_buffer_index];
208a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
209a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (likely(vb->stride) || nv30->vbo_fifo)
210a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state);
211a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      else
212a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
213a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
214a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
215a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   for (; i < nv30->state.num_vtxelts; i++) {
216a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
217a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
218a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
219a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   for (i = 0; i < vertex->num_elements; i++) {
220a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      struct nv04_resource *res;
221a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned offset;
222a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      boolean user;
223a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
224a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      ve = &vertex->pipe[i];
225a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      vb = &nv30->vtxbuf[ve->vertex_buffer_index];
226a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      user = (nv30->vbo_user & (1 << ve->vertex_buffer_index));
227a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
228a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      res = nv04_resource(vb->buffer);
229a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
230a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (nv30->vbo_fifo || unlikely(vb->stride == 0)) {
231a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (!nv30->vbo_fifo)
232a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30_emit_vtxattr(nv30, vb, ve, i);
233a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         continue;
234a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
235a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
236a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      offset = ve->src_offset + vb->buffer_offset;
237a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
238a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
239a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF,
240a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
241a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       0, NV30_3D_VTXBUF_DMA1);
242a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
243a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
244a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->state.num_vtxelts = vertex->num_elements;
245a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
246a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
247a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void *
248a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vertex_state_create(struct pipe_context *pipe, unsigned num_elements,
249a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                         const struct pipe_vertex_element *elements)
250a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
251a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    struct nv30_vertex_stateobj *so;
252a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    struct translate_key transkey;
253a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    unsigned i;
254a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
255a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    assert(num_elements);
256a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
257a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so = MALLOC(sizeof(*so) + sizeof(*so->element) * num_elements);
258a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    if (!so)
259a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        return NULL;
260a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
261a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so->num_elements = num_elements;
262a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so->need_conversion = FALSE;
263a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
264a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    transkey.nr_elements = 0;
265a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    transkey.output_stride = 0;
266a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
267a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    for (i = 0; i < num_elements; i++) {
268a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        const struct pipe_vertex_element *ve = &elements[i];
269a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        const unsigned vbi = ve->vertex_buffer_index;
270a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        enum pipe_format fmt = ve->src_format;
271a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
272a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
273a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        if (!so->element[i].state) {
274a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            switch (util_format_get_nr_components(fmt)) {
275a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            case 1: fmt = PIPE_FORMAT_R32_FLOAT; break;
276a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break;
277a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break;
278a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break;
279a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            default:
280a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                assert(0);
281a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                return NULL;
282a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            }
283a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
284a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            so->need_conversion = TRUE;
285a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        }
286a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
287a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        if (1) {
288a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            unsigned j = transkey.nr_elements++;
289a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
290a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
291a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].input_format = ve->src_format;
292a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].input_buffer = vbi;
293a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].input_offset = ve->src_offset;
294a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].instance_divisor = ve->instance_divisor;
295a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
296a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].output_format = fmt;
297a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.element[j].output_offset = transkey.output_stride;
298a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
299a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        }
300a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    }
301a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
302a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so->translate = translate_create(&transkey);
303a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so->vtx_size = transkey.output_stride / 4;
304a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    so->vtx_per_packet_max = NV04_PFIFO_MAX_PACKET_LEN / MAX2(so->vtx_size, 1);
305a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    return so;
306a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
307a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
308a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
309a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vertex_state_delete(struct pipe_context *pipe, void *hwcso)
310a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
311a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv30_vertex_stateobj *so = hwcso;
312a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
313a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (so->translate)
314a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      so->translate->release(so->translate);
315a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   FREE(hwcso);
316a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
317a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
318a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
319a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
320a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
321a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv30_context *nv30 = nv30_context(pipe);
322a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
323a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->vertex = hwcso;
324a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->dirty |= NV30_NEW_VERTEX;
325a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
326a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
327a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
328a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_draw_arrays(struct nv30_context *nv30,
329a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                 unsigned mode, unsigned start, unsigned count,
330a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                 unsigned instance_count)
331a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
332a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
333a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   unsigned prim;
334a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
335a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   prim = nv30_prim_gl(mode);
336a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
337a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
338a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   PUSH_DATA (push, prim);
339a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (count) {
340a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      const unsigned mpush = 2047 * 256;
341a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned npush  = (count > mpush) ? mpush : count;
342a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned wpush  = ((npush + 255) & ~255) >> 8;
343a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
344a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      count -= npush;
345a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
346a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), wpush);
347a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      while (npush >= 256) {
348a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, 0xff000000 | start);
349a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         start += 256;
350a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         npush -= 256;
351a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
352a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
353a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (npush)
354a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, ((npush - 1) << 24) | start);
355a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
356a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
357a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
358a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
359a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
360a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
361384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumillernv30_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map,
362a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                              unsigned start, unsigned count)
363a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
364a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   map += start;
365a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
366a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (count & 1) {
367a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
368a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, *map++);
369a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
370a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
371a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   count >>= 1;
372a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (count) {
373a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
374a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      count -= npush;
375a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
376a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
377a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      while (npush--) {
378a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, (map[1] << 16) | map[0]);
379a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         map += 2;
380a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
381a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
382a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
383a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
384a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
385a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
386384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumillernv30_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map,
387a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                              unsigned start, unsigned count)
388a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
389a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   map += start;
390a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
391a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (count & 1) {
392a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
393a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, *map++);
394a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
395a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
396a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   count >>= 1;
397a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (count) {
398a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
399a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      count -= npush;
400a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
401a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
402a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      while (npush--) {
403a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, (map[1] << 16) | map[0]);
404a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         map += 2;
405a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
406a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
407a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
408a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
409a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
410384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumillernv30_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map,
411a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                              unsigned start, unsigned count)
412a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
413a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   map += start;
414a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
415a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (count) {
416a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
417a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
418a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U32), nr);
419a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATAp(push, map, nr);
420a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
421a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      map += nr;
422a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      count -= nr;
423a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
424a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
425a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
426a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
427384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumillernv30_draw_elements_inline_u32_short(struct nouveau_pushbuf *push,
428384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller                                    const uint32_t *map,
429a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                                    unsigned start, unsigned count)
430a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
431a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   map += start;
432a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
433a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (count & 1) {
434a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
435a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, *map++);
436a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
437a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
438a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   count >>= 1;
439a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   while (count) {
440a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);;
441a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      count -= npush;
442a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
443a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
444a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      while (npush--) {
445a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, (map[1] << 16) | map[0]);
446a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         map += 2;
447a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
448a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
449a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
450a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
451a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
452a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_draw_elements(struct nv30_context *nv30, boolean shorten,
453a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                   unsigned mode, unsigned start, unsigned count,
454a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                   unsigned instance_count, int32_t index_bias)
455a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
456a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   const unsigned index_size = nv30->idxbuf.index_size;
457a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
458a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_object *eng3d = nv30->screen->eng3d;
459a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   unsigned prim = nv30_prim_gl(mode);
460a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
461a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#if 0 /*XXX*/
462a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (index_bias != nv30->state.index_bias) {
463a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1);
464a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, index_bias);
465a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30->state.index_bias = index_bias;
466a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
467a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs#endif
468a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
469a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 &&
470384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller       nv30->idxbuf.buffer) {
471a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer);
472a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      unsigned offset = nv30->idxbuf.offset;
473a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
474384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller      assert(nouveau_resource_mapped_by_gpu(&res->base));
475384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller
476a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2);
477a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset,
478a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
479a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo,
480a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       (index_size == 2) ? 0x00000010 : 0x00000000,
481a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       res->domain | NOUVEAU_BO_RD,
482a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       0, NV30_3D_IDXBUF_FORMAT_DMA1);
483a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
484a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, prim);
485a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      while (count) {
486a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         const unsigned mpush = 2047 * 256;
487a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         unsigned npush  = (count > mpush) ? mpush : count;
488a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         unsigned wpush  = ((npush + 255) & ~255) >> 8;
489a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
490a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         count -= npush;
491a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
492a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush);
493a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         while (npush >= 256) {
494a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            PUSH_DATA (push, 0xff000000 | start);
495a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            start += 256;
496a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            npush -= 256;
497a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         }
498a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
499a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (npush)
500a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            PUSH_DATA (push, ((npush - 1) << 24) | start);
501a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
502a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
503a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
504a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_RESET(push, BUFCTX_IDXBUF);
505a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   } else {
506384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller      const void *data;
507384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller      if (nv30->idxbuf.buffer)
508384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller         data = nouveau_resource_map_offset(&nv30->base,
509384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller                                            nv04_resource(nv30->idxbuf.buffer),
510384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller                                            nv30->idxbuf.offset, NOUVEAU_BO_RD);
511384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller      else
512384ef28cb376eb53c43167f0e8f0f7c3fec7d288Christoph Bumiller         data = nv30->idxbuf.user_buffer;
513a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (!data)
514a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         return;
515a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
516a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
517a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, prim);
518a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      switch (index_size) {
519a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      case 1:
520a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         nv30_draw_elements_inline_u08(push, data, start, count);
521a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         break;
522a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      case 2:
523a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         nv30_draw_elements_inline_u16(push, data, start, count);
524a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         break;
525a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      case 4:
526a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (shorten)
527a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30_draw_elements_inline_u32_short(push, data, start, count);
528a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         else
529a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            nv30_draw_elements_inline_u32(push, data, start, count);
530a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         break;
531a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      default:
532a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         assert(0);
533a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         return;
534a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
535a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
536a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
537a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
538a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
539a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
540a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsstatic void
541a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
542a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
543a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nv30_context *nv30 = nv30_context(pipe);
544a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   struct nouveau_pushbuf *push = nv30->base.pushbuf;
545a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
546a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   /* For picking only a few vertices from a large user buffer, push is better,
547a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    * if index count is larger and we expect repeated vertices, suggest upload.
548a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs    */
549a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->vbo_push_hint = /* the 64 is heuristic */
550a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      !(info->indexed &&
551a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs        ((info->max_index - info->min_index + 64) < info->count));
552a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
553a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->vbo_min_index = info->min_index;
554a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30->vbo_max_index = info->max_index;
555a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
556a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (nv30->vbo_push_hint != !!nv30->vbo_fifo)
557a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30->dirty |= NV30_NEW_ARRAYS;
558a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
559a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   push->user_priv = &nv30->bufctx;
560a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (nv30->vbo_user && !(nv30->dirty & (NV30_NEW_VERTEX | NV30_NEW_ARRAYS)))
561a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_update_user_vbufs(nv30);
562a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
563a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30_state_validate(nv30, TRUE);
564a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (nv30->draw_flags) {
565a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_render_vbo(pipe, info);
566a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      return;
567a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   } else
568a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (nv30->vbo_fifo) {
569a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_push_vbo(nv30, info);
570a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      return;
571a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
572a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
573a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (nv30->base.vbo_dirty) {
574a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
575a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      PUSH_DATA (push, 0);
576a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30->base.vbo_dirty = FALSE;
577a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
578a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
579a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   if (!info->indexed) {
580a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_draw_arrays(nv30,
581a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       info->mode, info->start, info->count,
582a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                       info->instance_count);
583a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   } else {
584a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      boolean shorten = info->max_index <= 65535;
585a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
586a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (info->primitive_restart != nv30->state.prim_restart) {
587a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (info->primitive_restart) {
588a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 2);
589a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            PUSH_DATA (push, 1);
590a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            PUSH_DATA (push, info->restart_index);
591a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
592a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            if (info->restart_index > 65535)
593a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs               shorten = FALSE;
594a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         } else {
595a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 1);
596a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            PUSH_DATA (push, 0);
597a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         }
598a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         nv30->state.prim_restart = info->primitive_restart;
599a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      } else
600a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      if (info->primitive_restart) {
601a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         BEGIN_NV04(push, NV40_3D(PRIM_RESTART_INDEX), 1);
602a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         PUSH_DATA (push, info->restart_index);
603a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
604a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs         if (info->restart_index > 65535)
605a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs            shorten = FALSE;
606a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      }
607a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
608a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs      nv30_draw_elements(nv30, shorten,
609a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                         info->mode, info->start, info->count,
610a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs                         info->instance_count, info->index_bias);
611a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   }
612a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
613a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30_state_release(nv30);
614a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   nv30_release_user_vbufs(nv30);
615a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
616a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs
617a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsvoid
618a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggsnv30_vbo_init(struct pipe_context *pipe)
619a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs{
620a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   pipe->create_vertex_elements_state = nv30_vertex_state_create;
621a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   pipe->delete_vertex_elements_state = nv30_vertex_state_delete;
622a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   pipe->bind_vertex_elements_state = nv30_vertex_state_bind;
623a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs   pipe->draw_vbo = nv30_draw_vbo;
624a2fc42b899de22273c1df96091bfb5c636075cb0Ben Skeggs}
625