2 * Copyright (C) 2009-2010 Francisco Jerez.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "nouveau_driver.h"
28 #include "nouveau_bufferobj.h"
29 #include "nouveau_util.h"
31 #include "main/bufferobj.h"
32 #include "main/glformats.h"
33 #include "main/varray.h"
34 #include "main/image.h"
36 /* Arbitrary pushbuf length we can assume we can get with a single
37 * call to WAIT_RING. */
38 #define PUSHBUF_DWORDS 65536
40 /* Functions to turn GL arrays or index buffers into nouveau_array
44 get_array_stride(struct gl_context
*ctx
, const struct tnl_vertex_array
*a
)
46 struct nouveau_render_state
*render
= to_render_state(ctx
);
47 const struct gl_vertex_buffer_binding
*binding
= a
->BufferBinding
;
49 if (render
->mode
== VBO
&& !binding
->BufferObj
) {
50 const struct gl_array_attributes
*attrib
= a
->VertexAttrib
;
51 /* Pack client buffers. */
52 return align(attrib
->Format
._ElementSize
, 4);
54 return binding
->Stride
;
59 vbo_init_arrays(struct gl_context
*ctx
, const struct _mesa_index_buffer
*ib
,
60 const struct tnl_vertex_array
*arrays
)
62 struct nouveau_render_state
*render
= to_render_state(ctx
);
63 GLboolean imm
= (render
->mode
== IMM
);
69 if (ib
->index_size_shift
== 2)
70 ib_type
= GL_UNSIGNED_INT
;
71 else if (ib
->index_size_shift
== 1)
72 ib_type
= GL_UNSIGNED_SHORT
;
74 ib_type
= GL_UNSIGNED_BYTE
;
76 nouveau_init_array(&render
->ib
, 0, 0, ib
->count
, ib_type
,
77 ib
->obj
, ib
->ptr
, GL_TRUE
, ctx
);
80 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
81 const struct tnl_vertex_array
*array
= &arrays
[attr
];
82 const struct gl_vertex_buffer_binding
*binding
=
84 const struct gl_array_attributes
*attrib
= array
->VertexAttrib
;
85 const GLubyte
*p
= _mesa_vertex_attrib_address(attrib
, binding
);
87 nouveau_init_array(&render
->attrs
[attr
], attr
,
88 get_array_stride(ctx
, array
),
89 attrib
->Format
.Size
, attrib
->Format
.Type
,
90 imm
? binding
->BufferObj
: NULL
,
96 vbo_deinit_arrays(struct gl_context
*ctx
, const struct _mesa_index_buffer
*ib
,
97 const struct tnl_vertex_array
*arrays
)
99 struct nouveau_render_state
*render
= to_render_state(ctx
);
103 nouveau_cleanup_array(&render
->ib
);
105 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
106 struct nouveau_array
*a
= &render
->attrs
[attr
];
108 if (render
->mode
== IMM
)
109 nouveau_bo_ref(NULL
, &a
->bo
);
111 nouveau_deinit_array(a
);
115 render
->attr_count
= 0;
118 /* Make some rendering decisions from the GL context. */
121 vbo_choose_render_mode(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
)
123 struct nouveau_render_state
*render
= to_render_state(ctx
);
128 if (ctx
->Light
.Enabled
) {
129 for (i
= 0; i
< VERT_ATTRIB_MAT_MAX
; i
++) {
130 if (arrays
[VERT_ATTRIB_MAT(i
)].BufferBinding
->Stride
) {
139 vbo_emit_attr(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
,
142 struct nouveau_pushbuf
*push
= context_push(ctx
);
143 struct nouveau_render_state
*render
= to_render_state(ctx
);
144 const struct tnl_vertex_array
*array
= &arrays
[attr
];
145 const struct gl_vertex_buffer_binding
*binding
= array
->BufferBinding
;
146 const struct gl_array_attributes
*attrib
= array
->VertexAttrib
;
147 const GLubyte
*p
= _mesa_vertex_attrib_address(attrib
, binding
);
148 struct nouveau_array
*a
= &render
->attrs
[attr
];
151 if (!binding
->Stride
) {
152 if (attr
>= VERT_ATTRIB_MAT(0))
153 /* nouveau_update_state takes care of materials. */
156 /* Constant attribute. */
157 nouveau_init_array(a
, attr
, binding
->Stride
, attrib
->Format
.Size
,
158 attrib
->Format
.Type
, binding
->BufferObj
, p
,
161 nouveau_deinit_array(a
);
164 /* Varying attribute. */
165 struct nouveau_attr_info
*info
= &TAG(vertex_attrs
)[attr
];
167 if (render
->mode
== VBO
) {
168 render
->map
[info
->vbo_index
] = attr
;
169 render
->vertex_size
+= attrib
->Format
._ElementSize
;
170 render
->attr_count
= MAX2(render
->attr_count
,
171 info
->vbo_index
+ 1);
173 render
->map
[render
->attr_count
++] = attr
;
174 render
->vertex_size
+= 4 * info
->imm_fields
;
179 #define MAT(a) VERT_ATTRIB_MAT(MAT_ATTRIB_##a)
182 vbo_choose_attrs(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
)
184 struct nouveau_render_state
*render
= to_render_state(ctx
);
187 /* Reset the vertex size. */
188 render
->vertex_size
= 0;
189 render
->attr_count
= 0;
191 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_COLOR0
);
192 if (ctx
->Fog
.ColorSumEnabled
&& !ctx
->Light
.Enabled
)
193 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_COLOR1
);
195 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
196 if (ctx
->Texture
._EnabledCoordUnits
& (1 << i
))
197 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_TEX0
+ i
);
200 if (ctx
->Fog
.Enabled
&& ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
)
201 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_FOG
);
203 if (ctx
->Light
.Enabled
||
204 (ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
))
205 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_NORMAL
);
207 if (ctx
->Light
.Enabled
&& render
->mode
== IMM
) {
208 vbo_emit_attr(ctx
, arrays
, MAT(FRONT_AMBIENT
));
209 vbo_emit_attr(ctx
, arrays
, MAT(FRONT_DIFFUSE
));
210 vbo_emit_attr(ctx
, arrays
, MAT(FRONT_SPECULAR
));
211 vbo_emit_attr(ctx
, arrays
, MAT(FRONT_SHININESS
));
213 if (ctx
->Light
.Model
.TwoSide
) {
214 vbo_emit_attr(ctx
, arrays
, MAT(BACK_AMBIENT
));
215 vbo_emit_attr(ctx
, arrays
, MAT(BACK_DIFFUSE
));
216 vbo_emit_attr(ctx
, arrays
, MAT(BACK_SPECULAR
));
217 vbo_emit_attr(ctx
, arrays
, MAT(BACK_SHININESS
));
221 vbo_emit_attr(ctx
, arrays
, VERT_ATTRIB_POS
);
225 get_max_client_stride(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
)
227 struct nouveau_render_state
*render
= to_render_state(ctx
);
230 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
231 const struct tnl_vertex_array
*a
= &arrays
[attr
];
233 if (!a
->BufferBinding
->BufferObj
)
234 s
= MAX2(s
, get_array_stride(ctx
, a
));
241 TAG(vbo_render_prims
)(struct gl_context
*ctx
,
242 const struct tnl_vertex_array
*arrays
,
243 const struct _mesa_prim
*prims
, GLuint nr_prims
,
244 const struct _mesa_index_buffer
*ib
,
245 GLboolean index_bounds_valid
,
246 GLuint min_index
, GLuint max_index
,
247 GLuint num_instances
, GLuint base_instance
);
250 vbo_maybe_split(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
,
251 const struct _mesa_prim
*prims
, GLuint nr_prims
,
252 const struct _mesa_index_buffer
*ib
,
253 GLuint min_index
, GLuint max_index
,
254 GLuint num_instances
, GLuint base_instance
)
256 struct nouveau_context
*nctx
= to_nouveau_context(ctx
);
257 struct nouveau_render_state
*render
= to_render_state(ctx
);
258 struct nouveau_bufctx
*bufctx
= nctx
->hw
.bufctx
;
259 unsigned pushbuf_avail
= PUSHBUF_DWORDS
- 2 * (bufctx
->relocs
+
261 vert_avail
= get_max_vertices(ctx
, NULL
, pushbuf_avail
),
262 idx_avail
= get_max_vertices(ctx
, ib
, pushbuf_avail
);
265 /* Try to keep client buffers smaller than the scratch BOs. */
266 if (render
->mode
== VBO
&&
267 (stride
= get_max_client_stride(ctx
, arrays
)))
268 vert_avail
= MIN2(vert_avail
,
269 NOUVEAU_SCRATCH_SIZE
/ stride
);
271 if (max_index
- min_index
> vert_avail
||
272 (ib
&& ib
->count
> idx_avail
)) {
273 struct split_limits limits
= {
274 .max_verts
= vert_avail
,
275 .max_indices
= idx_avail
,
279 _tnl_split_prims(ctx
, arrays
, prims
, nr_prims
, ib
, min_index
,
280 max_index
, num_instances
, base_instance
,
281 TAG(vbo_render_prims
), &limits
);
288 /* VBO rendering path. */
291 check_update_array(struct nouveau_array
*a
, unsigned offset
,
292 struct nouveau_bo
*bo
, int *pdelta
)
299 delta
= ((int)offset
- (int)a
->offset
) / a
->stride
;
301 dirty
= (delta
< 0 ||
302 offset
!= (a
->offset
+ delta
* a
->stride
));
307 *pdelta
= (dirty
? 0 : delta
);
312 vbo_bind_vertices(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
,
313 int base
, unsigned min_index
, unsigned max_index
, int *pdelta
)
315 struct nouveau_render_state
*render
= to_render_state(ctx
);
316 struct nouveau_pushbuf
*push
= context_push(ctx
);
317 struct nouveau_bo
*bo
[NUM_VERTEX_ATTRS
];
318 unsigned offset
[NUM_VERTEX_ATTRS
];
319 GLboolean dirty
= GL_FALSE
;
325 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
326 const struct tnl_vertex_array
*array
= &arrays
[attr
];
327 const struct gl_vertex_buffer_binding
*binding
=
328 array
->BufferBinding
;
329 const struct gl_array_attributes
*attrib
= array
->VertexAttrib
;
330 const GLubyte
*p
= _mesa_vertex_attrib_address(attrib
, binding
);
331 struct gl_buffer_object
*obj
= binding
->BufferObj
;
332 struct nouveau_array
*a
= &render
->attrs
[attr
];
333 unsigned delta
= (base
+ min_index
) * binding
->Stride
;
337 if (nouveau_bufferobj_hw(obj
)) {
338 /* Array in a buffer obj. */
339 nouveau_bo_ref(to_nouveau_bufferobj(obj
)->bo
, &bo
[i
]);
340 offset
[i
] = delta
+ (intptr_t)p
;
343 int n
= max_index
- min_index
+ 1;
346 sp
= (char *)ADD_POINTERS(
347 nouveau_bufferobj_sys(obj
), p
) + delta
;
349 sp
= (char *)(p
+ delta
);
351 char *dp
= nouveau_get_scratch(ctx
, n
* a
->stride
,
354 /* Array in client memory, move it to a
355 * scratch buffer obj. */
356 for (j
= 0; j
< n
; j
++)
357 memcpy(dp
+ j
* a
->stride
,
358 sp
+ j
* binding
->Stride
,
362 dirty
|= check_update_array(a
, offset
[i
], bo
[i
], pdelta
);
365 *pdelta
-= min_index
;
368 /* Buffers changed, update the attribute binding. */
369 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
370 struct nouveau_array
*a
= &render
->attrs
[attr
];
372 nouveau_bo_ref(NULL
, &a
->bo
);
373 a
->offset
= offset
[i
];
377 TAG(render_release_vertices
)(ctx
);
378 TAG(render_bind_vertices
)(ctx
);
381 FOR_EACH_BOUND_ATTR(render
, i
, attr
)
382 nouveau_bo_ref(NULL
, &bo
[i
]);
389 vbo_draw_vbo(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
,
390 const struct _mesa_prim
*prims
, GLuint nr_prims
,
391 const struct _mesa_index_buffer
*ib
, GLuint min_index
,
394 struct nouveau_context
*nctx
= to_nouveau_context(ctx
);
395 struct nouveau_pushbuf
*push
= context_push(ctx
);
396 dispatch_t dispatch
= get_array_dispatch(&to_render_state(ctx
)->ib
);
397 int i
, delta
= 0, basevertex
= 0;
400 TAG(render_set_format
)(ctx
);
402 for (i
= 0; i
< nr_prims
; i
++) {
403 unsigned start
= prims
[i
].start
,
404 count
= prims
[i
].count
;
406 if (i
== 0 || basevertex
!= prims
[i
].basevertex
) {
407 basevertex
= prims
[i
].basevertex
;
408 vbo_bind_vertices(ctx
, arrays
, basevertex
, min_index
,
411 nouveau_pushbuf_bufctx(push
, nctx
->hw
.bufctx
);
412 if (nouveau_pushbuf_validate(push
)) {
413 nouveau_pushbuf_bufctx(push
, NULL
);
418 if (count
> get_max_vertices(ctx
, ib
, PUSH_AVAIL(push
)))
419 PUSH_SPACE(push
, PUSHBUF_DWORDS
);
421 BATCH_BEGIN(nvgl_primitive(prims
[i
].mode
));
422 dispatch(ctx
, start
, delta
, count
);
426 nouveau_pushbuf_bufctx(push
, NULL
);
427 TAG(render_release_vertices
)(ctx
);
430 /* Immediate rendering path. */
433 extract_id(struct nouveau_array
*a
, int i
, int j
)
439 vbo_draw_imm(struct gl_context
*ctx
, const struct tnl_vertex_array
*arrays
,
440 const struct _mesa_prim
*prims
, GLuint nr_prims
,
441 const struct _mesa_index_buffer
*ib
, GLuint min_index
,
444 struct nouveau_render_state
*render
= to_render_state(ctx
);
445 struct nouveau_context
*nctx
= to_nouveau_context(ctx
);
446 struct nouveau_pushbuf
*push
= context_push(ctx
);
447 extract_u_t extract
= ib
? render
->ib
.extract_u
: extract_id
;
451 nouveau_pushbuf_bufctx(push
, nctx
->hw
.bufctx
);
452 if (nouveau_pushbuf_validate(push
)) {
453 nouveau_pushbuf_bufctx(push
, NULL
);
457 for (i
= 0; i
< nr_prims
; i
++) {
458 unsigned start
= prims
[i
].start
,
459 end
= start
+ prims
[i
].count
;
461 if (prims
[i
].count
> get_max_vertices(ctx
, ib
,
463 PUSH_SPACE(push
, PUSHBUF_DWORDS
);
465 BATCH_BEGIN(nvgl_primitive(prims
[i
].mode
));
467 for (; start
< end
; start
++) {
468 j
= prims
[i
].basevertex
+
469 extract(&render
->ib
, 0, start
);
471 FOR_EACH_BOUND_ATTR(render
, k
, attr
)
472 EMIT_IMM(ctx
, &render
->attrs
[attr
], j
);
478 nouveau_pushbuf_bufctx(push
, NULL
);
481 /* draw_prims entry point when we're doing hw-tnl. */
484 TAG(vbo_render_prims
)(struct gl_context
*ctx
,
485 const struct tnl_vertex_array
*arrays
,
486 const struct _mesa_prim
*prims
, GLuint nr_prims
,
487 const struct _mesa_index_buffer
*ib
,
488 GLboolean index_bounds_valid
,
489 GLuint min_index
, GLuint max_index
,
490 GLuint num_instances
, GLuint base_instance
)
492 struct nouveau_render_state
*render
= to_render_state(ctx
);
494 if (!index_bounds_valid
)
495 vbo_get_minmax_indices(ctx
, prims
, ib
, &min_index
, &max_index
,
498 vbo_choose_render_mode(ctx
, arrays
);
499 vbo_choose_attrs(ctx
, arrays
);
501 if (vbo_maybe_split(ctx
, arrays
, prims
, nr_prims
, ib
, min_index
,
502 max_index
, num_instances
, base_instance
))
505 vbo_init_arrays(ctx
, ib
, arrays
);
507 if (render
->mode
== VBO
)
508 vbo_draw_vbo(ctx
, arrays
, prims
, nr_prims
, ib
, min_index
,
511 vbo_draw_imm(ctx
, arrays
, prims
, nr_prims
, ib
, min_index
,
514 vbo_deinit_arrays(ctx
, ib
, arrays
);
517 /* VBO rendering entry points. */
520 TAG(vbo_check_render_prims
)(struct gl_context
*ctx
,
521 const struct tnl_vertex_array
*arrays
,
522 const struct _mesa_prim
*prims
, GLuint nr_prims
,
523 const struct _mesa_index_buffer
*ib
,
524 GLboolean index_bounds_valid
,
525 GLuint min_index
, GLuint max_index
,
526 GLuint num_instances
, GLuint base_instance
)
528 struct nouveau_context
*nctx
= to_nouveau_context(ctx
);
530 nouveau_validate_framebuffer(ctx
);
532 if (nctx
->fallback
== HWTNL
)
533 TAG(vbo_render_prims
)(ctx
, arrays
, prims
, nr_prims
, ib
,
534 index_bounds_valid
, min_index
, max_index
,
535 num_instances
, base_instance
);
537 if (nctx
->fallback
== SWTNL
)
538 _tnl_draw_prims(ctx
, arrays
, prims
, nr_prims
, ib
,
539 index_bounds_valid
, min_index
, max_index
,
540 num_instances
, base_instance
);
544 TAG(vbo_draw
)(struct gl_context
*ctx
,
545 const struct _mesa_prim
*prims
, GLuint nr_prims
,
546 const struct _mesa_index_buffer
*ib
,
547 GLboolean index_bounds_valid
,
548 GLuint min_index
, GLuint max_index
,
549 GLuint num_instances
, GLuint base_instance
,
550 UNUSED
struct gl_transform_feedback_object
*tfb_vertcount
,
551 UNUSED
unsigned stream
)
553 /* Borrow and update the inputs list from the tnl context */
554 const struct tnl_vertex_array
* arrays
= _tnl_bind_inputs(ctx
);
556 TAG(vbo_check_render_prims
)(ctx
, arrays
,
558 index_bounds_valid
, min_index
, max_index
,
559 num_instances
, base_instance
);
563 TAG(vbo_init
)(struct gl_context
*ctx
)
565 struct nouveau_render_state
*render
= to_render_state(ctx
);
568 for (i
= 0; i
< VERT_ATTRIB_MAX
; i
++)
571 /* Overwrite our draw function */
572 ctx
->Driver
.Draw
= TAG(vbo_draw
);
576 TAG(vbo_destroy
)(struct gl_context
*ctx
)