1bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/*
2bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * Copyright (C) 2009-2010 Francisco Jerez.
3bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * All Rights Reserved.
4bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
5bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * Permission is hereby granted, free of charge, to any person obtaining
6bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * a copy of this software and associated documentation files (the
7bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * "Software"), to deal in the Software without restriction, including
8bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * without limitation the rights to use, copy, modify, merge, publish,
9bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * distribute, sublicense, and/or sell copies of the Software, and to
10bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * permit persons to whom the Software is furnished to do so, subject to
11bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * the following conditions:
12bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
13bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * The above copyright notice and this permission notice (including the
14bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * next paragraph) shall be included in all copies or substantial
15bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * portions of the Software.
16bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
17bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
25bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez */
26bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
272e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs#include "nouveau_driver.h"
28bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#include "nouveau_bufferobj.h"
2943c347c63ee10db95bd912fc39b1127fa35305a4Francisco Jerez#include "nouveau_util.h"
3043c347c63ee10db95bd912fc39b1127fa35305a4Francisco Jerez
3143c347c63ee10db95bd912fc39b1127fa35305a4Francisco Jerez#include "main/bufferobj.h"
321f9239ec8d67c3e8ee64e6f5306499b6d97ea136Brian Paul#include "main/glformats.h"
3343c347c63ee10db95bd912fc39b1127fa35305a4Francisco Jerez#include "main/image.h"
34bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
35bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/* Arbitrary pushbuf length we can assume we can get with a single
3657382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez * call to WAIT_RING. */
37c25fcf5aa5beccd7731706b8f85682170a2eca56Francisco Jerez#define PUSHBUF_DWORDS 65536
38bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
3957382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez/* Functions to turn GL arrays or index buffers into nouveau_array
4057382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez * structures. */
41bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
427f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerezstatic int
43f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergget_array_stride(struct gl_context *ctx, const struct gl_client_array *a)
447f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez{
457f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
467f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez
477f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez	if (render->mode == VBO && !_mesa_is_bufferobj(a->BufferObj))
487f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez		/* Pack client buffers. */
497f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez		return align(_mesa_sizeof_type(a->Type) * a->Size, 4);
507f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez	else
517f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez		return a->StrideB;
527f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez}
537f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerez
54bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
55f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_init_arrays(struct gl_context *ctx, const struct _mesa_index_buffer *ib,
56bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		const struct gl_client_array **arrays)
57bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
58bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
599d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	GLboolean imm = (render->mode == IMM);
609d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	int i, attr;
61bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
62bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (ib)
6357382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_init_array(&render->ib, 0, 0, ib->count, ib->type,
642e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				   ib->obj, ib->ptr, GL_TRUE, ctx);
65bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
669d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	FOR_EACH_BOUND_ATTR(render, i, attr) {
679d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		const struct gl_client_array *array = arrays[attr];
68bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
6957382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_init_array(&render->attrs[attr], attr,
7057382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez				   get_array_stride(ctx, array),
7157382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez				   array->Size, array->Type,
72e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez				   imm ? array->BufferObj : NULL,
732e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				   array->Ptr, imm, ctx);
74bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
75bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
76bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
77bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
78f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_deinit_arrays(struct gl_context *ctx, const struct _mesa_index_buffer *ib,
799d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		  const struct gl_client_array **arrays)
80bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
81bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
829d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	int i, attr;
83bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
84bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (ib)
8557382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_cleanup_array(&render->ib);
86bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
879d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	FOR_EACH_BOUND_ATTR(render, i, attr) {
8857382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		struct nouveau_array *a = &render->attrs[attr];
89bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
90e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		if (render->mode == IMM)
91e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			nouveau_bo_ref(NULL, &a->bo);
92e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
9357382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_deinit_array(a);
949d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		render->map[i] = -1;
95bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
96bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
97bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	render->attr_count = 0;
98bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
99bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
100bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/* Make some rendering decisions from the GL context. */
101bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
102bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
103f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_choose_render_mode(struct gl_context *ctx, const struct gl_client_array **arrays)
104bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
105bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
106bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	int i;
107bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
108bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	render->mode = VBO;
109bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
110bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (ctx->Light.Enabled) {
111bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		for (i = 0; i < MAT_ATTRIB_MAX; i++) {
112bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			if (arrays[VERT_ATTRIB_GENERIC0 + i]->StrideB) {
113bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez				render->mode = IMM;
114bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez				break;
115bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			}
116bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
117bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
118bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
119bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
120bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
12157382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerezvbo_emit_attr(struct gl_context *ctx, const struct gl_client_array **arrays,
12257382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez	      int attr)
123bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
1242e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_pushbuf *push = context_push(ctx);
125bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
126bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	const struct gl_client_array *array = arrays[attr];
12757382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez	struct nouveau_array *a = &render->attrs[attr];
128bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	RENDER_LOCALS(ctx);
129bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
130bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (!array->StrideB) {
131bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (attr >= VERT_ATTRIB_GENERIC0)
132bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			/* nouveau_update_state takes care of materials. */
133bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			return;
134bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
135bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		/* Constant attribute. */
13657382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_init_array(a, attr, array->StrideB, array->Size,
13757382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez				   array->Type, array->BufferObj, array->Ptr,
1382e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				   GL_TRUE, ctx);
139bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		EMIT_IMM(ctx, a, 0);
14057382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		nouveau_deinit_array(a);
141bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
142bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	} else {
143bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		/* Varying attribute. */
144bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		struct nouveau_attr_info *info = &TAG(vertex_attrs)[attr];
145bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
146bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (render->mode == VBO) {
147bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			render->map[info->vbo_index] = attr;
148bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			render->vertex_size += array->_ElementSize;
1499d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez			render->attr_count = MAX2(render->attr_count,
1509d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez						  info->vbo_index + 1);
151bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		} else {
152bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			render->map[render->attr_count++] = attr;
153bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			render->vertex_size += 4 * info->imm_fields;
154bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
155bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
156bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
157bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
158bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#define MAT(a) (VERT_ATTRIB_GENERIC0 + MAT_ATTRIB_##a)
159bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
160bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
161f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_choose_attrs(struct gl_context *ctx, const struct gl_client_array **arrays)
162bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
163bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
164bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	int i;
165bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
166bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	/* Reset the vertex size. */
167bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	render->vertex_size = 0;
1689d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	render->attr_count = 0;
169bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
170bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR0);
171bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (ctx->Fog.ColorSumEnabled && !ctx->Light.Enabled)
172bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR1);
173bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
174bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
175bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (ctx->Texture._EnabledCoordUnits & (1 << i))
176bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			vbo_emit_attr(ctx, arrays, VERT_ATTRIB_TEX0 + i);
177bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
178bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
179bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD)
180bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG);
181bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
182c944fb5ffe7cf16154d6395001f43a6c965cab1fFrancisco Jerez	if (ctx->Light.Enabled ||
183c944fb5ffe7cf16154d6395001f43a6c965cab1fFrancisco Jerez	    (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))
184bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL);
185bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
186e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	if (ctx->Light.Enabled && render->mode == IMM) {
187bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT));
188bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE));
189bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR));
190bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_emit_attr(ctx, arrays, MAT(FRONT_SHININESS));
191bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
192bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (ctx->Light.Model.TwoSide) {
193bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			vbo_emit_attr(ctx, arrays, MAT(BACK_AMBIENT));
194bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			vbo_emit_attr(ctx, arrays, MAT(BACK_DIFFUSE));
195bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			vbo_emit_attr(ctx, arrays, MAT(BACK_SPECULAR));
196bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			vbo_emit_attr(ctx, arrays, MAT(BACK_SHININESS));
197bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
198bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
199bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
200bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS);
201bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
202bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
2037f1f4c14eced51bf3f43764e2864693ba1c4a6d5Francisco Jerezstatic int
204f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergget_max_client_stride(struct gl_context *ctx, const struct gl_client_array **arrays)
20580316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez{
20680316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
2079d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	int i, attr, s = 0;
20880316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
2099d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	FOR_EACH_BOUND_ATTR(render, i, attr) {
2109d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		const struct gl_client_array *a = arrays[attr];
21180316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
2129d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		if (!_mesa_is_bufferobj(a->BufferObj))
2139d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez			s = MAX2(s, get_array_stride(ctx, a));
21480316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	}
21580316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
21680316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	return s;
21780316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez}
21880316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
219bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
22050f7e75f9e945cfbb2ae868cc961a2205a0b6e73Marek OlšákTAG(vbo_render_prims)(struct gl_context *ctx,
221bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      const struct _mesa_prim *prims, GLuint nr_prims,
222bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      const struct _mesa_index_buffer *ib,
223bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      GLboolean index_bounds_valid,
22414bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák		      GLuint min_index, GLuint max_index,
22514bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák		      struct gl_transform_feedback_object *tfb_vertcount);
226bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
227bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic GLboolean
228f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_maybe_split(struct gl_context *ctx, const struct gl_client_array **arrays,
229bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	    const struct _mesa_prim *prims, GLuint nr_prims,
230bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	    const struct _mesa_index_buffer *ib,
231bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	    GLuint min_index, GLuint max_index)
232bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
233bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_context *nctx = to_nouveau_context(ctx);
23480316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
2352e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_bufctx *bufctx = nctx->hw.bufctx;
2362e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (bufctx->relocs +
237d475eae50b15646efd83fa7f73ad7f2b40dd5206Francisco Jerez						       render->attr_count),
238bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail),
239bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		idx_avail = get_max_vertices(ctx, ib, pushbuf_avail);
24080316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	int stride;
24180316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
24280316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez	/* Try to keep client buffers smaller than the scratch BOs. */
243ea027bda8e4a7cdd8f131e01ab4ff80d6c6a3ab7Francisco Jerez	if (render->mode == VBO &&
244d475eae50b15646efd83fa7f73ad7f2b40dd5206Francisco Jerez	    (stride = get_max_client_stride(ctx, arrays)))
24580316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez		    vert_avail = MIN2(vert_avail,
246f2098e0fefbbcd72df4c8283d195beae4a113f35Francisco Jerez				      NOUVEAU_SCRATCH_SIZE / stride);
24780316cbefaa28454ab9d6da44ac93805608c3685Francisco Jerez
248ea027bda8e4a7cdd8f131e01ab4ff80d6c6a3ab7Francisco Jerez	if (max_index - min_index > vert_avail ||
249ea027bda8e4a7cdd8f131e01ab4ff80d6c6a3ab7Francisco Jerez	    (ib && ib->count > idx_avail)) {
250bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		struct split_limits limits = {
251bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			.max_verts = vert_avail,
252bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			.max_indices = idx_avail,
253bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			.max_vb_size = ~0,
254bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		};
255bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
256bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_split_prims(ctx, arrays, prims, nr_prims, ib, min_index,
257bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez				max_index, TAG(vbo_render_prims), &limits);
258bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		return GL_TRUE;
259bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
260bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
261bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return GL_FALSE;
262bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
263bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
264bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/* VBO rendering path. */
265bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
266e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerezstatic GLboolean
267e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerezcheck_update_array(struct nouveau_array *a, unsigned offset,
268e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		   struct nouveau_bo *bo, int *pdelta)
269e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez{
270e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	int delta = *pdelta;
271e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	GLboolean dirty;
272e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
273e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	if (a->bo == bo) {
274e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		if (delta < 0)
275453b71855294508fce8358134f9bf5316043b834Francisco Jerez			delta = ((int)offset - (int)a->offset) / a->stride;
276e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
277e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		dirty = (delta < 0 ||
278e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			 offset != (a->offset + delta * a->stride));
279e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	} else {
280e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		dirty = GL_TRUE;
281e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	}
282e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
283e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	*pdelta = (dirty ? 0 : delta);
284e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	return dirty;
285e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez}
286e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
287bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
288f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_bind_vertices(struct gl_context *ctx, const struct gl_client_array **arrays,
289e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		  int base, unsigned min_index, unsigned max_index, int *pdelta)
290bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
291bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
2922e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_pushbuf *push = context_push(ctx);
293e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	struct nouveau_bo *bo[NUM_VERTEX_ATTRS];
294e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	unsigned offset[NUM_VERTEX_ATTRS];
295e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	GLboolean dirty = GL_FALSE;
296e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	int i, j, attr;
297e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	RENDER_LOCALS(ctx);
298e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
299e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	*pdelta = -1;
300bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
3019d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	FOR_EACH_BOUND_ATTR(render, i, attr) {
3029d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		const struct gl_client_array *array = arrays[attr];
303f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		struct gl_buffer_object *obj = array->BufferObj;
30457382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez		struct nouveau_array *a = &render->attrs[attr];
305e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		unsigned delta = (base + min_index) * array->StrideB;
306e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
307e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		bo[i] = NULL;
308e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
309f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		if (nouveau_bufferobj_hw(obj)) {
3109d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez			/* Array in a buffer obj. */
311f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez			nouveau_bo_ref(to_nouveau_bufferobj(obj)->bo, &bo[i]);
312e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			offset[i] = delta + (intptr_t)array->Ptr;
313e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
3149d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez		} else {
315e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			int n = max_index - min_index + 1;
316f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez			char *sp = (char *)ADD_POINTERS(
317f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez				nouveau_bufferobj_sys(obj), array->Ptr) + delta;
318e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			char *dp  = nouveau_get_scratch(ctx, n * a->stride,
319e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez							&bo[i], &offset[i]);
3209d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez
321e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			/* Array in client memory, move it to a
322e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			 * scratch buffer obj. */
3239d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez			for (j = 0; j < n; j++)
3249d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez				memcpy(dp + j * a->stride,
3259d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez				       sp + j * array->StrideB,
3269d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez				       a->stride);
327bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
328e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
329e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		dirty |= check_update_array(a, offset[i], bo[i], pdelta);
330e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	}
331e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
332e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	*pdelta -= min_index;
333e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
334e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	if (dirty) {
335e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		/* Buffers changed, update the attribute binding. */
336e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		FOR_EACH_BOUND_ATTR(render, i, attr) {
337e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			struct nouveau_array *a = &render->attrs[attr];
338e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
339e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			nouveau_bo_ref(NULL, &a->bo);
340e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			a->offset = offset[i];
341e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			a->bo = bo[i];
342e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		}
343e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez
3442e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		TAG(render_release_vertices)(ctx);
345e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		TAG(render_bind_vertices)(ctx);
346e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	} else {
347e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		/* Just cleanup. */
348e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez		FOR_EACH_BOUND_ATTR(render, i, attr)
349e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			nouveau_bo_ref(NULL, &bo[i]);
350bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
351bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
352e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	BATCH_VALIDATE();
353bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
354bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
355bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
356f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_draw_vbo(struct gl_context *ctx, const struct gl_client_array **arrays,
357bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     const struct _mesa_prim *prims, GLuint nr_prims,
358bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     const struct _mesa_index_buffer *ib, GLuint min_index,
359bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     GLuint max_index)
360bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
3612e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_context *nctx = to_nouveau_context(ctx);
3622e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_pushbuf *push = context_push(ctx);
36357382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerez	dispatch_t dispatch = get_array_dispatch(&to_render_state(ctx)->ib);
364e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez	int i, delta = 0, basevertex = 0;
365bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	RENDER_LOCALS(ctx);
366bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
367bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	TAG(render_set_format)(ctx);
368bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
369bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	for (i = 0; i < nr_prims; i++) {
370bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		unsigned start = prims[i].start,
371bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			count = prims[i].count;
372bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
373bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (i == 0 || basevertex != prims[i].basevertex) {
374bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			basevertex = prims[i].basevertex;
375e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez			vbo_bind_vertices(ctx, arrays, basevertex, min_index,
376e89af209261e51988b99d954d09f2cbc59e55358Francisco Jerez					  max_index, &delta);
3772e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs
3782e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			nouveau_pushbuf_bufctx(push, nctx->hw.bufctx);
3792e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			if (nouveau_pushbuf_validate(push)) {
3802e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				nouveau_pushbuf_bufctx(push, NULL);
3812e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				return;
3822e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			}
383bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
384bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
3852e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		if (count > get_max_vertices(ctx, ib, PUSH_AVAIL(push)))
3862e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			PUSH_SPACE(push, PUSHBUF_DWORDS);
387bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
388bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		BATCH_BEGIN(nvgl_primitive(prims[i].mode));
389bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		dispatch(ctx, start, delta, count);
390bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		BATCH_END();
391bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
3922e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs
3932e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	nouveau_pushbuf_bufctx(push, NULL);
3942e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	TAG(render_release_vertices)(ctx);
395bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
396bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
397bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/* Immediate rendering path. */
398bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
399bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic unsigned
40057382e71ef892a36ca2171fe8758aba6c9c885e6Francisco Jerezextract_id(struct nouveau_array *a, int i, int j)
401bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
402bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return j;
403bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
404bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
405bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
406f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvbo_draw_imm(struct gl_context *ctx, const struct gl_client_array **arrays,
407bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     const struct _mesa_prim *prims, GLuint nr_prims,
408bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     const struct _mesa_index_buffer *ib, GLuint min_index,
409bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	     GLuint max_index)
410bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
411bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
4122e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_context *nctx = to_nouveau_context(ctx);
4132e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	struct nouveau_pushbuf *push = context_push(ctx);
414bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	extract_u_t extract = ib ? render->ib.extract_u : extract_id;
4159d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez	int i, j, k, attr;
416bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	RENDER_LOCALS(ctx);
417bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
4182e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	nouveau_pushbuf_bufctx(push, nctx->hw.bufctx);
4192e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	if (nouveau_pushbuf_validate(push)) {
4202e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		nouveau_pushbuf_bufctx(push, NULL);
4212e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		return;
4222e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	}
4232e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs
424bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	for (i = 0; i < nr_prims; i++) {
425bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		unsigned start = prims[i].start,
426bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			end = start + prims[i].count;
427bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
428bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		if (prims[i].count > get_max_vertices(ctx, ib,
4292e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs						      PUSH_AVAIL(push)))
4302e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			PUSH_SPACE(push, PUSHBUF_DWORDS);
431bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
432bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		BATCH_BEGIN(nvgl_primitive(prims[i].mode));
433bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
434bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		for (; start < end; start++) {
435bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			j = prims[i].basevertex +
436bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez				extract(&render->ib, 0, start);
437bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
4389d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez			FOR_EACH_BOUND_ATTR(render, k, attr)
4399d1f1fcf136e8f5f427ae203128ff641cc9e7197Francisco Jerez				EMIT_IMM(ctx, &render->attrs[attr], j);
440bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		}
441bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
442bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		BATCH_END();
443bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	}
4442e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs
4452e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	nouveau_pushbuf_bufctx(push, NULL);
446bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
447bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
448bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/* draw_prims entry point when we're doing hw-tnl. */
449bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
450bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
45157382e71ef892a36ca2171fe8758aba6c9c885e6Francisco JerezTAG(vbo_render_prims)(struct gl_context *ctx,
452bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      const struct _mesa_prim *prims, GLuint nr_prims,
453bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      const struct _mesa_index_buffer *ib,
454bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		      GLboolean index_bounds_valid,
45514bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák		      GLuint min_index, GLuint max_index,
45614bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák		      struct gl_transform_feedback_object *tfb_vertcount)
457bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
458bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
45950f7e75f9e945cfbb2ae868cc961a2205a0b6e73Marek Olšák	const struct gl_client_array **arrays = ctx->Array._DrawArrays;
460bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
461bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (!index_bounds_valid)
46242d4972bf0b147b0241c2be7e6579fd64cf2c216Yuanhan Liu		vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
46342d4972bf0b147b0241c2be7e6579fd64cf2c216Yuanhan Liu				       nr_prims);
464bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
465bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_choose_render_mode(ctx, arrays);
466bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_choose_attrs(ctx, arrays);
467bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
468bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (vbo_maybe_split(ctx, arrays, prims, nr_prims, ib, min_index,
469bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			    max_index))
470bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		return;
471bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
472bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_init_arrays(ctx, ib, arrays);
473bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
474bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (render->mode == VBO)
475bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_draw_vbo(ctx, arrays, prims, nr_prims, ib, min_index,
476bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			     max_index);
477bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	else
478bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		vbo_draw_imm(ctx, arrays, prims, nr_prims, ib, min_index,
479bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			     max_index);
480bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
481bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	vbo_deinit_arrays(ctx, ib, arrays);
482bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
483cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
484cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez/* VBO rendering entry points. */
485cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
486cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerezstatic void
487cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco JerezTAG(vbo_check_render_prims)(struct gl_context *ctx,
488cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez			    const struct _mesa_prim *prims, GLuint nr_prims,
489cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez			    const struct _mesa_index_buffer *ib,
490cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez			    GLboolean index_bounds_valid,
49114bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák			    GLuint min_index, GLuint max_index,
49214bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák			    struct gl_transform_feedback_object *tfb_vertcount)
493cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez{
494cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	struct nouveau_context *nctx = to_nouveau_context(ctx);
495cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
496cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	nouveau_validate_framebuffer(ctx);
497cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
498cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	if (nctx->fallback == HWTNL)
49950f7e75f9e945cfbb2ae868cc961a2205a0b6e73Marek Olšák		TAG(vbo_render_prims)(ctx, prims, nr_prims, ib,
50014bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák				      index_bounds_valid, min_index, max_index,
50114bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák				      tfb_vertcount);
502cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
503cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	if (nctx->fallback == SWTNL)
50450f7e75f9e945cfbb2ae868cc961a2205a0b6e73Marek Olšák		_tnl_vbo_draw_prims(ctx, prims, nr_prims, ib,
50514bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák				    index_bounds_valid, min_index, max_index,
50614bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák				    tfb_vertcount);
507cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez}
508cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
509cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerezvoid
510cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco JerezTAG(vbo_init)(struct gl_context *ctx)
511cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez{
512cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	struct nouveau_render_state *render = to_render_state(ctx);
513cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	int i;
514cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
515cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	for (i = 0; i < VERT_ATTRIB_MAX; i++)
516cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez		render->map[i] = -1;
517cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
518cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	vbo_set_draw_func(ctx, TAG(vbo_check_render_prims));
519cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez	vbo_use_buffer_objects(ctx);
520cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez}
521cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez
522cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerezvoid
523cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco JerezTAG(vbo_destroy)(struct gl_context *ctx)
524cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez{
525cdb38b5d3d1b93a90a91ad06c0f03efdfde6b525Francisco Jerez}
526