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 "tnl/t_context.h"
28 #include "tnl/t_pipeline.h"
29 #include "tnl/t_vertex.h"
31 #define SWTNL_VBO_SIZE 65536
33 static enum tnl_attr_format
34 swtnl_get_format(int type
, int fields
) {
49 case GL_UNSIGNED_BYTE
:
52 return EMIT_4UB_4F_RGBA
;
61 static struct swtnl_attr_info
{
64 } swtnl_attrs
[VERT_ATTRIB_MAX
] = {
69 [VERT_ATTRIB_NORMAL
] = {
73 [VERT_ATTRIB_COLOR0
] = {
74 .type
= GL_UNSIGNED_BYTE
,
77 [VERT_ATTRIB_COLOR1
] = {
78 .type
= GL_UNSIGNED_BYTE
,
85 [VERT_ATTRIB_TEX0
] = {
89 [VERT_ATTRIB_TEX1
] = {
93 [VERT_ATTRIB_TEX2
] = {
97 [VERT_ATTRIB_TEX3
] = {
104 swtnl_choose_attrs(struct gl_context
*ctx
)
106 struct nouveau_render_state
*render
= to_render_state(ctx
);
107 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
108 struct tnl_clipspace
*vtx
= &tnl
->clipspace
;
109 static struct tnl_attr_map map
[NUM_VERTEX_ATTRS
];
110 int fields
, attr
, i
, n
= 0;
113 render
->attr_count
= NUM_VERTEX_ATTRS
;
115 /* We always want non Ndc coords format */
116 tnl
->vb
.AttribPtr
[VERT_ATTRIB_POS
] = tnl
->vb
.ClipPtr
;
118 for (i
= 0; i
< VERT_ATTRIB_MAX
; i
++) {
119 struct nouveau_attr_info
*ha
= &TAG(vertex_attrs
)[i
];
120 struct swtnl_attr_info
*sa
= &swtnl_attrs
[i
];
121 struct nouveau_array
*a
= &render
->attrs
[i
];
124 continue; /* Unsupported attribute. */
126 if (tnl
->render_inputs_bitset
& BITFIELD64_BIT(i
)) {
130 fields
= tnl
->vb
.AttribPtr
[i
]->size
;
132 map
[n
++] = (struct tnl_attr_map
) {
134 .format
= swtnl_get_format(sa
->type
, fields
),
137 render
->map
[ha
->vbo_index
] = i
;
144 _tnl_install_attrs(ctx
, map
, n
, NULL
, 0);
146 FOR_EACH_BOUND_ATTR(render
, i
, attr
)
147 render
->attrs
[attr
].stride
= vtx
->vertex_size
;
149 TAG(render_set_format
)(ctx
);
153 swtnl_alloc_vertices(struct gl_context
*ctx
)
155 struct nouveau_swtnl_state
*swtnl
= &to_render_state(ctx
)->swtnl
;
157 nouveau_bo_ref(NULL
, &swtnl
->vbo
);
158 swtnl
->buf
= nouveau_get_scratch(ctx
, SWTNL_VBO_SIZE
, &swtnl
->vbo
,
160 swtnl
->vertex_count
= 0;
164 swtnl_bind_vertices(struct gl_context
*ctx
)
166 struct nouveau_render_state
*render
= to_render_state(ctx
);
167 struct nouveau_swtnl_state
*swtnl
= &render
->swtnl
;
168 struct tnl_clipspace
*vtx
= &TNL_CONTEXT(ctx
)->clipspace
;
171 for (i
= 0; i
< vtx
->attr_count
; i
++) {
172 struct tnl_clipspace_attr
*ta
= &vtx
->attr
[i
];
173 struct nouveau_array
*a
= &render
->attrs
[ta
->attrib
];
175 nouveau_bo_ref(swtnl
->vbo
, &a
->bo
);
176 a
->offset
= swtnl
->offset
+ ta
->vertoffset
;
179 TAG(render_bind_vertices
)(ctx
);
183 swtnl_unbind_vertices(struct gl_context
*ctx
)
185 struct nouveau_render_state
*render
= to_render_state(ctx
);
188 TAG(render_release_vertices
)(ctx
);
190 FOR_EACH_BOUND_ATTR(render
, i
, attr
) {
191 nouveau_bo_ref(NULL
, &render
->attrs
[attr
].bo
);
195 render
->attr_count
= 0;
199 swtnl_flush_vertices(struct gl_context
*ctx
)
201 struct nouveau_pushbuf
*push
= context_push(ctx
);
202 struct nouveau_swtnl_state
*swtnl
= &to_render_state(ctx
)->swtnl
;
203 unsigned npush
, start
= 0, count
= swtnl
->vertex_count
;
206 swtnl_bind_vertices(ctx
);
209 npush
= get_max_vertices(ctx
, NULL
, PUSH_AVAIL(push
));
210 npush
= MIN2(npush
/ 12 * 12, count
);
218 BATCH_BEGIN(nvgl_primitive(swtnl
->primitive
));
219 EMIT_VBO(L
, ctx
, start
, 0, npush
);
225 swtnl_alloc_vertices(ctx
);
228 /* TnL renderer entry points */
231 swtnl_start(struct gl_context
*ctx
)
233 swtnl_choose_attrs(ctx
);
237 swtnl_finish(struct gl_context
*ctx
)
239 swtnl_flush_vertices(ctx
);
240 swtnl_unbind_vertices(ctx
);
244 swtnl_primitive(struct gl_context
*ctx
, GLenum mode
)
249 swtnl_reset_stipple(struct gl_context
*ctx
)
253 /* Primitive rendering */
255 #define BEGIN_PRIMITIVE(p, n) \
256 struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; \
257 int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size; \
259 if (swtnl->vertex_count + (n) > SWTNL_VBO_SIZE/vertex_len \
260 || (swtnl->vertex_count && swtnl->primitive != p)) \
261 swtnl_flush_vertices(ctx); \
263 swtnl->primitive = p;
265 #define OUT_VERTEX(i) do { \
266 memcpy(swtnl->buf + swtnl->vertex_count * vertex_len, \
267 _tnl_get_vertex(ctx, (i)), vertex_len); \
268 swtnl->vertex_count++; \
272 swtnl_points(struct gl_context
*ctx
, GLuint first
, GLuint last
)
276 while (first
< last
) {
277 BEGIN_PRIMITIVE(GL_POINTS
, last
- first
);
279 count
= MIN2(SWTNL_VBO_SIZE
/ vertex_len
, last
- first
);
280 for (i
= 0; i
< count
; i
++)
281 OUT_VERTEX(first
+ i
);
288 swtnl_line(struct gl_context
*ctx
, GLuint v1
, GLuint v2
)
290 BEGIN_PRIMITIVE(GL_LINES
, 2);
296 swtnl_triangle(struct gl_context
*ctx
, GLuint v1
, GLuint v2
, GLuint v3
)
298 BEGIN_PRIMITIVE(GL_TRIANGLES
, 3);
305 swtnl_quad(struct gl_context
*ctx
, GLuint v1
, GLuint v2
, GLuint v3
, GLuint v4
)
307 BEGIN_PRIMITIVE(GL_QUADS
, 4);
314 /* TnL initialization. */
316 TAG(swtnl_init
)(struct gl_context
*ctx
)
318 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
320 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
321 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
322 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
323 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
324 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
325 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
327 tnl
->Driver
.Render
.Start
= swtnl_start
;
328 tnl
->Driver
.Render
.Finish
= swtnl_finish
;
329 tnl
->Driver
.Render
.PrimitiveNotify
= swtnl_primitive
;
330 tnl
->Driver
.Render
.ResetLineStipple
= swtnl_reset_stipple
;
332 tnl
->Driver
.Render
.Points
= swtnl_points
;
333 tnl
->Driver
.Render
.Line
= swtnl_line
;
334 tnl
->Driver
.Render
.Triangle
= swtnl_triangle
;
335 tnl
->Driver
.Render
.Quad
= swtnl_quad
;
337 _tnl_init_vertices(ctx
, tnl
->vb
.Size
,
338 NUM_VERTEX_ATTRS
* 4 * sizeof(GLfloat
));
339 _tnl_need_projected_coords(ctx
, GL_FALSE
);
340 _tnl_allow_vertex_fog(ctx
, GL_FALSE
);
343 swtnl_alloc_vertices(ctx
);
347 TAG(swtnl_destroy
)(struct gl_context
*ctx
)
349 nouveau_bo_ref(NULL
, &to_render_state(ctx
)->swtnl
.vbo
);