[THEMES]
[reactos.git] / reactos / dll / opengl / mesa / vbo / vbo_save_draw.c
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 <keith@tungstengraphics.com>
27 */
28
29 #include <precomp.h>
30
31 #if FEATURE_dlist
32
33
34 /**
35 * After playback, copy everything but the position from the
36 * last vertex to the saved state
37 */
38 static void
39 _playback_copy_to_current(struct gl_context *ctx,
40 const struct vbo_save_vertex_list *node)
41 {
42 struct vbo_context *vbo = vbo_context(ctx);
43 GLfloat vertex[VBO_ATTRIB_MAX * 4];
44 GLfloat *data;
45 GLuint i, offset;
46
47 if (node->current_size == 0)
48 return;
49
50 if (node->current_data) {
51 data = node->current_data;
52 }
53 else {
54 data = vertex;
55
56 if (node->count)
57 offset = (node->buffer_offset +
58 (node->count-1) * node->vertex_size * sizeof(GLfloat));
59 else
60 offset = node->buffer_offset;
61
62 ctx->Driver.GetBufferSubData( ctx, offset,
63 node->vertex_size * sizeof(GLfloat),
64 data, node->vertex_store->bufferobj );
65
66 data += node->attrsz[0]; /* skip vertex position */
67 }
68
69 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
70 if (node->attrsz[i]) {
71 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
72 GLfloat tmp[4];
73
74 COPY_CLEAN_4V(tmp,
75 node->attrsz[i],
76 data);
77
78 if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
79 memcpy(current, tmp, 4 * sizeof(GLfloat));
80
81 vbo->currval[i].Size = node->attrsz[i];
82 assert(vbo->currval[i].Type == GL_FLOAT);
83 vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
84
85 if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
86 i <= VBO_ATTRIB_LAST_MATERIAL)
87 ctx->NewState |= _NEW_LIGHT;
88
89 ctx->NewState |= _NEW_CURRENT_ATTRIB;
90 }
91
92 data += node->attrsz[i];
93 }
94 }
95
96 /* Colormaterial -- this kindof sucks.
97 */
98 if (ctx->Light.ColorMaterialEnabled) {
99 _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
100 }
101
102 /* CurrentExecPrimitive
103 */
104 if (node->prim_count) {
105 const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
106 if (prim->end)
107 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
108 else
109 ctx->Driver.CurrentExecPrimitive = prim->mode;
110 }
111 }
112
113
114
115 /**
116 * Treat the vertex storage as a VBO, define vertex arrays pointing
117 * into it:
118 */
119 static void vbo_bind_vertex_list(struct gl_context *ctx,
120 const struct vbo_save_vertex_list *node)
121 {
122 struct vbo_context *vbo = vbo_context(ctx);
123 struct vbo_save_context *save = &vbo->save;
124 struct gl_client_array *arrays = save->arrays;
125 GLuint buffer_offset = node->buffer_offset;
126 GLuint attr;
127 GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
128 GLbitfield64 varying_inputs = 0x0;
129
130 memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
131
132 /* Install the default (ie Current) attributes first, then overlay
133 * all active ones.
134 */
135 for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) {
136 save->inputs[attr] = &vbo->currval[attr];
137 }
138
139 for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) {
140
141 if (node_attrsz[attr]) {
142 /* override the default array set above */
143 save->inputs[attr] = &arrays[attr];
144
145 arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
146 arrays[attr].Size = node_attrsz[attr];
147 arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
148 arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
149 arrays[attr].Type = GL_FLOAT;
150 arrays[attr].Enabled = 1;
151 arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
152 _mesa_reference_buffer_object(ctx,
153 &arrays[attr].BufferObj,
154 node->vertex_store->bufferobj);
155 arrays[attr]._MaxElement = node->count; /* ??? */
156
157 assert(arrays[attr].BufferObj->Name);
158
159 buffer_offset += node_attrsz[attr] * sizeof(GLfloat);
160 varying_inputs |= VERT_BIT(attr);
161 ctx->NewState |= _NEW_ARRAY;
162 }
163 }
164 }
165
166
167 static void
168 vbo_save_loopback_vertex_list(struct gl_context *ctx,
169 const struct vbo_save_vertex_list *list)
170 {
171 const char *buffer =
172 ctx->Driver.MapBufferRange(ctx, 0,
173 list->vertex_store->bufferobj->Size,
174 GL_MAP_READ_BIT, /* ? */
175 list->vertex_store->bufferobj);
176
177 vbo_loopback_vertex_list(ctx,
178 (const GLfloat *)(buffer + list->buffer_offset),
179 list->attrsz,
180 list->prim,
181 list->prim_count,
182 list->wrap_count,
183 list->vertex_size);
184
185 ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj);
186 }
187
188
189 /**
190 * Execute the buffer and save copied verts.
191 * This is called from the display list code when executing
192 * a drawing command.
193 */
194 void
195 vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
196 {
197 const struct vbo_save_vertex_list *node =
198 (const struct vbo_save_vertex_list *) data;
199 struct vbo_save_context *save = &vbo_context(ctx)->save;
200 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
201
202 FLUSH_CURRENT(ctx, 0);
203
204 if (node->prim_count > 0) {
205
206 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
207 node->prim[0].begin) {
208
209 /* Degenerate case: list is called inside begin/end pair and
210 * includes operations such as glBegin or glDrawArrays.
211 */
212 if (0)
213 printf("displaylist recursive begin");
214
215 vbo_save_loopback_vertex_list( ctx, node );
216 return;
217 }
218 else if (save->replay_flags) {
219 /* Various degnerate cases: translate into immediate mode
220 * calls rather than trying to execute in place.
221 */
222 vbo_save_loopback_vertex_list( ctx, node );
223 return;
224 }
225
226 if (ctx->NewState)
227 _mesa_update_state( ctx );
228
229 vbo_bind_vertex_list( ctx, node );
230
231 vbo_draw_method(exec, DRAW_DISPLAY_LIST);
232
233 /* Again...
234 */
235 if (ctx->NewState)
236 _mesa_update_state( ctx );
237
238 if (node->count > 0) {
239 vbo_context(ctx)->draw_prims(ctx,
240 save->inputs,
241 node->prim,
242 node->prim_count,
243 NULL,
244 GL_TRUE,
245 0, /* Node is a VBO, so this is ok */
246 node->count - 1);
247 }
248 }
249
250 /* Copy to current?
251 */
252 _playback_copy_to_current( ctx, node );
253 }
254
255
256 #endif /* FEATURE_dlist */