2 * Copyright 2008 Ben Skeggs
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
23 #include "pipe/p_context.h"
24 #include "pipe/p_state.h"
25 #include "util/u_inlines.h"
26 #include "util/u_format.h"
28 #include "nouveau/nouveau_util.h"
29 #include "nv50_context.h"
31 #define NV50_USING_LOATHED_EDGEFLAG(ctx) ((ctx)->vertprog->cfg.edgeflag_in < 16)
33 static INLINE
unsigned
34 nv50_prim(unsigned mode
)
37 case PIPE_PRIM_POINTS
: return NV50TCL_VERTEX_BEGIN_POINTS
;
38 case PIPE_PRIM_LINES
: return NV50TCL_VERTEX_BEGIN_LINES
;
39 case PIPE_PRIM_LINE_LOOP
: return NV50TCL_VERTEX_BEGIN_LINE_LOOP
;
40 case PIPE_PRIM_LINE_STRIP
: return NV50TCL_VERTEX_BEGIN_LINE_STRIP
;
41 case PIPE_PRIM_TRIANGLES
: return NV50TCL_VERTEX_BEGIN_TRIANGLES
;
42 case PIPE_PRIM_TRIANGLE_STRIP
:
43 return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP
;
44 case PIPE_PRIM_TRIANGLE_FAN
: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN
;
45 case PIPE_PRIM_QUADS
: return NV50TCL_VERTEX_BEGIN_QUADS
;
46 case PIPE_PRIM_QUAD_STRIP
: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP
;
47 case PIPE_PRIM_POLYGON
: return NV50TCL_VERTEX_BEGIN_POLYGON
;
48 case PIPE_PRIM_LINES_ADJACENCY
:
49 return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY
;
50 case PIPE_PRIM_LINE_STRIP_ADJACENCY
:
51 return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY
;
52 case PIPE_PRIM_TRIANGLES_ADJACENCY
:
53 return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY
;
54 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
:
55 return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY
;
60 NOUVEAU_ERR("invalid primitive type %d\n", mode
);
61 return NV50TCL_VERTEX_BEGIN_POINTS
;
64 static INLINE
uint32_t
65 nv50_vbo_type_to_hw(enum pipe_format format
)
67 const struct util_format_description
*desc
;
69 desc
= util_format_description(format
);
72 switch (desc
->channel
[0].type
) {
73 case UTIL_FORMAT_TYPE_FLOAT
:
74 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT
;
75 case UTIL_FORMAT_TYPE_UNSIGNED
:
76 if (desc
->channel
[0].normalized
) {
77 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM
;
79 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED
;
80 case UTIL_FORMAT_TYPE_SIGNED
:
81 if (desc
->channel
[0].normalized
) {
82 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM
;
84 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED
;
86 case PIPE_FORMAT_TYPE_UINT:
87 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UINT;
88 case PIPE_FORMAT_TYPE_SINT:
89 return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SINT; */
95 static INLINE
uint32_t
96 nv50_vbo_size_to_hw(unsigned size
, unsigned nr_c
)
98 static const uint32_t hw_values
[] = {
100 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_8
,
101 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_8_8
,
102 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_8_8_8
,
103 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_8_8_8_8
,
104 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_16
,
105 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_16_16
,
106 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_16_16_16
,
107 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_16_16_16_16
,
109 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_32
,
110 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_32_32
,
111 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_32_32_32
,
112 NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_32_32_32_32
};
114 /* we'd also have R11G11B10 and R10G10B10A2 */
116 assert(nr_c
> 0 && nr_c
<= 4);
122 return hw_values
[size
+ (nr_c
- 1)];
125 static INLINE
uint32_t
126 nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element
*ve
)
128 uint32_t hw_type
, hw_size
;
129 enum pipe_format pf
= ve
->src_format
;
130 const struct util_format_description
*desc
;
131 unsigned size
, nr_components
;
133 desc
= util_format_description(pf
);
136 size
= util_format_get_component_bits(pf
, UTIL_FORMAT_COLORSPACE_RGB
, 0);
137 nr_components
= util_format_get_nr_components(pf
);
139 hw_type
= nv50_vbo_type_to_hw(pf
);
140 hw_size
= nv50_vbo_size_to_hw(size
, nr_components
);
142 if (!hw_type
|| !hw_size
) {
143 NOUVEAU_ERR("unsupported vbo format: %s\n", util_format_name(pf
));
148 if (desc
->swizzle
[0] == UTIL_FORMAT_SWIZZLE_Z
) /* BGRA */
149 hw_size
|= (1 << 31); /* no real swizzle bits :-( */
151 return (hw_type
| hw_size
);
155 struct nouveau_bo
*bo
;
163 instance_init(struct nv50_context
*nv50
, struct instance
*a
, unsigned first
)
167 for (i
= 0; i
< nv50
->vtxelt
->num_elements
; i
++) {
168 struct pipe_vertex_element
*ve
= &nv50
->vtxelt
->pipe
[i
];
169 struct pipe_vertex_buffer
*vb
;
171 a
[i
].divisor
= ve
->instance_divisor
;
173 vb
= &nv50
->vtxbuf
[ve
->vertex_buffer_index
];
175 a
[i
].bo
= nouveau_bo(vb
->buffer
);
176 a
[i
].stride
= vb
->stride
;
177 a
[i
].step
= first
% a
[i
].divisor
;
178 a
[i
].delta
= vb
->buffer_offset
+ ve
->src_offset
+
179 (first
* a
[i
].stride
);
185 instance_step(struct nv50_context
*nv50
, struct instance
*a
)
187 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
188 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
191 for (i
= 0; i
< nv50
->vtxelt
->num_elements
; i
++) {
195 BEGIN_RING(chan
, tesla
,
196 NV50TCL_VERTEX_ARRAY_START_HIGH(i
), 2);
197 OUT_RELOCh(chan
, a
[i
].bo
, a
[i
].delta
, NOUVEAU_BO_RD
|
198 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
);
199 OUT_RELOCl(chan
, a
[i
].bo
, a
[i
].delta
, NOUVEAU_BO_RD
|
200 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
);
201 if (++a
[i
].step
== a
[i
].divisor
) {
203 a
[i
].delta
+= a
[i
].stride
;
209 nv50_draw_arrays_instanced(struct pipe_context
*pipe
,
210 unsigned mode
, unsigned start
, unsigned count
,
211 unsigned startInstance
, unsigned instanceCount
)
213 struct nv50_context
*nv50
= nv50_context(pipe
);
214 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
215 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
216 struct instance a
[16];
217 unsigned prim
= nv50_prim(mode
);
219 instance_init(nv50
, a
, startInstance
);
220 if (!nv50_state_validate(nv50
, 10 + 16*3))
223 if (nv50
->vbo_fifo
) {
224 nv50_push_elements_instanced(pipe
, NULL
, 0, mode
, start
,
225 count
, startInstance
,
230 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
231 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
232 OUT_RING (chan
, startInstance
);
233 while (instanceCount
--) {
234 if (AVAIL_RING(chan
) < (7 + 16*3)) {
236 if (!nv50_state_validate(nv50
, 7 + 16*3)) {
241 instance_step(nv50
, a
);
243 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
244 OUT_RING (chan
, prim
);
245 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BUFFER_FIRST
, 2);
246 OUT_RING (chan
, start
);
247 OUT_RING (chan
, count
);
248 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
256 nv50_draw_arrays(struct pipe_context
*pipe
, unsigned mode
, unsigned start
,
259 nv50_draw_arrays_instanced(pipe
, mode
, start
, count
, 0, 1);
263 struct nv50_context
*nv50
;
268 inline_elt08(void *priv
, unsigned start
, unsigned count
)
270 struct inline_ctx
*ctx
= priv
;
271 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
272 struct nouveau_channel
*chan
= tesla
->channel
;
273 uint8_t *map
= (uint8_t *)ctx
->map
+ start
;
276 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, 1);
277 OUT_RING (chan
, map
[0]);
286 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
, count
);
288 OUT_RING(chan
, (map
[1] << 16) | map
[0]);
294 inline_elt16(void *priv
, unsigned start
, unsigned count
)
296 struct inline_ctx
*ctx
= priv
;
297 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
298 struct nouveau_channel
*chan
= tesla
->channel
;
299 uint16_t *map
= (uint16_t *)ctx
->map
+ start
;
302 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, 1);
303 OUT_RING (chan
, map
[0]);
312 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
, count
);
314 OUT_RING(chan
, (map
[1] << 16) | map
[0]);
320 inline_elt32(void *priv
, unsigned start
, unsigned count
)
322 struct inline_ctx
*ctx
= priv
;
323 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
324 struct nouveau_channel
*chan
= tesla
->channel
;
326 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, count
);
327 OUT_RINGp (chan
, (uint32_t *)ctx
->map
+ start
, count
);
331 inline_edgeflag(void *priv
, boolean enabled
)
333 struct inline_ctx
*ctx
= priv
;
334 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
335 struct nouveau_channel
*chan
= tesla
->channel
;
337 BEGIN_RING(chan
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
338 OUT_RING (chan
, enabled
? 1 : 0);
342 nv50_draw_elements_inline(struct pipe_context
*pipe
,
343 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
344 unsigned mode
, unsigned start
, unsigned count
,
345 unsigned startInstance
, unsigned instanceCount
)
347 struct pipe_screen
*pscreen
= pipe
->screen
;
348 struct nv50_context
*nv50
= nv50_context(pipe
);
349 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
350 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
351 struct instance a
[16];
352 struct inline_ctx ctx
;
353 struct u_split_prim s
;
357 overhead
= 16*3; /* potential instance adjustments */
358 overhead
+= 4; /* Begin()/End() */
359 overhead
+= 4; /* potential edgeflag disable/reenable */
360 overhead
+= 3; /* potentially 3 VTX_ELT_U16/U32 packet headers */
364 s
.emit
= inline_elt08
;
367 s
.emit
= inline_elt16
;
369 s
.emit
= inline_elt32
;
370 s
.edge
= inline_edgeflag
;
373 ctx
.map
= pipe_buffer_map(pscreen
, indexBuffer
, PIPE_BUFFER_USAGE_CPU_READ
);
378 instance_init(nv50
, a
, startInstance
);
379 if (!nv50_state_validate(nv50
, overhead
+ 6 + 3))
382 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
383 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
384 OUT_RING (chan
, startInstance
);
385 while (instanceCount
--) {
389 u_split_prim_init(&s
, mode
, start
, count
);
391 if (AVAIL_RING(chan
) < (overhead
+ 6)) {
393 if (!nv50_state_validate(nv50
, (overhead
+ 6))) {
399 max_verts
= AVAIL_RING(chan
) - overhead
;
400 if (max_verts
> 2047)
404 instance_step(nv50
, a
);
406 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
407 OUT_RING (chan
, nv50_prim(s
.mode
) | (nzi
? (1<<28) : 0));
408 done
= u_split_prim_next(&s
, max_verts
);
409 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
416 pipe_buffer_unmap(pscreen
, indexBuffer
);
420 nv50_draw_elements_instanced(struct pipe_context
*pipe
,
421 struct pipe_buffer
*indexBuffer
,
423 unsigned mode
, unsigned start
, unsigned count
,
424 unsigned startInstance
, unsigned instanceCount
)
426 struct nv50_context
*nv50
= nv50_context(pipe
);
427 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
428 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
429 struct instance a
[16];
430 unsigned prim
= nv50_prim(mode
);
432 instance_init(nv50
, a
, startInstance
);
433 if (!nv50_state_validate(nv50
, 13 + 16*3))
436 if (nv50
->vbo_fifo
) {
437 nv50_push_elements_instanced(pipe
, indexBuffer
, indexSize
,
438 mode
, start
, count
, startInstance
,
442 if (!(indexBuffer
->usage
& PIPE_BUFFER_USAGE_INDEX
) || indexSize
== 1) {
443 nv50_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
444 mode
, start
, count
, startInstance
,
449 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
450 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
451 OUT_RING (chan
, startInstance
);
452 while (instanceCount
--) {
453 if (AVAIL_RING(chan
) < (7 + 16*3)) {
455 if (!nv50_state_validate(nv50
, 10 + 16*3)) {
460 instance_step(nv50
, a
);
462 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
463 OUT_RING (chan
, prim
);
464 if (indexSize
== 4) {
465 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
| 0x30000, 0);
466 OUT_RING (chan
, count
);
467 nouveau_pushbuf_submit(chan
, nouveau_bo(indexBuffer
),
468 start
<< 2, count
<< 2);
470 if (indexSize
== 2) {
471 unsigned vb_start
= (start
& ~1);
472 unsigned vb_end
= (start
+ count
+ 1) & ~1;
473 unsigned dwords
= (vb_end
- vb_start
) >> 1;
475 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16_SETUP
, 1);
476 OUT_RING (chan
, ((start
& 1) << 31) | count
);
477 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
| 0x30000, 0);
478 OUT_RING (chan
, dwords
);
479 nouveau_pushbuf_submit(chan
, nouveau_bo(indexBuffer
),
480 vb_start
<< 1, dwords
<< 2);
481 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16_SETUP
, 1);
484 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
492 nv50_draw_elements(struct pipe_context
*pipe
,
493 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
494 unsigned mode
, unsigned start
, unsigned count
)
496 nv50_draw_elements_instanced(pipe
, indexBuffer
, indexSize
,
497 mode
, start
, count
, 0, 1);
500 static INLINE boolean
501 nv50_vbo_static_attrib(struct nv50_context
*nv50
, unsigned attrib
,
502 struct nouveau_stateobj
**pso
,
503 struct pipe_vertex_element
*ve
,
504 struct pipe_vertex_buffer
*vb
)
507 struct nouveau_stateobj
*so
;
508 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
509 struct nouveau_bo
*bo
= nouveau_bo(vb
->buffer
);
512 unsigned nr_components
= util_format_get_nr_components(ve
->src_format
);
514 ret
= nouveau_bo_map(bo
, NOUVEAU_BO_RD
);
518 util_format_read_4f(ve
->src_format
, v
, 0, (uint8_t *)bo
->map
+
519 (vb
->buffer_offset
+ ve
->src_offset
), 0,
523 *pso
= so
= so_new(nv50
->vtxelt
->num_elements
,
524 nv50
->vtxelt
->num_elements
* 4, 0);
526 switch (nr_components
) {
528 so_method(so
, tesla
, NV50TCL_VTX_ATTR_4F_X(attrib
), 4);
529 so_data (so
, fui(v
[0]));
530 so_data (so
, fui(v
[1]));
531 so_data (so
, fui(v
[2]));
532 so_data (so
, fui(v
[3]));
535 so_method(so
, tesla
, NV50TCL_VTX_ATTR_3F_X(attrib
), 3);
536 so_data (so
, fui(v
[0]));
537 so_data (so
, fui(v
[1]));
538 so_data (so
, fui(v
[2]));
541 so_method(so
, tesla
, NV50TCL_VTX_ATTR_2F_X(attrib
), 2);
542 so_data (so
, fui(v
[0]));
543 so_data (so
, fui(v
[1]));
546 if (attrib
== nv50
->vertprog
->cfg
.edgeflag_in
) {
547 so_method(so
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
548 so_data (so
, v
[0] ? 1 : 0);
550 so_method(so
, tesla
, NV50TCL_VTX_ATTR_1F(attrib
), 1);
551 so_data (so
, fui(v
[0]));
554 nouveau_bo_unmap(bo
);
558 nouveau_bo_unmap(bo
);
563 nv50_vtxelt_construct(struct nv50_vtxelt_stateobj
*cso
)
567 for (i
= 0; i
< cso
->num_elements
; ++i
) {
568 struct pipe_vertex_element
*ve
= &cso
->pipe
[i
];
570 cso
->hw
[i
] = nv50_vbo_vtxelt_to_hw(ve
);
574 struct nouveau_stateobj
*
575 nv50_vbo_validate(struct nv50_context
*nv50
)
577 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
578 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
, *vtxattr
;
581 /* don't validate if Gallium took away our buffers */
582 if (nv50
->vtxbuf_nr
== 0)
585 if (NV50_USING_LOATHED_EDGEFLAG(nv50
))
586 nv50
->vbo_fifo
= 0xffff;
587 nv50
->vbo_fifo
= 0xffff;
589 n_ve
= MAX2(nv50
->vtxelt
->num_elements
, nv50
->state
.vtxelt_nr
);
592 vtxbuf
= so_new(n_ve
* 2, n_ve
* 5, nv50
->vtxelt
->num_elements
* 4);
593 vtxfmt
= so_new(1, n_ve
, 0);
594 so_method(vtxfmt
, tesla
, NV50TCL_VERTEX_ARRAY_ATTRIB(0), n_ve
);
596 for (i
= 0; i
< nv50
->vtxelt
->num_elements
; i
++) {
597 struct pipe_vertex_element
*ve
= &nv50
->vtxelt
->pipe
[i
];
598 struct pipe_vertex_buffer
*vb
=
599 &nv50
->vtxbuf
[ve
->vertex_buffer_index
];
600 struct nouveau_bo
*bo
= nouveau_bo(vb
->buffer
);
601 uint32_t hw
= nv50
->vtxelt
->hw
[i
];
604 nv50_vbo_static_attrib(nv50
, i
, &vtxattr
, ve
, vb
)) {
605 so_data(vtxfmt
, hw
| (1 << 4));
607 so_method(vtxbuf
, tesla
,
608 NV50TCL_VERTEX_ARRAY_FORMAT(i
), 1);
611 nv50
->vbo_fifo
&= ~(1 << i
);
615 if (nv50
->vbo_fifo
) {
616 so_data (vtxfmt
, hw
| (ve
->instance_divisor
? (1 << 4) : i
));
617 so_method(vtxbuf
, tesla
,
618 NV50TCL_VERTEX_ARRAY_FORMAT(i
), 1);
623 so_data(vtxfmt
, hw
| i
);
625 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_FORMAT(i
), 3);
626 so_data (vtxbuf
, 0x20000000 |
627 (ve
->instance_divisor
? 0 : vb
->stride
));
628 so_reloc (vtxbuf
, bo
, vb
->buffer_offset
+
629 ve
->src_offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
|
630 NOUVEAU_BO_RD
| NOUVEAU_BO_HIGH
, 0, 0);
631 so_reloc (vtxbuf
, bo
, vb
->buffer_offset
+
632 ve
->src_offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
|
633 NOUVEAU_BO_RD
| NOUVEAU_BO_LOW
, 0, 0);
635 /* vertex array limits */
636 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i
), 2);
637 so_reloc (vtxbuf
, bo
, vb
->buffer
->size
- 1,
638 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
|
639 NOUVEAU_BO_HIGH
, 0, 0);
640 so_reloc (vtxbuf
, bo
, vb
->buffer
->size
- 1,
641 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
|
642 NOUVEAU_BO_LOW
, 0, 0);
644 for (; i
< n_ve
; ++i
) {
645 so_data (vtxfmt
, 0x7e080010);
647 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_FORMAT(i
), 1);
650 nv50
->state
.vtxelt_nr
= nv50
->vtxelt
->num_elements
;
652 so_ref (vtxbuf
, &nv50
->state
.vtxbuf
);
653 so_ref (vtxattr
, &nv50
->state
.vtxattr
);
654 so_ref (NULL
, &vtxbuf
);
655 so_ref (NULL
, &vtxattr
);