2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "pipe/p_context.h"
27 #include "pipe/p_state.h"
28 #include "util/u_inlines.h"
29 #include "util/u_format.h"
30 #include "translate/translate.h"
32 #include "nouveau/nv_object.xml.h"
33 #include "nv30-40_3d.xml.h"
34 #include "nv30_context.h"
35 #include "nv30_resource.h"
38 struct nouveau_pushbuf
*push
;
45 uint32_t vertex_words
;
46 uint32_t packet_vertex_limit
;
48 struct translate
*translate
;
50 boolean primitive_restart
;
52 uint32_t restart_index
;
55 static INLINE
unsigned
56 prim_restart_search_i08(uint8_t *elts
, unsigned push
, uint8_t index
)
59 for (i
= 0; i
< push
; ++i
)
65 static INLINE
unsigned
66 prim_restart_search_i16(uint16_t *elts
, unsigned push
, uint16_t index
)
69 for (i
= 0; i
< push
; ++i
)
75 static INLINE
unsigned
76 prim_restart_search_i32(uint32_t *elts
, unsigned push
, uint32_t index
)
79 for (i
= 0; i
< push
; ++i
)
86 emit_vertices_i08(struct push_context
*ctx
, unsigned start
, unsigned count
)
88 uint8_t *elts
= (uint8_t *)ctx
->idxbuf
+ start
;
91 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
95 if (ctx
->primitive_restart
)
96 nr
= prim_restart_search_i08(elts
, push
, ctx
->restart_index
);
98 size
= ctx
->vertex_words
* nr
;
100 BEGIN_NI04(ctx
->push
, NV30_3D(VERTEX_DATA
), size
);
102 ctx
->translate
->run_elts8(ctx
->translate
, elts
, nr
, 0, ctx
->push
->cur
);
104 ctx
->push
->cur
+= size
;
109 BEGIN_NV04(ctx
->push
, NV30_3D(VB_ELEMENT_U32
), 1);
110 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
118 emit_vertices_i16(struct push_context
*ctx
, unsigned start
, unsigned count
)
120 uint16_t *elts
= (uint16_t *)ctx
->idxbuf
+ start
;
123 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
127 if (ctx
->primitive_restart
)
128 nr
= prim_restart_search_i16(elts
, push
, ctx
->restart_index
);
130 size
= ctx
->vertex_words
* nr
;
132 BEGIN_NI04(ctx
->push
, NV30_3D(VERTEX_DATA
), size
);
134 ctx
->translate
->run_elts16(ctx
->translate
, elts
, nr
, 0, ctx
->push
->cur
);
136 ctx
->push
->cur
+= size
;
141 BEGIN_NV04(ctx
->push
, NV30_3D(VB_ELEMENT_U32
), 1);
142 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
150 emit_vertices_i32(struct push_context
*ctx
, unsigned start
, unsigned count
)
152 uint32_t *elts
= (uint32_t *)ctx
->idxbuf
+ start
;
155 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
159 if (ctx
->primitive_restart
)
160 nr
= prim_restart_search_i32(elts
, push
, ctx
->restart_index
);
162 size
= ctx
->vertex_words
* nr
;
164 BEGIN_NI04(ctx
->push
, NV30_3D(VERTEX_DATA
), size
);
166 ctx
->translate
->run_elts(ctx
->translate
, elts
, nr
, 0, ctx
->push
->cur
);
168 ctx
->push
->cur
+= size
;
173 BEGIN_NV04(ctx
->push
, NV30_3D(VB_ELEMENT_U32
), 1);
174 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
182 emit_vertices_seq(struct push_context
*ctx
, unsigned start
, unsigned count
)
185 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
186 unsigned size
= ctx
->vertex_words
* push
;
188 BEGIN_NI04(ctx
->push
, NV30_3D(VERTEX_DATA
), size
);
190 ctx
->translate
->run(ctx
->translate
, start
, push
, 0, ctx
->push
->cur
);
191 ctx
->push
->cur
+= size
;
198 nv30_push_vbo(struct nv30_context
*nv30
, const struct pipe_draw_info
*info
)
200 struct push_context ctx
;
201 unsigned i
, index_size
;
202 boolean apply_bias
= info
->indexed
&& info
->index_bias
;
204 ctx
.push
= nv30
->base
.pushbuf
;
205 ctx
.translate
= nv30
->vertex
->translate
;
206 ctx
.packet_vertex_limit
= nv30
->vertex
->vtx_per_packet_max
;
207 ctx
.vertex_words
= nv30
->vertex
->vtx_size
;
209 for (i
= 0; i
< nv30
->num_vtxbufs
; ++i
) {
211 struct pipe_vertex_buffer
*vb
= &nv30
->vtxbuf
[i
];
212 struct nv04_resource
*res
= nv04_resource(vb
->buffer
);
214 if (!vb
->buffer
&& !vb
->user_buffer
) {
218 data
= nouveau_resource_map_offset(&nv30
->base
, res
,
219 vb
->buffer_offset
, NOUVEAU_BO_RD
);
222 data
+= info
->index_bias
* vb
->stride
;
224 ctx
.translate
->set_buffer(ctx
.translate
, i
, data
, vb
->stride
, ~0);
228 if (nv30
->idxbuf
.buffer
)
229 ctx
.idxbuf
= nouveau_resource_map_offset(&nv30
->base
,
230 nv04_resource(nv30
->idxbuf
.buffer
), nv30
->idxbuf
.offset
,
233 ctx
.idxbuf
= nv30
->idxbuf
.user_buffer
;
235 nv30_state_release(nv30
);
238 index_size
= nv30
->idxbuf
.index_size
;
239 ctx
.primitive_restart
= info
->primitive_restart
;
240 ctx
.restart_index
= info
->restart_index
;
244 ctx
.primitive_restart
= FALSE
;
245 ctx
.restart_index
= 0;
248 if (nv30
->screen
->eng3d
->oclass
>= NV40_3D_CLASS
) {
249 BEGIN_NV04(ctx
.push
, NV40_3D(PRIM_RESTART_ENABLE
), 2);
250 PUSH_DATA (ctx
.push
, info
->primitive_restart
);
251 PUSH_DATA (ctx
.push
, info
->restart_index
);
252 nv30
->state
.prim_restart
= info
->primitive_restart
;
255 ctx
.prim
= nv30_prim_gl(info
->mode
);
257 PUSH_RESET(ctx
.push
, BUFCTX_IDXBUF
);
258 BEGIN_NV04(ctx
.push
, NV30_3D(VERTEX_BEGIN_END
), 1);
259 PUSH_DATA (ctx
.push
, ctx
.prim
);
260 switch (index_size
) {
262 emit_vertices_seq(&ctx
, info
->start
, info
->count
);
265 emit_vertices_i08(&ctx
, info
->start
, info
->count
);
268 emit_vertices_i16(&ctx
, info
->start
, info
->count
);
271 emit_vertices_i32(&ctx
, info
->start
, info
->count
);
277 BEGIN_NV04(ctx
.push
, NV30_3D(VERTEX_BEGIN_END
), 1);
278 PUSH_DATA (ctx
.push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
281 nouveau_resource_unmap(nv04_resource(nv30
->idxbuf
.buffer
));
283 for (i
= 0; i
< nv30
->num_vtxbufs
; ++i
) {
284 if (nv30
->vtxbuf
[i
].buffer
) {
285 nouveau_resource_unmap(nv04_resource(nv30
->vtxbuf
[i
].buffer
));
289 nv30_state_release(nv30
);