2 * Copyright (C) 2009 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_context.h"
29 #include "nouveau_util.h"
30 #include "nv04_3d.xml.h"
31 #include "nv04_driver.h"
34 #include "tnl/t_pipeline.h"
35 #include "tnl/t_vertex.h"
37 #define NUM_VERTEX_ATTRS 6
40 swtnl_update_viewport(struct gl_context
*ctx
)
42 float *viewport
= to_nv04_context(ctx
)->viewport
;
43 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
45 get_viewport_scale(ctx
, viewport
);
46 get_viewport_translate(ctx
, &viewport
[MAT_TX
]);
48 /* It wants normalized Z coordinates. */
49 viewport
[MAT_SZ
] /= fb
->_DepthMaxF
;
50 viewport
[MAT_TZ
] /= fb
->_DepthMaxF
;
54 swtnl_emit_attr(struct gl_context
*ctx
, struct tnl_attr_map
*m
, int attr
, int emit
)
56 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
58 if (tnl
->render_inputs_bitset
& BITFIELD64_BIT(attr
))
59 *m
= (struct tnl_attr_map
) {
64 *m
= (struct tnl_attr_map
) {
66 .offset
= _tnl_format_info
[emit
].attrsize
,
71 swtnl_choose_attrs(struct gl_context
*ctx
)
73 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
74 struct nouveau_object
*fahrenheit
= nv04_context_engine(ctx
);
75 struct nv04_context
*nctx
= to_nv04_context(ctx
);
76 static struct tnl_attr_map map
[NUM_VERTEX_ATTRS
];
79 tnl
->vb
.AttribPtr
[VERT_ATTRIB_POS
] = tnl
->vb
.NdcPtr
;
81 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
82 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
83 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
84 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
85 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_TEX0
, EMIT_2F
);
86 if (nv04_mtex_engine(fahrenheit
))
87 swtnl_emit_attr(ctx
, &map
[n
++], _TNL_ATTRIB_TEX1
, EMIT_2F
);
89 swtnl_update_viewport(ctx
);
91 _tnl_install_attrs(ctx
, map
, n
, nctx
->viewport
, 0);
94 /* TnL renderer entry points */
97 swtnl_restart_ttri(struct nv04_context
*nv04
, struct nouveau_pushbuf
*push
)
99 BEGIN_NV04(push
, NV04_TTRI(COLORKEY
), 7);
100 PUSH_DATA (push
, nv04
->colorkey
);
101 PUSH_RELOC(push
, nv04
->texture
[0]->bo
, nv04
->texture
[0]->offset
,
102 NOUVEAU_BO_LOW
, 0, 0);
103 PUSH_RELOC(push
, nv04
->texture
[0]->bo
, nv04
->format
[0], NOUVEAU_BO_OR
,
104 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A
,
105 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B
);
106 PUSH_DATA (push
, nv04
->filter
[0]);
107 PUSH_DATA (push
, nv04
->blend
);
108 PUSH_DATA (push
, nv04
->ctrl
[0] & ~0x3e000000);
109 PUSH_DATA (push
, nv04
->fog
);
113 swtnl_restart_mtri(struct nv04_context
*nv04
, struct nouveau_pushbuf
*push
)
115 BEGIN_NV04(push
, NV04_MTRI(OFFSET(0)), 8);
116 PUSH_RELOC(push
, nv04
->texture
[0]->bo
, nv04
->texture
[0]->offset
,
117 NOUVEAU_BO_LOW
, 0, 0);
118 PUSH_RELOC(push
, nv04
->texture
[1]->bo
, nv04
->texture
[1]->offset
,
119 NOUVEAU_BO_LOW
, 0, 0);
120 PUSH_RELOC(push
, nv04
->texture
[0]->bo
, nv04
->format
[0], NOUVEAU_BO_OR
,
121 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A
,
122 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B
);
123 PUSH_RELOC(push
, nv04
->texture
[1]->bo
, nv04
->format
[1], NOUVEAU_BO_OR
,
124 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A
,
125 NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B
);
126 PUSH_DATA (push
, nv04
->filter
[0]);
127 PUSH_DATA (push
, nv04
->filter
[1]);
128 PUSH_DATA (push
, nv04
->alpha
[0]);
129 PUSH_DATA (push
, nv04
->color
[0]);
130 BEGIN_NV04(push
, NV04_MTRI(COMBINE_ALPHA(1)), 8);
131 PUSH_DATA (push
, nv04
->alpha
[1]);
132 PUSH_DATA (push
, nv04
->color
[1]);
133 PUSH_DATA (push
, nv04
->factor
);
134 PUSH_DATA (push
, nv04
->blend
& ~0x0000000f);
135 PUSH_DATA (push
, nv04
->ctrl
[0]);
136 PUSH_DATA (push
, nv04
->ctrl
[1]);
137 PUSH_DATA (push
, nv04
->ctrl
[2]);
138 PUSH_DATA (push
, nv04
->fog
);
142 swtnl_restart(struct gl_context
*ctx
, int multi
, unsigned vertex_size
)
144 const int tex_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
;
145 struct nv04_context
*nv04
= to_nv04_context(ctx
);
146 struct nouveau_pushbuf
*push
= context_push(ctx
);
147 struct nouveau_pushbuf_refn refs
[] = {
148 { nv04
->texture
[0]->bo
, tex_flags
},
149 { nv04
->texture
[1]->bo
, tex_flags
},
152 /* wait for enough space for state, and at least one whole primitive */
153 if (nouveau_pushbuf_space(push
, 32 + (4 * vertex_size
), 4, 0) ||
154 nouveau_pushbuf_refn (push
, refs
, multi
? 2 : 1))
157 /* emit engine state */
159 swtnl_restart_mtri(nv04
, push
);
161 swtnl_restart_ttri(nv04
, push
);
167 swtnl_start(struct gl_context
*ctx
)
169 struct nouveau_object
*eng3d
= nv04_context_engine(ctx
);
170 struct nouveau_pushbuf
*push
= context_push(ctx
);
171 unsigned vertex_size
;
173 nouveau_pushbuf_bufctx(push
, push
->user_priv
);
174 nouveau_pushbuf_validate(push
);
176 swtnl_choose_attrs(ctx
);
178 vertex_size
= TNL_CONTEXT(ctx
)->clipspace
.vertex_size
/ 4;
179 if (eng3d
->oclass
== NV04_MULTITEX_TRIANGLE_CLASS
)
180 swtnl_restart(ctx
, 1, vertex_size
);
182 swtnl_restart(ctx
, 0, vertex_size
);
186 swtnl_finish(struct gl_context
*ctx
)
188 struct nouveau_pushbuf
*push
= context_push(ctx
);
190 nouveau_pushbuf_bufctx(push
, NULL
);
194 swtnl_primitive(struct gl_context
*ctx
, GLenum mode
)
199 swtnl_reset_stipple(struct gl_context
*ctx
)
203 /* Primitive rendering */
205 #define BEGIN_PRIMITIVE(n) \
206 struct nouveau_object *eng3d = to_nv04_context(ctx)->eng3d; \
207 struct nouveau_pushbuf *push = context_push(ctx); \
208 int vertex_size = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4; \
209 int multi = (eng3d->oclass == NV04_MULTITEX_TRIANGLE_CLASS); \
211 if (PUSH_AVAIL(push) < 32 + (n * vertex_size)) { \
212 if (!swtnl_restart(ctx, multi, vertex_size)) \
216 BEGIN_NV04(push, NV04_TTRI(TLVERTEX_SX(0)), n * vertex_size);
218 #define OUT_VERTEX(i) \
219 PUSH_DATAp(push, _tnl_get_vertex(ctx, i), vertex_size);
221 #define END_PRIMITIVE(draw) \
223 BEGIN_NV04(push, NV04_MTRI(DRAWPRIMITIVE(0)), 1); \
224 PUSH_DATA (push, draw); \
226 BEGIN_NV04(push, NV04_TTRI(DRAWPRIMITIVE(0)), 1); \
227 PUSH_DATA (push, draw); \
231 swtnl_points(struct gl_context
*ctx
, GLuint first
, GLuint last
)
236 swtnl_line(struct gl_context
*ctx
, GLuint v1
, GLuint v2
)
241 swtnl_triangle(struct gl_context
*ctx
, GLuint v1
, GLuint v2
, GLuint v3
)
247 END_PRIMITIVE(0x102);
251 swtnl_quad(struct gl_context
*ctx
, GLuint v1
, GLuint v2
, GLuint v3
, GLuint v4
)
258 END_PRIMITIVE(0x213103);
261 /* TnL initialization. */
263 nv04_render_init(struct gl_context
*ctx
)
265 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
267 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
268 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
269 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
270 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
271 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
272 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
274 tnl
->Driver
.Render
.Start
= swtnl_start
;
275 tnl
->Driver
.Render
.Finish
= swtnl_finish
;
276 tnl
->Driver
.Render
.PrimitiveNotify
= swtnl_primitive
;
277 tnl
->Driver
.Render
.ResetLineStipple
= swtnl_reset_stipple
;
279 tnl
->Driver
.Render
.Points
= swtnl_points
;
280 tnl
->Driver
.Render
.Line
= swtnl_line
;
281 tnl
->Driver
.Render
.Triangle
= swtnl_triangle
;
282 tnl
->Driver
.Render
.Quad
= swtnl_quad
;
284 _tnl_need_projected_coords(ctx
, GL_TRUE
);
285 _tnl_init_vertices(ctx
, tnl
->vb
.Size
,
286 NUM_VERTEX_ATTRS
* 4 * sizeof(GLfloat
));
287 _tnl_allow_pixel_fog(ctx
, GL_FALSE
);
292 nv04_render_destroy(struct gl_context
*ctx
)