Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * Version: 7.2 |
||
4 | * |
||
5 | * Copyright (C) 1999-2008 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 | |||
25 | /* Author: |
||
26 | * Keith Whitwell |
||
27 | */ |
||
28 | |||
29 | #include "main/glheader.h" |
||
30 | #include "main/bufferobj.h" |
||
31 | #include "main/context.h" |
||
32 | #include "main/imports.h" |
||
33 | #include "main/mtypes.h" |
||
34 | #include "main/macros.h" |
||
35 | #include "main/light.h" |
||
36 | #include "main/state.h" |
||
37 | |||
38 | #include "vbo_context.h" |
||
39 | |||
40 | |||
41 | #if FEATURE_dlist |
||
42 | |||
43 | |||
44 | /** |
||
45 | * After playback, copy everything but the position from the |
||
46 | * last vertex to the saved state |
||
47 | */ |
||
48 | static void |
||
49 | _playback_copy_to_current(struct gl_context *ctx, |
||
50 | const struct vbo_save_vertex_list *node) |
||
51 | { |
||
52 | struct vbo_context *vbo = vbo_context(ctx); |
||
53 | GLfloat vertex[VBO_ATTRIB_MAX * 4]; |
||
54 | GLfloat *data; |
||
55 | GLuint i, offset; |
||
56 | |||
57 | if (node->current_size == 0) |
||
58 | return; |
||
59 | |||
60 | if (node->current_data) { |
||
61 | data = node->current_data; |
||
62 | } |
||
63 | else { |
||
64 | data = vertex; |
||
65 | |||
66 | if (node->count) |
||
67 | offset = (node->buffer_offset + |
||
68 | (node->count-1) * node->vertex_size * sizeof(GLfloat)); |
||
69 | else |
||
70 | offset = node->buffer_offset; |
||
71 | |||
72 | ctx->Driver.GetBufferSubData( ctx, 0, offset, |
||
73 | node->vertex_size * sizeof(GLfloat), |
||
74 | data, node->vertex_store->bufferobj ); |
||
75 | |||
76 | data += node->attrsz[0]; /* skip vertex position */ |
||
77 | } |
||
78 | |||
79 | for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { |
||
80 | if (node->attrsz[i]) { |
||
81 | GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; |
||
82 | GLfloat tmp[4]; |
||
83 | |||
84 | COPY_CLEAN_4V(tmp, |
||
85 | node->attrsz[i], |
||
86 | data); |
||
87 | |||
88 | if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) { |
||
89 | memcpy(current, tmp, 4 * sizeof(GLfloat)); |
||
90 | |||
91 | vbo->currval[i].Size = node->attrsz[i]; |
||
92 | |||
93 | if (i >= VBO_ATTRIB_FIRST_MATERIAL && |
||
94 | i <= VBO_ATTRIB_LAST_MATERIAL) |
||
95 | ctx->NewState |= _NEW_LIGHT; |
||
96 | |||
97 | ctx->NewState |= _NEW_CURRENT_ATTRIB; |
||
98 | } |
||
99 | |||
100 | data += node->attrsz[i]; |
||
101 | } |
||
102 | } |
||
103 | |||
104 | /* Colormaterial -- this kindof sucks. |
||
105 | */ |
||
106 | if (ctx->Light.ColorMaterialEnabled) { |
||
107 | _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); |
||
108 | } |
||
109 | |||
110 | /* CurrentExecPrimitive |
||
111 | */ |
||
112 | if (node->prim_count) { |
||
113 | const struct _mesa_prim *prim = &node->prim[node->prim_count - 1]; |
||
114 | if (prim->end) |
||
115 | ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; |
||
116 | else |
||
117 | ctx->Driver.CurrentExecPrimitive = prim->mode; |
||
118 | } |
||
119 | } |
||
120 | |||
121 | |||
122 | |||
123 | /** |
||
124 | * Treat the vertex storage as a VBO, define vertex arrays pointing |
||
125 | * into it: |
||
126 | */ |
||
127 | static void vbo_bind_vertex_list(struct gl_context *ctx, |
||
128 | const struct vbo_save_vertex_list *node) |
||
129 | { |
||
130 | struct vbo_context *vbo = vbo_context(ctx); |
||
131 | struct vbo_save_context *save = &vbo->save; |
||
132 | struct gl_client_array *arrays = save->arrays; |
||
133 | GLuint buffer_offset = node->buffer_offset; |
||
134 | const GLuint *map; |
||
135 | GLuint attr; |
||
136 | GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */ |
||
137 | GLbitfield varying_inputs = 0x0; |
||
138 | |||
139 | memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); |
||
140 | |||
141 | /* Install the default (ie Current) attributes first, then overlay |
||
142 | * all active ones. |
||
143 | */ |
||
144 | switch (get_program_mode(ctx)) { |
||
145 | case VP_NONE: |
||
146 | for (attr = 0; attr < 16; attr++) { |
||
147 | save->inputs[attr] = &vbo->legacy_currval[attr]; |
||
148 | } |
||
149 | for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { |
||
150 | save->inputs[attr + 16] = &vbo->mat_currval[attr]; |
||
151 | } |
||
152 | map = vbo->map_vp_none; |
||
153 | break; |
||
154 | case VP_NV: |
||
155 | case VP_ARB: |
||
156 | /* The aliasing of attributes for NV vertex programs has already |
||
157 | * occurred. NV vertex programs cannot access material values, |
||
158 | * nor attributes greater than VERT_ATTRIB_TEX7. |
||
159 | */ |
||
160 | for (attr = 0; attr < 16; attr++) { |
||
161 | save->inputs[attr] = &vbo->legacy_currval[attr]; |
||
162 | save->inputs[attr + 16] = &vbo->generic_currval[attr]; |
||
163 | } |
||
164 | map = vbo->map_vp_arb; |
||
165 | |||
166 | /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. |
||
167 | * In that case we effectively need to route the data from |
||
168 | * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. |
||
169 | */ |
||
170 | if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && |
||
171 | (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { |
||
172 | save->inputs[16] = save->inputs[0]; |
||
173 | node_attrsz[16] = node_attrsz[0]; |
||
174 | node_attrsz[0] = 0; |
||
175 | } |
||
176 | break; |
||
177 | default: |
||
178 | assert(0); |
||
179 | } |
||
180 | |||
181 | for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
||
182 | const GLuint src = map[attr]; |
||
183 | |||
184 | if (node_attrsz[src]) { |
||
185 | /* override the default array set above */ |
||
186 | save->inputs[attr] = &arrays[attr]; |
||
187 | |||
188 | arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; |
||
189 | arrays[attr].Size = node->attrsz[src]; |
||
190 | arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); |
||
191 | arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); |
||
192 | arrays[attr].Type = GL_FLOAT; |
||
193 | arrays[attr].Format = GL_RGBA; |
||
194 | arrays[attr].Enabled = 1; |
||
195 | _mesa_reference_buffer_object(ctx, |
||
196 | &arrays[attr].BufferObj, |
||
197 | node->vertex_store->bufferobj); |
||
198 | arrays[attr]._MaxElement = node->count; /* ??? */ |
||
199 | |||
200 | assert(arrays[attr].BufferObj->Name); |
||
201 | |||
202 | buffer_offset += node->attrsz[src] * sizeof(GLfloat); |
||
203 | varying_inputs |= 1< |
||
204 | } |
||
205 | } |
||
206 | |||
207 | _mesa_set_varying_vp_inputs( ctx, varying_inputs ); |
||
208 | } |
||
209 | |||
210 | |||
211 | static void |
||
212 | vbo_save_loopback_vertex_list(struct gl_context *ctx, |
||
213 | const struct vbo_save_vertex_list *list) |
||
214 | { |
||
215 | const char *buffer = ctx->Driver.MapBuffer(ctx, |
||
216 | GL_ARRAY_BUFFER_ARB, |
||
217 | GL_READ_ONLY, /* ? */ |
||
218 | list->vertex_store->bufferobj); |
||
219 | |||
220 | vbo_loopback_vertex_list(ctx, |
||
221 | (const GLfloat *)(buffer + list->buffer_offset), |
||
222 | list->attrsz, |
||
223 | list->prim, |
||
224 | list->prim_count, |
||
225 | list->wrap_count, |
||
226 | list->vertex_size); |
||
227 | |||
228 | ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, |
||
229 | list->vertex_store->bufferobj); |
||
230 | } |
||
231 | |||
232 | |||
233 | /** |
||
234 | * Execute the buffer and save copied verts. |
||
235 | * This is called from the display list code when executing |
||
236 | * a drawing command. |
||
237 | */ |
||
238 | void |
||
239 | vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) |
||
240 | { |
||
241 | const struct vbo_save_vertex_list *node = |
||
242 | (const struct vbo_save_vertex_list *) data; |
||
243 | struct vbo_save_context *save = &vbo_context(ctx)->save; |
||
244 | |||
245 | FLUSH_CURRENT(ctx, 0); |
||
246 | |||
247 | if (node->prim_count > 0 && node->count > 0) { |
||
248 | |||
249 | if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && |
||
250 | node->prim[0].begin) { |
||
251 | |||
252 | /* Degenerate case: list is called inside begin/end pair and |
||
253 | * includes operations such as glBegin or glDrawArrays. |
||
254 | */ |
||
255 | if (0) |
||
256 | printf("displaylist recursive begin"); |
||
257 | |||
258 | vbo_save_loopback_vertex_list( ctx, node ); |
||
259 | return; |
||
260 | } |
||
261 | else if (save->replay_flags) { |
||
262 | /* Various degnerate cases: translate into immediate mode |
||
263 | * calls rather than trying to execute in place. |
||
264 | */ |
||
265 | vbo_save_loopback_vertex_list( ctx, node ); |
||
266 | return; |
||
267 | } |
||
268 | |||
269 | if (ctx->NewState) |
||
270 | _mesa_update_state( ctx ); |
||
271 | |||
272 | /* XXX also need to check if shader enabled, but invalid */ |
||
273 | if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || |
||
274 | (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { |
||
275 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
276 | "glBegin (invalid vertex/fragment program)"); |
||
277 | return; |
||
278 | } |
||
279 | |||
280 | vbo_bind_vertex_list( ctx, node ); |
||
281 | |||
282 | /* Again... |
||
283 | */ |
||
284 | if (ctx->NewState) |
||
285 | _mesa_update_state( ctx ); |
||
286 | |||
287 | vbo_context(ctx)->draw_prims(ctx, |
||
288 | save->inputs, |
||
289 | node->prim, |
||
290 | node->prim_count, |
||
291 | NULL, |
||
292 | GL_TRUE, |
||
293 | 0, /* Node is a VBO, so this is ok */ |
||
294 | node->count - 1); |
||
295 | } |
||
296 | |||
297 | /* Copy to current? |
||
298 | */ |
||
299 | _playback_copy_to_current( ctx, node ); |
||
300 | } |
||
301 | |||
302 | |||
303 | #endif /* FEATURE_dlist */ |