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 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
224 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
225 OUT_RING (chan
, startInstance
);
226 while (instanceCount
--) {
227 if (AVAIL_RING(chan
) < (7 + 16*3)) {
229 if (!nv50_state_validate(nv50
, 7 + 16*3)) {
234 instance_step(nv50
, a
);
236 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
237 OUT_RING (chan
, prim
);
238 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BUFFER_FIRST
, 2);
239 OUT_RING (chan
, start
);
240 OUT_RING (chan
, count
);
241 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
249 nv50_draw_arrays(struct pipe_context
*pipe
, unsigned mode
, unsigned start
,
252 nv50_draw_arrays_instanced(pipe
, mode
, start
, count
, 0, 1);
256 struct nv50_context
*nv50
;
261 inline_elt08(void *priv
, unsigned start
, unsigned count
)
263 struct inline_ctx
*ctx
= priv
;
264 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
265 struct nouveau_channel
*chan
= tesla
->channel
;
266 uint8_t *map
= (uint8_t *)ctx
->map
+ start
;
269 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, 1);
270 OUT_RING (chan
, map
[0]);
279 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
, count
);
281 OUT_RING(chan
, (map
[1] << 16) | map
[0]);
287 inline_elt16(void *priv
, unsigned start
, unsigned count
)
289 struct inline_ctx
*ctx
= priv
;
290 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
291 struct nouveau_channel
*chan
= tesla
->channel
;
292 uint16_t *map
= (uint16_t *)ctx
->map
+ start
;
295 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, 1);
296 OUT_RING (chan
, map
[0]);
305 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
, count
);
307 OUT_RING(chan
, (map
[1] << 16) | map
[0]);
313 inline_elt32(void *priv
, unsigned start
, unsigned count
)
315 struct inline_ctx
*ctx
= priv
;
316 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
317 struct nouveau_channel
*chan
= tesla
->channel
;
319 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
, count
);
320 OUT_RINGp (chan
, (uint32_t *)ctx
->map
+ start
, count
);
324 inline_edgeflag(void *priv
, boolean enabled
)
326 struct inline_ctx
*ctx
= priv
;
327 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
328 struct nouveau_channel
*chan
= tesla
->channel
;
330 BEGIN_RING(chan
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
331 OUT_RING (chan
, enabled
? 1 : 0);
335 nv50_draw_elements_inline(struct pipe_context
*pipe
,
336 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
337 unsigned mode
, unsigned start
, unsigned count
,
338 unsigned startInstance
, unsigned instanceCount
)
340 struct pipe_screen
*pscreen
= pipe
->screen
;
341 struct nv50_context
*nv50
= nv50_context(pipe
);
342 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
343 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
344 struct instance a
[16];
345 struct inline_ctx ctx
;
346 struct u_split_prim s
;
350 overhead
= 16*3; /* potential instance adjustments */
351 overhead
+= 4; /* Begin()/End() */
352 overhead
+= 4; /* potential edgeflag disable/reenable */
353 overhead
+= 3; /* potentially 3 VTX_ELT_U16/U32 packet headers */
357 s
.emit
= inline_elt08
;
360 s
.emit
= inline_elt16
;
362 s
.emit
= inline_elt32
;
363 s
.edge
= inline_edgeflag
;
366 ctx
.map
= pipe_buffer_map(pscreen
, indexBuffer
, PIPE_BUFFER_USAGE_CPU_READ
);
371 instance_init(nv50
, a
, startInstance
);
372 if (!nv50_state_validate(nv50
, overhead
+ 6 + 3))
375 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
376 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
377 OUT_RING (chan
, startInstance
);
378 while (instanceCount
--) {
382 u_split_prim_init(&s
, mode
, start
, count
);
384 if (AVAIL_RING(chan
) < (overhead
+ 6)) {
386 if (!nv50_state_validate(nv50
, (overhead
+ 6))) {
392 max_verts
= AVAIL_RING(chan
) - overhead
;
393 if (max_verts
> 2047)
397 instance_step(nv50
, a
);
399 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
400 OUT_RING (chan
, nv50_prim(s
.mode
) | (nzi
? (1<<28) : 0));
401 done
= u_split_prim_next(&s
, max_verts
);
402 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
409 pipe_buffer_unmap(pscreen
, indexBuffer
);
413 nv50_draw_elements_instanced(struct pipe_context
*pipe
,
414 struct pipe_buffer
*indexBuffer
,
416 unsigned mode
, unsigned start
, unsigned count
,
417 unsigned startInstance
, unsigned instanceCount
)
419 struct nv50_context
*nv50
= nv50_context(pipe
);
420 struct nouveau_channel
*chan
= nv50
->screen
->tesla
->channel
;
421 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
422 struct instance a
[16];
423 unsigned prim
= nv50_prim(mode
);
425 if (!(indexBuffer
->usage
& PIPE_BUFFER_USAGE_INDEX
) ||
427 nv50_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
428 mode
, start
, count
, startInstance
,
433 instance_init(nv50
, a
, startInstance
);
434 if (!nv50_state_validate(nv50
, 13 + 16*3))
437 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
438 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
439 OUT_RING (chan
, startInstance
);
440 while (instanceCount
--) {
441 if (AVAIL_RING(chan
) < (7 + 16*3)) {
443 if (!nv50_state_validate(nv50
, 10 + 16*3)) {
448 instance_step(nv50
, a
);
450 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
451 OUT_RING (chan
, prim
);
452 if (indexSize
== 4) {
453 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U32
| 0x30000, 0);
454 OUT_RING (chan
, count
);
455 nouveau_pushbuf_submit(chan
, nouveau_bo(indexBuffer
),
456 start
<< 2, count
<< 2);
458 if (indexSize
== 2) {
459 unsigned vb_start
= (start
& ~1);
460 unsigned vb_end
= (start
+ count
+ 1) & ~1;
461 unsigned dwords
= (vb_end
- vb_start
) >> 1;
463 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16_SETUP
, 1);
464 OUT_RING (chan
, ((start
& 1) << 31) | count
);
465 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16
| 0x30000, 0);
466 OUT_RING (chan
, dwords
);
467 nouveau_pushbuf_submit(chan
, nouveau_bo(indexBuffer
),
468 vb_start
<< 1, dwords
<< 2);
469 BEGIN_RING(chan
, tesla
, NV50TCL_VB_ELEMENT_U16_SETUP
, 1);
472 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
480 nv50_draw_elements(struct pipe_context
*pipe
,
481 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
482 unsigned mode
, unsigned start
, unsigned count
)
484 nv50_draw_elements_instanced(pipe
, indexBuffer
, indexSize
,
485 mode
, start
, count
, 0, 1);
488 static INLINE boolean
489 nv50_vbo_static_attrib(struct nv50_context
*nv50
, unsigned attrib
,
490 struct nouveau_stateobj
**pso
,
491 struct pipe_vertex_element
*ve
,
492 struct pipe_vertex_buffer
*vb
)
495 struct nouveau_stateobj
*so
;
496 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
497 struct nouveau_bo
*bo
= nouveau_bo(vb
->buffer
);
500 unsigned nr_components
= util_format_get_nr_components(ve
->src_format
);
502 ret
= nouveau_bo_map(bo
, NOUVEAU_BO_RD
);
506 util_format_read_4f(ve
->src_format
, v
, 0, (uint8_t *)bo
->map
+
507 (vb
->buffer_offset
+ ve
->src_offset
), 0,
511 *pso
= so
= so_new(nv50
->vtxelt
->num_elements
,
512 nv50
->vtxelt
->num_elements
* 4, 0);
514 switch (nr_components
) {
516 so_method(so
, tesla
, NV50TCL_VTX_ATTR_4F_X(attrib
), 4);
517 so_data (so
, fui(v
[0]));
518 so_data (so
, fui(v
[1]));
519 so_data (so
, fui(v
[2]));
520 so_data (so
, fui(v
[3]));
523 so_method(so
, tesla
, NV50TCL_VTX_ATTR_3F_X(attrib
), 3);
524 so_data (so
, fui(v
[0]));
525 so_data (so
, fui(v
[1]));
526 so_data (so
, fui(v
[2]));
529 so_method(so
, tesla
, NV50TCL_VTX_ATTR_2F_X(attrib
), 2);
530 so_data (so
, fui(v
[0]));
531 so_data (so
, fui(v
[1]));
534 if (attrib
== nv50
->vertprog
->cfg
.edgeflag_in
) {
535 so_method(so
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
536 so_data (so
, v
[0] ? 1 : 0);
538 so_method(so
, tesla
, NV50TCL_VTX_ATTR_1F(attrib
), 1);
539 so_data (so
, fui(v
[0]));
542 nouveau_bo_unmap(bo
);
546 nouveau_bo_unmap(bo
);
551 nv50_vtxelt_construct(struct nv50_vtxelt_stateobj
*cso
)
555 for (i
= 0; i
< cso
->num_elements
; ++i
) {
556 struct pipe_vertex_element
*ve
= &cso
->pipe
[i
];
558 cso
->hw
[i
] = nv50_vbo_vtxelt_to_hw(ve
);
562 struct nouveau_stateobj
*
563 nv50_vbo_validate(struct nv50_context
*nv50
)
565 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
566 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
, *vtxattr
;
569 /* don't validate if Gallium took away our buffers */
570 if (nv50
->vtxbuf_nr
== 0)
573 assert(!NV50_USING_LOATHED_EDGEFLAG(nv50
));
575 n_ve
= MAX2(nv50
->vtxelt
->num_elements
, nv50
->state
.vtxelt_nr
);
578 vtxbuf
= so_new(n_ve
* 2, n_ve
* 5, nv50
->vtxelt
->num_elements
* 4);
579 vtxfmt
= so_new(1, n_ve
, 0);
580 so_method(vtxfmt
, tesla
, NV50TCL_VERTEX_ARRAY_ATTRIB(0), n_ve
);
582 for (i
= 0; i
< nv50
->vtxelt
->num_elements
; i
++) {
583 struct pipe_vertex_element
*ve
= &nv50
->vtxelt
->pipe
[i
];
584 struct pipe_vertex_buffer
*vb
=
585 &nv50
->vtxbuf
[ve
->vertex_buffer_index
];
586 struct nouveau_bo
*bo
= nouveau_bo(vb
->buffer
);
587 uint32_t hw
= nv50
->vtxelt
->hw
[i
];
590 nv50_vbo_static_attrib(nv50
, i
, &vtxattr
, ve
, vb
)) {
591 so_data(vtxfmt
, hw
| (1 << 4));
593 so_method(vtxbuf
, tesla
,
594 NV50TCL_VERTEX_ARRAY_FORMAT(i
), 1);
599 so_data(vtxfmt
, hw
| i
);
601 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_FORMAT(i
), 3);
602 so_data (vtxbuf
, 0x20000000 |
603 (ve
->instance_divisor
? 0 : vb
->stride
));
604 so_reloc (vtxbuf
, bo
, vb
->buffer_offset
+
605 ve
->src_offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
|
606 NOUVEAU_BO_RD
| NOUVEAU_BO_HIGH
, 0, 0);
607 so_reloc (vtxbuf
, bo
, vb
->buffer_offset
+
608 ve
->src_offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
|
609 NOUVEAU_BO_RD
| NOUVEAU_BO_LOW
, 0, 0);
611 /* vertex array limits */
612 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i
), 2);
613 so_reloc (vtxbuf
, bo
, vb
->buffer
->size
- 1,
614 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
|
615 NOUVEAU_BO_HIGH
, 0, 0);
616 so_reloc (vtxbuf
, bo
, vb
->buffer
->size
- 1,
617 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
|
618 NOUVEAU_BO_LOW
, 0, 0);
620 for (; i
< n_ve
; ++i
) {
621 so_data (vtxfmt
, 0x7e080010);
623 so_method(vtxbuf
, tesla
, NV50TCL_VERTEX_ARRAY_FORMAT(i
), 1);
626 nv50
->state
.vtxelt_nr
= nv50
->vtxelt
->num_elements
;
628 so_ref (vtxbuf
, &nv50
->state
.vtxbuf
);
629 so_ref (vtxattr
, &nv50
->state
.vtxattr
);
630 so_ref (NULL
, &vtxbuf
);
631 so_ref (NULL
, &vtxattr
);