Merge branch 'master' into crestline
[mesa.git] / src / mesa / drivers / dri / i965 / brw_exec_draw.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "enums.h"
31 #include "state.h"
32 #include "macros.h"
33
34 #include "brw_exec.h"
35 #include "brw_draw.h"
36 #include "brw_fallback.h"
37
38
39 static void brw_exec_debug_verts( struct brw_exec_context *exec )
40 {
41 GLuint count = exec->vtx.vert_count;
42 GLuint i;
43
44 _mesa_printf("%s: %u vertices %d primitives, %d vertsize\n",
45 __FUNCTION__,
46 count,
47 exec->vtx.prim_count,
48 exec->vtx.vertex_size);
49
50 for (i = 0 ; i < exec->vtx.prim_count ; i++) {
51 struct brw_draw_prim *prim = &exec->vtx.prim[i];
52 _mesa_printf(" prim %d: %s%s %d..%d %s %s\n",
53 i,
54 _mesa_lookup_enum_by_nr(prim->mode),
55 prim->weak ? " (weak)" : "",
56 prim->start,
57 prim->start + prim->count,
58 prim->begin ? "BEGIN" : "(wrap)",
59 prim->end ? "END" : "(wrap)");
60 }
61 }
62
63
64 /*
65 * NOTE: Need to have calculated primitives by this point -- do it on the fly.
66 * NOTE: Old 'parity' issue is gone.
67 */
68 static GLuint brw_copy_vertices( struct brw_exec_context *exec )
69 {
70 GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
71 GLuint ovf, i;
72 GLuint sz = exec->vtx.vertex_size;
73 GLfloat *dst = exec->vtx.copied.buffer;
74 GLfloat *src = ((GLfloat *)exec->vtx.buffer_map +
75 exec->vtx.prim[exec->vtx.prim_count-1].start *
76 exec->vtx.vertex_size);
77
78
79 switch( exec->ctx->Driver.CurrentExecPrimitive )
80 {
81 case GL_POINTS:
82 return 0;
83 case GL_LINES:
84 ovf = nr&1;
85 for (i = 0 ; i < ovf ; i++)
86 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
87 return i;
88 case GL_TRIANGLES:
89 ovf = nr%3;
90 for (i = 0 ; i < ovf ; i++)
91 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
92 return i;
93 case GL_QUADS:
94 ovf = nr&3;
95 for (i = 0 ; i < ovf ; i++)
96 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
97 return i;
98 case GL_LINE_STRIP:
99 if (nr == 0)
100 return 0;
101 else {
102 _mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
103 return 1;
104 }
105 case GL_LINE_LOOP:
106 case GL_TRIANGLE_FAN:
107 case GL_POLYGON:
108 if (nr == 0)
109 return 0;
110 else if (nr == 1) {
111 _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
112 return 1;
113 } else {
114 _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
115 _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
116 return 2;
117 }
118 case GL_TRIANGLE_STRIP:
119 case GL_QUAD_STRIP:
120 switch (nr) {
121 case 0: ovf = 0; break;
122 case 1: ovf = 1; break;
123 default: ovf = 2 + (nr&1); break;
124 }
125 for (i = 0 ; i < ovf ; i++)
126 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
127 return i;
128 case GL_POLYGON+1:
129 return 0;
130 default:
131 assert(0);
132 return 0;
133 }
134 }
135
136
137 /* TODO: populate these as the vertex is defined:
138 */
139 static void brw_exec_bind_arrays( struct brw_exec_context *exec )
140 {
141 struct gl_client_array *arrays = exec->vtx.arrays;
142 GLuint count = exec->vtx.vert_count;
143 GLubyte *data = exec->vtx.buffer_map;
144 GLuint attr;
145
146 memset(arrays, 0, BRW_ATTRIB_MAX * sizeof(arrays[0]));
147
148 /* Make all active attributes (including edgeflag) available as
149 * arrays of floats.
150 */
151 for (attr = 0; attr < BRW_ATTRIB_MAX ; attr++) {
152 if (exec->vtx.attrsz[attr]) {
153 arrays[attr].Ptr = (void *)data;
154 arrays[attr].Size = exec->vtx.attrsz[attr];
155 arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
156 arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
157 arrays[attr].Type = GL_FLOAT;
158 arrays[attr].Enabled = 1;
159 arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */
160 arrays[attr]._MaxElement = count; /* ??? */
161
162 data += exec->vtx.attrsz[attr] * sizeof(GLfloat);
163 }
164 }
165 }
166
167
168 static
169 void brw_exec_loopback_vertex_list( GLcontext *ctx,
170 struct brw_exec_context *exec )
171 {
172 const GLfloat *buffer = (const GLfloat *)exec->vtx.buffer_map;
173
174 brw_fallback(ctx);
175
176 brw_loopback_vertex_list( ctx,
177 buffer,
178 exec->vtx.attrsz,
179 exec->vtx.prim,
180 exec->vtx.prim_count,
181 0, /* XXX - copied.nr */
182 exec->vtx.vertex_size);
183
184
185 brw_unfallback(ctx);
186 }
187
188
189 /**
190 * Execute the buffer and save copied verts.
191 */
192 void brw_exec_vtx_flush( struct brw_exec_context *exec )
193 {
194 if (0)
195 brw_exec_debug_verts( exec );
196
197
198 if (exec->vtx.prim_count &&
199 exec->vtx.vert_count) {
200
201 exec->vtx.copied.nr = brw_copy_vertices( exec );
202
203 if (exec->vtx.copied.nr != exec->vtx.vert_count) {
204 GLcontext *ctx = exec->ctx;
205
206 brw_exec_bind_arrays( exec );
207
208
209 if (!brw_draw_prims( ctx,
210 exec->vtx.inputs,
211 exec->vtx.prim,
212 exec->vtx.prim_count,
213 NULL,
214 0,
215 exec->vtx.vert_count,
216 0 )) {
217 /* Fallback path:
218 */
219 brw_exec_loopback_vertex_list(ctx, exec);
220 }
221 }
222 }
223
224 exec->vtx.prim_count = 0;
225 exec->vtx.vert_count = 0;
226 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
227 }