14c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
24c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "pipe/p_context.h"
34c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "pipe/p_state.h"
44c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "util/u_inlines.h"
54c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "util/u_format.h"
64c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "translate/translate.h"
74c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
84c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "nvc0_context.h"
94c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "nvc0_resource.h"
104c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
114c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#include "nvc0_3d.xml.h"
124c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
134c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstruct push_context {
146d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller   struct nouveau_pushbuf *push;
154c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
164c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   void *idxbuf;
174c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
185655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   uint32_t vertex_words;
194c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   uint32_t packet_vertex_limit;
204c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
214c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   struct translate *translate;
225655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
235655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   boolean primitive_restart;
247b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   boolean need_vertex_id;
255655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   uint32_t prim;
265655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   uint32_t restart_index;
27a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller   uint32_t instance_id;
2807f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
2907f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   struct {
3007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      int buffer;
3107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      float value;
3207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      uint8_t *data;
3307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      unsigned offset;
3407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      unsigned stride;
3507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   } edgeflag;
364c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller};
374c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
3807f73577af29d68a245283be65b12aca244c0690Christoph Bumillerstatic void
3907f73577af29d68a245283be65b12aca244c0690Christoph Bumillerinit_push_context(struct nvc0_context *nvc0, struct push_context *ctx)
4007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller{
4107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   struct pipe_vertex_element *ve;
4207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
436d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller   ctx->push = nvc0->base.pushbuf;
4407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   ctx->translate = nvc0->vertex->translate;
4507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
467b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   if (likely(nvc0->vertex->num_elements < 32))
477b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      ctx->need_vertex_id = nvc0->vertprog->vp.need_vertex_id;
487b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   else
497b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      ctx->need_vertex_id = FALSE;
507b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
517b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   ctx->edgeflag.buffer = -1;
5207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   ctx->edgeflag.value = 0.5f;
5307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
547b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   if (unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) {
5507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ve = &nvc0->vertex->element[nvc0->vertprog->vp.edgeflag].pipe;
5607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx->edgeflag.buffer = ve->vertex_buffer_index;
5707f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx->edgeflag.offset = ve->src_offset;
5807f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx->packet_vertex_limit = 1;
5907f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   } else {
6007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx->packet_vertex_limit = nvc0->vertex->vtx_per_packet_max;
617b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->need_vertex_id))
627b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller         ctx->packet_vertex_limit = 1;
6307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   }
6407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
6507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   ctx->vertex_words = nvc0->vertex->vtx_size;
6607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller}
6707f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
6807f73577af29d68a245283be65b12aca244c0690Christoph Bumillerstatic INLINE void
6907f73577af29d68a245283be65b12aca244c0690Christoph Bumillerset_edgeflag(struct push_context *ctx, unsigned vtx_id)
7007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller{
7107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   float f = *(float *)(ctx->edgeflag.data + vtx_id * ctx->edgeflag.stride);
7207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
7307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   if (ctx->edgeflag.value != f) {
7407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx->edgeflag.value = f;
756d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      IMMED_NVC0(ctx->push, NVC0_3D(EDGEFLAG), f ? 1 : 0);
7607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   }
7707f73577af29d68a245283be65b12aca244c0690Christoph Bumiller}
7807f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
797b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumillerstatic INLINE void
807b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumillerset_vertexid(struct push_context *ctx, uint32_t vtx_id)
817b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller{
827b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller#if 0
836d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller   BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_ID), 1); /* broken on nvc0 */
847b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller#else
856d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller   BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_DATA), 1); /* as last attribute */
867b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller#endif
876d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller   PUSH_DATA (ctx->push, vtx_id);
887b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller}
897b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
905655f8d42d919270791588162399ac7a2c718733Christoph Bumillerstatic INLINE unsigned
915655f8d42d919270791588162399ac7a2c718733Christoph Bumillerprim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
925655f8d42d919270791588162399ac7a2c718733Christoph Bumiller{
935655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   unsigned i;
945655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   for (i = 0; i < push; ++i)
955655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (elts[i] == index)
965655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         break;
975655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   return i;
985655f8d42d919270791588162399ac7a2c718733Christoph Bumiller}
995655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1005655f8d42d919270791588162399ac7a2c718733Christoph Bumillerstatic INLINE unsigned
1015655f8d42d919270791588162399ac7a2c718733Christoph Bumillerprim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
1025655f8d42d919270791588162399ac7a2c718733Christoph Bumiller{
1035655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   unsigned i;
1045655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   for (i = 0; i < push; ++i)
1055655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (elts[i] == index)
1065655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         break;
1075655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   return i;
1085655f8d42d919270791588162399ac7a2c718733Christoph Bumiller}
1095655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1105655f8d42d919270791588162399ac7a2c718733Christoph Bumillerstatic INLINE unsigned
1115655f8d42d919270791588162399ac7a2c718733Christoph Bumillerprim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
1125655f8d42d919270791588162399ac7a2c718733Christoph Bumiller{
1135655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   unsigned i;
1145655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   for (i = 0; i < push; ++i)
1155655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (elts[i] == index)
1165655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         break;
1175655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   return i;
1185655f8d42d919270791588162399ac7a2c718733Christoph Bumiller}
1195655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1204c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstatic void
1214c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumilleremit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
1224c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
12307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   uint8_t *restrict elts = (uint8_t *)ctx->idxbuf + start;
1244c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
1254c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   while (count) {
1264c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      unsigned push = MIN2(count, ctx->packet_vertex_limit);
1275655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      unsigned size, nr;
1285655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1295655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      nr = push;
1305655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (ctx->primitive_restart)
1315655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         nr = prim_restart_search_i08(elts, push, ctx->restart_index);
1325655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1337b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
13407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         set_edgeflag(ctx, elts[0]);
13507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
1365655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      size = ctx->vertex_words * nr;
1374c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
1386d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
1394c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
140a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller      ctx->translate->run_elts8(ctx->translate, elts, nr, ctx->instance_id,
1416d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller                                ctx->push->cur);
1426d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      ctx->push->cur += size;
1437b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
1447b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->need_vertex_id) && likely(size))
1457b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller         set_vertexid(ctx, elts[0]);
1467b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
147703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      count -= nr;
148703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      elts += nr;
1495655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1505655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (nr != push) {
151703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         count--;
152703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         elts++;
1536d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
1546d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, 0);
1556d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
156a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller                    (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
1575655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      }
1584c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
1594c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
1604c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
1614c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstatic void
1624c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumilleremit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
1634c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
16407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   uint16_t *restrict elts = (uint16_t *)ctx->idxbuf + start;
1654c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
1664c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   while (count) {
1674c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      unsigned push = MIN2(count, ctx->packet_vertex_limit);
1685655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      unsigned size, nr;
1695655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1705655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      nr = push;
1715655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (ctx->primitive_restart)
1725655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         nr = prim_restart_search_i16(elts, push, ctx->restart_index);
1735655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1747b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
17507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         set_edgeflag(ctx, elts[0]);
17607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
1775655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      size = ctx->vertex_words * nr;
1784c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
1796d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
1804c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
181a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller      ctx->translate->run_elts16(ctx->translate, elts, nr, ctx->instance_id,
1826d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller                                 ctx->push->cur);
1836d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      ctx->push->cur += size;
1847b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
1857b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->need_vertex_id))
1867b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller         set_vertexid(ctx, elts[0]);
1877b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
188703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      count -= nr;
189703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      elts += nr;
1905655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
1915655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (nr != push) {
192703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         count--;
193703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         elts++;
1946d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
1956d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, 0);
1966d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
197a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller                    (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
1985655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      }
1994c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
2004c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
2014c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2024c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstatic void
2034c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumilleremit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
2044c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
20507f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   uint32_t *restrict elts = (uint32_t *)ctx->idxbuf + start;
2064c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2074c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   while (count) {
2084c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      unsigned push = MIN2(count, ctx->packet_vertex_limit);
2095655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      unsigned size, nr;
2105655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
2115655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      nr = push;
2125655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (ctx->primitive_restart)
2135655f8d42d919270791588162399ac7a2c718733Christoph Bumiller         nr = prim_restart_search_i32(elts, push, ctx->restart_index);
2145655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
2157b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
21607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         set_edgeflag(ctx, elts[0]);
21707f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
2185655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      size = ctx->vertex_words * nr;
2194c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2206d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
2214c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
222a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller      ctx->translate->run_elts(ctx->translate, elts, nr, ctx->instance_id,
2236d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller                               ctx->push->cur);
2246d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      ctx->push->cur += size;
2257b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
2267b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->need_vertex_id))
2277b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller         set_vertexid(ctx, elts[0]);
2287b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
229703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      count -= nr;
230703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller      elts += nr;
2315655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
2325655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      if (nr != push) {
233703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         count--;
234703f3597ad0e2b7134d4ea0fc2194eb67161910aChristoph Bumiller         elts++;
2356d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
2366d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, 0);
2376d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller         PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
238a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller                    (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
2395655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      }
2404c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
2414c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
2424c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2434c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstatic void
2444c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumilleremit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
2454c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
2464c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   while (count) {
2474c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      unsigned push = MIN2(count, ctx->packet_vertex_limit);
2485655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      unsigned size = ctx->vertex_words * push;
2494c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
25007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      if (unlikely(ctx->edgeflag.buffer >= 0))
25107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         set_edgeflag(ctx, start);
25207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
2536d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
2544c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
255a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller      ctx->translate->run(ctx->translate, start, push, ctx->instance_id,
2566d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller                          ctx->push->cur);
2576d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      ctx->push->cur += size;
2587b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
2597b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      if (unlikely(ctx->need_vertex_id))
2607b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller         set_vertexid(ctx, start);
2617b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
2624c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      count -= push;
2634c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      start += push;
2644c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
2654c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
2664c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2674c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2684c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller#define NVC0_PRIM_GL_CASE(n) \
2694c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
2704c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2714c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillerstatic INLINE unsigned
2724c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillernvc0_prim_gl(unsigned prim)
2734c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
2744c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   switch (prim) {
2754c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(POINTS);
2764c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(LINES);
2774c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(LINE_LOOP);
2784c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(LINE_STRIP);
2794c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(TRIANGLES);
2804c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(TRIANGLE_STRIP);
2814c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(TRIANGLE_FAN);
2824c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(QUADS);
2834c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(QUAD_STRIP);
2844c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(POLYGON);
2854c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(LINES_ADJACENCY);
2864c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
2874c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
2884c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
2894c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   /*
2904c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   NVC0_PRIM_GL_CASE(PATCHES); */
2914c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   default:
2924c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
2934c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      break;
2944c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
2954c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
2964c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
2974c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillervoid
2984c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumillernvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
2994c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller{
3004c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   struct push_context ctx;
3014c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   unsigned i, index_size;
30214bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller   unsigned inst_count = info->instance_count;
30314bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller   unsigned vert_count = info->count;
30449f16c96f150b192bfd6828ae4ba03afe3a7b8f3Christoph Bumiller   boolean apply_bias = info->indexed && info->index_bias;
3054c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
30607f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   init_push_context(nvc0, &ctx);
3074c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
3084c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   for (i = 0; i < nvc0->num_vtxbufs; ++i) {
3094c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      uint8_t *data;
3104c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i];
3114826cd0f6125b071530026143ffd8205d84b3d5eBen Skeggs      struct nv04_resource *res = nv04_resource(vb->buffer);
3124c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
3131ba8e9510812f155359d380bda6876cdee5ba21eBen Skeggs      data = nouveau_resource_map_offset(&nvc0->base, res,
3144826cd0f6125b071530026143ffd8205d84b3d5eBen Skeggs                                         vb->buffer_offset, NOUVEAU_BO_RD);
31549f16c96f150b192bfd6828ae4ba03afe3a7b8f3Christoph Bumiller
31649f16c96f150b192bfd6828ae4ba03afe3a7b8f3Christoph Bumiller      if (apply_bias && likely(!(nvc0->vertex->instance_bufs & (1 << i))))
3174c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         data += info->index_bias * vb->stride;
3184c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
3194c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
32007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
32107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      if (unlikely(i == ctx.edgeflag.buffer)) {
32207f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         ctx.edgeflag.data = data + ctx.edgeflag.offset;
32307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         ctx.edgeflag.stride = vb->stride;
32407f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      }
3254c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
3264c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
3274c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   if (info->indexed) {
32807f73577af29d68a245283be65b12aca244c0690Christoph Bumiller      ctx.idxbuf =
32907f73577af29d68a245283be65b12aca244c0690Christoph Bumiller         nouveau_resource_map_offset(&nvc0->base,
33007f73577af29d68a245283be65b12aca244c0690Christoph Bumiller                                     nv04_resource(nvc0->idxbuf.buffer),
33107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller                                     nvc0->idxbuf.offset, NOUVEAU_BO_RD);
3324c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      if (!ctx.idxbuf)
3334c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         return;
3344c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      index_size = nvc0->idxbuf.index_size;
3355655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      ctx.primitive_restart = info->primitive_restart;
3365655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      ctx.restart_index = info->restart_index;
3374c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   } else {
3384c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      ctx.idxbuf = NULL;
3394c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      index_size = 0;
3405655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      ctx.primitive_restart = FALSE;
3415655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      ctx.restart_index = 0;
34214bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller
34314bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller      if (info->count_from_stream_output) {
34414bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         struct pipe_context *pipe = &nvc0->base.pipe;
34514bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         struct nvc0_so_target *targ;
34614bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         targ = nvc0_so_target(info->count_from_stream_output);
3474445e170bee23a3607ece0e010adef7058ac6a11Marek Olšák         pipe->get_query_result(pipe, targ->pq, TRUE, (void*)&vert_count);
34814bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         vert_count /= targ->stride;
34914bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller      }
3504c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
3514c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
352a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller   ctx.instance_id = info->start_instance;
3535655f8d42d919270791588162399ac7a2c718733Christoph Bumiller   ctx.prim = nvc0_prim_gl(info->mode);
3545655f8d42d919270791588162399ac7a2c718733Christoph Bumiller
3557b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   if (unlikely(ctx.need_vertex_id)) {
3567b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      const unsigned a = nvc0->vertex->num_elements;
3576d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1);
3586d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      PUSH_DATA (ctx.push, (a << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) |
3597b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller                 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
3607b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller                 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
3616d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 1);
3626d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      PUSH_DATA (ctx.push, (((0x80 + a * 0x10) / 4) << 4) | 1);
3637b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   }
3647b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
36514bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller   while (inst_count--) {
3666d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);
3676d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      PUSH_DATA (ctx.push, ctx.prim);
3684c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      switch (index_size) {
3694c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      case 0:
37014bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         emit_vertices_seq(&ctx, info->start, vert_count);
3714c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         break;
3724c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      case 1:
37314bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         emit_vertices_i08(&ctx, info->start, vert_count);
3744c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         break;
3754c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      case 2:
37614bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         emit_vertices_i16(&ctx, info->start, vert_count);
3774c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         break;
3784c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      case 4:
37914bd9d764802b5fedb652c791faafe4d13b65262Christoph Bumiller         emit_vertices_i32(&ctx, info->start, vert_count);
3804c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         break;
3814c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      default:
3824c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         assert(0);
3834c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller         break;
3844c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller      }
3856d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);
3864c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
387a4742c6a07179f01eebfc486e6cd21be05d9c8aeChristoph Bumiller      ctx.instance_id++;
3885655f8d42d919270791588162399ac7a2c718733Christoph Bumiller      ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
3894c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   }
3904c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
39107f73577af29d68a245283be65b12aca244c0690Christoph Bumiller   if (unlikely(ctx.edgeflag.value == 0.0f))
3926d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);
39307f73577af29d68a245283be65b12aca244c0690Christoph Bumiller
3947b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   if (unlikely(ctx.need_vertex_id)) {
3957b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller      const unsigned a = nvc0->vertex->num_elements;
3966d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);
3976d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1);
3986d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      PUSH_DATA (ctx.push,
3997b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller                 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |
4007b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller                 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
4017b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller                 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
4027b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller   }
4037b6881932a71b36dd47f63200c9dbee8e2b9af4fChristoph Bumiller
4044c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller   if (info->indexed)
4054826cd0f6125b071530026143ffd8205d84b3d5eBen Skeggs      nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer));
4064c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller
407c024c1d75fdce72fe2de2d6b987b796fc9561115Christoph Bumiller   for (i = 0; i < nvc0->num_vtxbufs; ++i)
4084826cd0f6125b071530026143ffd8205d84b3d5eBen Skeggs      nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer));
4094c2247538394a313e1e90bfcd07c1ab9c7d41281Christoph Bumiller}
410