Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / nouveau / nouveau_swtnl_t.c
1 /*
2  * Copyright (C) 2009-2010 Francisco Jerez.
3  * All Rights Reserved.
4  *
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:
12  *
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.
16  *
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.
24  *
25  */
26
27 #include "tnl/t_context.h"
28 #include "tnl/t_pipeline.h"
29 #include "tnl/t_vertex.h"
30
31 #define SWTNL_VBO_SIZE 65536
32
33 static enum tnl_attr_format
34 swtnl_get_format(int type, int fields) {
35         switch (type) {
36         case GL_FLOAT:
37                 switch (fields){
38                 case 1:
39                         return EMIT_1F;
40                 case 2:
41                         return EMIT_2F;
42                 case 3:
43                         return EMIT_3F;
44                 case 4:
45                         return EMIT_4F;
46                 default:
47                         assert(0);
48                 }
49         case GL_UNSIGNED_BYTE:
50                 switch (fields) {
51                 case 4:
52                         return EMIT_4UB_4F_RGBA;
53                 default:
54                         assert(0);
55                 }
56         default:
57                 assert(0);
58         }
59 }
60
61 static struct swtnl_attr_info {
62         int type;
63         int fields;
64 } swtnl_attrs[VERT_ATTRIB_MAX] = {
65         [VERT_ATTRIB_POS] = {
66                 .type = GL_FLOAT,
67                 .fields = 4,
68         },
69         [VERT_ATTRIB_NORMAL] = {
70                 .type = GL_FLOAT,
71                 .fields = -1,
72         },
73         [VERT_ATTRIB_COLOR0] = {
74                 .type = GL_UNSIGNED_BYTE,
75                 .fields = 4,
76         },
77         [VERT_ATTRIB_COLOR1] = {
78                 .type = GL_UNSIGNED_BYTE,
79                 .fields = 4,
80         },
81         [VERT_ATTRIB_FOG] = {
82                 .type = GL_FLOAT,
83                 .fields = 1,
84         },
85         [VERT_ATTRIB_TEX0] = {
86                 .type = GL_FLOAT,
87                 .fields = -1,
88         },
89         [VERT_ATTRIB_TEX1] = {
90                 .type = GL_FLOAT,
91                 .fields = -1,
92         },
93         [VERT_ATTRIB_TEX2] = {
94                 .type = GL_FLOAT,
95                 .fields = -1,
96         },
97         [VERT_ATTRIB_TEX3] = {
98                 .type = GL_FLOAT,
99                 .fields = -1,
100         },
101 };
102
103 static void
104 swtnl_choose_attrs(struct gl_context *ctx)
105 {
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;
111
112         render->mode = VBO;
113         render->attr_count = NUM_VERTEX_ATTRS;
114
115         /* We always want non Ndc coords format */
116         tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.ClipPtr;
117
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];
122
123                 if (!sa->fields)
124                         continue; /* Unsupported attribute. */
125
126                 if (RENDERINPUTS_TEST(tnl->render_inputs_bitset, i)) {
127                         if (sa->fields > 0)
128                                 fields = sa->fields;
129                         else
130                                 fields = tnl->vb.AttribPtr[i]->size;
131
132                         map[n++] = (struct tnl_attr_map) {
133                                 .attrib = i,
134                                 .format = swtnl_get_format(sa->type, fields),
135                         };
136
137                         render->map[ha->vbo_index] = i;
138                         a->attr = i;
139                         a->fields = fields;
140                         a->type = sa->type;
141                 }
142         }
143
144         _tnl_install_attrs(ctx, map, n, NULL, 0);
145
146         FOR_EACH_BOUND_ATTR(render, i, attr)
147                 render->attrs[attr].stride = vtx->vertex_size;
148
149         TAG(render_set_format)(ctx);
150 }
151
152 static void
153 swtnl_alloc_vertices(struct gl_context *ctx)
154 {
155         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
156
157         nouveau_bo_ref(NULL, &swtnl->vbo);
158         swtnl->buf = nouveau_get_scratch(ctx, SWTNL_VBO_SIZE, &swtnl->vbo,
159                                          &swtnl->offset);
160         swtnl->vertex_count = 0;
161 }
162
163 static void
164 swtnl_bind_vertices(struct gl_context *ctx)
165 {
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;
169         int i;
170
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];
174
175                 nouveau_bo_ref(swtnl->vbo, &a->bo);
176                 a->offset = swtnl->offset + ta->vertoffset;
177         }
178
179         TAG(render_bind_vertices)(ctx);
180 }
181
182 static void
183 swtnl_unbind_vertices(struct gl_context *ctx)
184 {
185         struct nouveau_render_state *render = to_render_state(ctx);
186         int i, attr;
187
188         FOR_EACH_BOUND_ATTR(render, i, attr) {
189                 nouveau_bo_ref(NULL, &render->attrs[attr].bo);
190                 render->map[i] = -1;
191         }
192
193         render->attr_count = 0;
194 }
195
196 static void
197 swtnl_flush_vertices(struct gl_context *ctx)
198 {
199         struct nouveau_channel *chan = context_chan(ctx);
200         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
201         unsigned push, start = 0, count = swtnl->vertex_count;
202         RENDER_LOCALS(ctx);
203
204         swtnl_bind_vertices(ctx);
205
206         while (count) {
207                 push = get_max_vertices(ctx, NULL, AVAIL_RING(chan));
208                 push = MIN2(push / 12 * 12, count);
209                 count -= push;
210
211                 if (!push) {
212                         FIRE_RING(chan);
213                         continue;
214                 }
215
216                 BATCH_BEGIN(nvgl_primitive(swtnl->primitive));
217                 EMIT_VBO(L, ctx, start, 0, push);
218                 BATCH_END();
219
220                 FIRE_RING(chan);
221         }
222
223         swtnl_alloc_vertices(ctx);
224 }
225
226 /* TnL renderer entry points */
227
228 static void
229 swtnl_start(struct gl_context *ctx)
230 {
231         swtnl_choose_attrs(ctx);
232 }
233
234 static void
235 swtnl_finish(struct gl_context *ctx)
236 {
237         swtnl_flush_vertices(ctx);
238         swtnl_unbind_vertices(ctx);
239 }
240
241 static void
242 swtnl_primitive(struct gl_context *ctx, GLenum mode)
243 {
244 }
245
246 static void
247 swtnl_reset_stipple(struct gl_context *ctx)
248 {
249 }
250
251 /* Primitive rendering */
252
253 #define BEGIN_PRIMITIVE(p, n)                                           \
254         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; \
255         int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size;       \
256                                                                         \
257         if (swtnl->vertex_count + (n) > SWTNL_VBO_SIZE/vertex_len       \
258             || (swtnl->vertex_count && swtnl->primitive != p))          \
259                 swtnl_flush_vertices(ctx);                              \
260                                                                         \
261         swtnl->primitive = p;
262
263 #define OUT_VERTEX(i) do {                                              \
264                 memcpy(swtnl->buf + swtnl->vertex_count * vertex_len,   \
265                        _tnl_get_vertex(ctx, (i)), vertex_len);          \
266                 swtnl->vertex_count++;                                  \
267         } while (0)
268
269 static void
270 swtnl_points(struct gl_context *ctx, GLuint first, GLuint last)
271 {
272         int i, count;
273
274         while (first < last) {
275                 BEGIN_PRIMITIVE(GL_POINTS, last - first);
276
277                 count = MIN2(SWTNL_VBO_SIZE / vertex_len, last - first);
278                 for (i = 0; i < count; i++)
279                         OUT_VERTEX(first + i);
280
281                 first += count;
282         }
283 }
284
285 static void
286 swtnl_line(struct gl_context *ctx, GLuint v1, GLuint v2)
287 {
288         BEGIN_PRIMITIVE(GL_LINES, 2);
289         OUT_VERTEX(v1);
290         OUT_VERTEX(v2);
291 }
292
293 static void
294 swtnl_triangle(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3)
295 {
296         BEGIN_PRIMITIVE(GL_TRIANGLES, 3);
297         OUT_VERTEX(v1);
298         OUT_VERTEX(v2);
299         OUT_VERTEX(v3);
300 }
301
302 static void
303 swtnl_quad(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4)
304 {
305         BEGIN_PRIMITIVE(GL_QUADS, 4);
306         OUT_VERTEX(v1);
307         OUT_VERTEX(v2);
308         OUT_VERTEX(v3);
309         OUT_VERTEX(v4);
310 }
311
312 /* TnL initialization. */
313 void
314 TAG(swtnl_init)(struct gl_context *ctx)
315 {
316         TNLcontext *tnl = TNL_CONTEXT(ctx);
317
318         tnl->Driver.RunPipeline = _tnl_run_pipeline;
319         tnl->Driver.Render.Interp = _tnl_interp;
320         tnl->Driver.Render.CopyPV = _tnl_copy_pv;
321         tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
322         tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
323         tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
324
325         tnl->Driver.Render.Start = swtnl_start;
326         tnl->Driver.Render.Finish = swtnl_finish;
327         tnl->Driver.Render.PrimitiveNotify = swtnl_primitive;
328         tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple;
329
330         tnl->Driver.Render.Points = swtnl_points;
331         tnl->Driver.Render.Line = swtnl_line;
332         tnl->Driver.Render.Triangle = swtnl_triangle;
333         tnl->Driver.Render.Quad = swtnl_quad;
334
335         _tnl_init_vertices(ctx, tnl->vb.Size,
336                            NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat));
337         _tnl_need_projected_coords(ctx, GL_FALSE);
338         _tnl_allow_vertex_fog(ctx, GL_FALSE);
339         _tnl_wakeup(ctx);
340
341         swtnl_alloc_vertices(ctx);
342 }
343
344 void
345 TAG(swtnl_destroy)(struct gl_context *ctx)
346 {
347         nouveau_bo_ref(NULL, &to_render_state(ctx)->swtnl.vbo);
348 }