dynfn --> _tnl_dynfn
[mesa.git] / src / mesa / array_cache / ac_import.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 "macros.h"
30 #include "imports.h"
31 #include "mtypes.h"
32
33 #include "math/m_translate.h"
34 #include "array_cache/ac_context.h"
35 #include "math/m_translate.h"
36
37 #define STRIDE_ARRAY( array, offset ) \
38 do { \
39 GLubyte *tmp = ADD_POINTERS( (array).BufferObj->Data, (array).Ptr ) \
40 + (offset) * (array).StrideB; \
41 (array).Ptr = tmp; \
42 } while (0)
43
44
45 /* Set the array pointer back to its source when the cached data is
46 * invalidated:
47 */
48 static void reset_texcoord( GLcontext *ctx, GLuint unit )
49 {
50 ACcontext *ac = AC_CONTEXT(ctx);
51
52 if (ctx->Array.TexCoord[unit].Enabled) {
53 ac->Raw.TexCoord[unit] = ctx->Array.TexCoord[unit];
54 STRIDE_ARRAY(ac->Raw.TexCoord[unit], ac->start);
55 }
56 else {
57 ac->Raw.TexCoord[unit] = ac->Fallback.TexCoord[unit];
58
59 if (ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][3] != 1.0)
60 ac->Raw.TexCoord[unit].Size = 4;
61 else if (ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][2] != 0.0)
62 ac->Raw.TexCoord[unit].Size = 3;
63 else
64 ac->Raw.TexCoord[unit].Size = 2;
65 }
66
67 ac->IsCached.TexCoord[unit] = GL_FALSE;
68 ac->NewArrayState &= ~_NEW_ARRAY_TEXCOORD(unit);
69 }
70
71 static void reset_vertex( GLcontext *ctx )
72 {
73 ACcontext *ac = AC_CONTEXT(ctx);
74 ASSERT(ctx->Array.Vertex.Enabled
75 || (ctx->VertexProgram.Enabled && ctx->Array.VertexAttrib[0].Enabled));
76 ac->Raw.Vertex = ctx->Array.Vertex;
77 STRIDE_ARRAY(ac->Raw.Vertex, ac->start);
78 ac->IsCached.Vertex = GL_FALSE;
79 ac->NewArrayState &= ~_NEW_ARRAY_VERTEX;
80 }
81
82
83 static void reset_normal( GLcontext *ctx )
84 {
85 ACcontext *ac = AC_CONTEXT(ctx);
86
87 if (ctx->Array.Normal.Enabled) {
88 ac->Raw.Normal = ctx->Array.Normal;
89 STRIDE_ARRAY(ac->Raw.Normal, ac->start);
90 }
91 else {
92 ac->Raw.Normal = ac->Fallback.Normal;
93 }
94
95 ac->IsCached.Normal = GL_FALSE;
96 ac->NewArrayState &= ~_NEW_ARRAY_NORMAL;
97 }
98
99
100 static void reset_color( GLcontext *ctx )
101 {
102 ACcontext *ac = AC_CONTEXT(ctx);
103
104
105 if (ctx->Array.Color.Enabled) {
106 ac->Raw.Color = ctx->Array.Color;
107 STRIDE_ARRAY(ac->Raw.Color, ac->start);
108 }
109 else
110 ac->Raw.Color = ac->Fallback.Color;
111
112 ac->IsCached.Color = GL_FALSE;
113 ac->NewArrayState &= ~_NEW_ARRAY_COLOR0;
114 }
115
116
117 static void reset_secondarycolor( GLcontext *ctx )
118 {
119 ACcontext *ac = AC_CONTEXT(ctx);
120
121 if (ctx->Array.SecondaryColor.Enabled & _NEW_ARRAY_COLOR1) {
122 ac->Raw.SecondaryColor = ctx->Array.SecondaryColor;
123 STRIDE_ARRAY(ac->Raw.SecondaryColor, ac->start);
124 }
125 else
126 ac->Raw.SecondaryColor = ac->Fallback.SecondaryColor;
127
128 ac->IsCached.SecondaryColor = GL_FALSE;
129 ac->NewArrayState &= ~_NEW_ARRAY_COLOR1;
130 }
131
132
133 static void reset_index( GLcontext *ctx )
134 {
135 ACcontext *ac = AC_CONTEXT(ctx);
136
137 if (ctx->Array.Index.Enabled & _NEW_ARRAY_INDEX) {
138 ac->Raw.Index = ctx->Array.Index;
139 STRIDE_ARRAY(ac->Raw.Index, ac->start);
140 }
141 else
142 ac->Raw.Index = ac->Fallback.Index;
143
144 ac->IsCached.Index = GL_FALSE;
145 ac->NewArrayState &= ~_NEW_ARRAY_INDEX;
146 }
147
148
149 static void reset_fogcoord( GLcontext *ctx )
150 {
151 ACcontext *ac = AC_CONTEXT(ctx);
152
153 if (ctx->Array.FogCoord.Enabled & _NEW_ARRAY_FOGCOORD) {
154 ac->Raw.FogCoord = ctx->Array.FogCoord;
155 STRIDE_ARRAY(ac->Raw.FogCoord, ac->start);
156 }
157 else
158 ac->Raw.FogCoord = ac->Fallback.FogCoord;
159
160 ac->IsCached.FogCoord = GL_FALSE;
161 ac->NewArrayState &= ~_NEW_ARRAY_FOGCOORD;
162 }
163
164
165 static void reset_edgeflag( GLcontext *ctx )
166 {
167 ACcontext *ac = AC_CONTEXT(ctx);
168
169 if (ctx->Array.EdgeFlag.Enabled & _NEW_ARRAY_EDGEFLAG) {
170 ac->Raw.EdgeFlag = ctx->Array.EdgeFlag;
171 STRIDE_ARRAY(ac->Raw.EdgeFlag, ac->start);
172 }
173 else
174 ac->Raw.EdgeFlag = ac->Fallback.EdgeFlag;
175
176 ac->IsCached.EdgeFlag = GL_FALSE;
177 ac->NewArrayState &= ~_NEW_ARRAY_EDGEFLAG;
178 }
179
180
181 static void reset_attrib( GLcontext *ctx, GLuint index )
182 {
183 ACcontext *ac = AC_CONTEXT(ctx);
184
185 if (ctx->Array.VertexAttrib[index].Enabled) {
186 ac->Raw.Attrib[index] = ctx->Array.VertexAttrib[index];
187 STRIDE_ARRAY(ac->Raw.Attrib[index], ac->start);
188 }
189 else
190 ac->Raw.Attrib[index] = ac->Fallback.Attrib[index];
191
192 ac->IsCached.Attrib[index] = GL_FALSE;
193 ac->NewArrayState &= ~_NEW_ARRAY_ATTRIB(index);
194 }
195
196
197 /*
198 * Generic import function for color data
199 */
200 static void import( GLcontext *ctx,
201 GLenum type,
202 struct gl_client_array *to,
203 struct gl_client_array *from )
204 {
205 GLubyte *dest;
206 const GLubyte *src;
207 ACcontext *ac = AC_CONTEXT(ctx);
208
209 if (type == 0)
210 type = from->Type;
211
212 /* The dest and source data addresses are the sum of the buffer
213 * object's start plus the vertex array pointer/offset.
214 */
215 dest = ADD_POINTERS(to->BufferObj->Data, to->Ptr);
216 src = ADD_POINTERS(from->BufferObj->Data, from->Ptr);
217
218 switch (type) {
219 case GL_FLOAT:
220 _math_trans_4fc( (GLfloat (*)[4]) dest,
221 src,
222 from->StrideB,
223 from->Type,
224 from->Size,
225 0,
226 ac->count - ac->start);
227
228 to->StrideB = 4 * sizeof(GLfloat);
229 to->Type = GL_FLOAT;
230 break;
231
232 case GL_UNSIGNED_BYTE:
233 _math_trans_4ub( (GLubyte (*)[4]) dest,
234 src,
235 from->StrideB,
236 from->Type,
237 from->Size,
238 0,
239 ac->count - ac->start);
240
241 to->StrideB = 4 * sizeof(GLubyte);
242 to->Type = GL_UNSIGNED_BYTE;
243 break;
244
245 case GL_UNSIGNED_SHORT:
246 _math_trans_4us( (GLushort (*)[4]) dest,
247 src,
248 from->StrideB,
249 from->Type,
250 from->Size,
251 0,
252 ac->count - ac->start);
253
254 to->StrideB = 4 * sizeof(GLushort);
255 to->Type = GL_UNSIGNED_SHORT;
256 break;
257
258 default:
259 ASSERT(0);
260 break;
261 }
262 }
263
264
265
266 /*
267 * Functions to import array ranges with specified types and strides.
268 * For example, if the vertex data is GLshort[2] and we want GLfloat[3]
269 * we'll use an import function to do the data conversion.
270 */
271
272 static void import_texcoord( GLcontext *ctx, GLuint unit,
273 GLenum type, GLuint stride )
274 {
275 ACcontext *ac = AC_CONTEXT(ctx);
276 struct gl_client_array *from = &ac->Raw.TexCoord[unit];
277 struct gl_client_array *to = &ac->Cache.TexCoord[unit];
278
279 ASSERT(unit < ctx->Const.MaxTextureCoordUnits);
280
281 /* Limited choices at this stage:
282 */
283 ASSERT(type == GL_FLOAT);
284 ASSERT(stride == 4*sizeof(GLfloat) || stride == 0);
285 ASSERT(ac->count - ac->start < ctx->Const.MaxArrayLockSize);
286
287 _math_trans_4f( (GLfloat (*)[4]) to->Ptr,
288 from->Ptr,
289 from->StrideB,
290 from->Type,
291 from->Size,
292 0,
293 ac->count - ac->start);
294
295 to->Size = from->Size;
296 to->StrideB = 4 * sizeof(GLfloat);
297 to->Type = GL_FLOAT;
298 ac->IsCached.TexCoord[unit] = GL_TRUE;
299 }
300
301 static void import_vertex( GLcontext *ctx,
302 GLenum type, GLuint stride )
303 {
304 ACcontext *ac = AC_CONTEXT(ctx);
305 struct gl_client_array *from = &ac->Raw.Vertex;
306 struct gl_client_array *to = &ac->Cache.Vertex;
307
308 /* Limited choices at this stage:
309 */
310 ASSERT(type == GL_FLOAT);
311 ASSERT(stride == 4*sizeof(GLfloat) || stride == 0);
312
313 _math_trans_4f( (GLfloat (*)[4]) to->Ptr,
314 from->Ptr,
315 from->StrideB,
316 from->Type,
317 from->Size,
318 0,
319 ac->count - ac->start);
320
321 to->Size = from->Size;
322 to->StrideB = 4 * sizeof(GLfloat);
323 to->Type = GL_FLOAT;
324 ac->IsCached.Vertex = GL_TRUE;
325 }
326
327 static void import_normal( GLcontext *ctx,
328 GLenum type, GLuint stride )
329 {
330 ACcontext *ac = AC_CONTEXT(ctx);
331 struct gl_client_array *from = &ac->Raw.Normal;
332 struct gl_client_array *to = &ac->Cache.Normal;
333
334 /* Limited choices at this stage:
335 */
336 ASSERT(type == GL_FLOAT);
337 ASSERT(stride == 3*sizeof(GLfloat) || stride == 0);
338
339 _math_trans_3f( (GLfloat (*)[3]) to->Ptr,
340 from->Ptr,
341 from->StrideB,
342 from->Type,
343 0,
344 ac->count - ac->start);
345
346 to->StrideB = 3 * sizeof(GLfloat);
347 to->Type = GL_FLOAT;
348 ac->IsCached.Normal = GL_TRUE;
349 }
350
351 static void import_color( GLcontext *ctx,
352 GLenum type, GLuint stride )
353 {
354 ACcontext *ac = AC_CONTEXT(ctx);
355 struct gl_client_array *from = &ac->Raw.Color;
356 struct gl_client_array *to = &ac->Cache.Color;
357
358 import( ctx, type, to, from );
359
360 ac->IsCached.Color = GL_TRUE;
361 }
362
363 static void import_index( GLcontext *ctx,
364 GLenum type, GLuint stride )
365 {
366 ACcontext *ac = AC_CONTEXT(ctx);
367 struct gl_client_array *from = &ac->Raw.Index;
368 struct gl_client_array *to = &ac->Cache.Index;
369
370 /* Limited choices at this stage:
371 */
372 ASSERT(type == GL_UNSIGNED_INT);
373 ASSERT(stride == sizeof(GLuint) || stride == 0);
374
375 _math_trans_1ui( (GLuint *) to->Ptr,
376 from->Ptr,
377 from->StrideB,
378 from->Type,
379 0,
380 ac->count - ac->start);
381
382 to->StrideB = sizeof(GLuint);
383 to->Type = GL_UNSIGNED_INT;
384 ac->IsCached.Index = GL_TRUE;
385 }
386
387 static void import_secondarycolor( GLcontext *ctx,
388 GLenum type, GLuint stride )
389 {
390 ACcontext *ac = AC_CONTEXT(ctx);
391 struct gl_client_array *from = &ac->Raw.SecondaryColor;
392 struct gl_client_array *to = &ac->Cache.SecondaryColor;
393
394 import( ctx, type, to, from );
395
396 ac->IsCached.SecondaryColor = GL_TRUE;
397 }
398
399 static void import_fogcoord( GLcontext *ctx,
400 GLenum type, GLuint stride )
401 {
402 ACcontext *ac = AC_CONTEXT(ctx);
403 struct gl_client_array *from = &ac->Raw.FogCoord;
404 struct gl_client_array *to = &ac->Cache.FogCoord;
405
406 /* Limited choices at this stage:
407 */
408 ASSERT(type == GL_FLOAT);
409 ASSERT(stride == sizeof(GLfloat) || stride == 0);
410
411 _math_trans_1f( (GLfloat *) to->Ptr,
412 from->Ptr,
413 from->StrideB,
414 from->Type,
415 0,
416 ac->count - ac->start);
417
418 to->StrideB = sizeof(GLfloat);
419 to->Type = GL_FLOAT;
420 ac->IsCached.FogCoord = GL_TRUE;
421 }
422
423 static void import_edgeflag( GLcontext *ctx,
424 GLenum type, GLuint stride )
425 {
426 ACcontext *ac = AC_CONTEXT(ctx);
427 struct gl_client_array *from = &ac->Raw.EdgeFlag;
428 struct gl_client_array *to = &ac->Cache.EdgeFlag;
429
430 /* Limited choices at this stage:
431 */
432 ASSERT(type == GL_UNSIGNED_BYTE);
433 ASSERT(stride == sizeof(GLubyte) || stride == 0);
434
435 _math_trans_1ub( (GLubyte *) to->Ptr,
436 from->Ptr,
437 from->StrideB,
438 from->Type,
439 0,
440 ac->count - ac->start);
441
442 to->StrideB = sizeof(GLubyte);
443 to->Type = GL_UNSIGNED_BYTE;
444 ac->IsCached.EdgeFlag = GL_TRUE;
445 }
446
447 static void import_attrib( GLcontext *ctx, GLuint index,
448 GLenum type, GLuint stride )
449 {
450 ACcontext *ac = AC_CONTEXT(ctx);
451 struct gl_client_array *from = &ac->Raw.Attrib[index];
452 struct gl_client_array *to = &ac->Cache.Attrib[index];
453
454 ASSERT(index < VERT_ATTRIB_MAX);
455
456 /* Limited choices at this stage:
457 */
458 ASSERT(type == GL_FLOAT);
459 ASSERT(stride == 4*sizeof(GLfloat) || stride == 0);
460 ASSERT(ac->count - ac->start < ctx->Const.MaxArrayLockSize);
461
462 _math_trans_4f( (GLfloat (*)[4]) to->Ptr,
463 from->Ptr,
464 from->StrideB,
465 from->Type,
466 from->Size,
467 0,
468 ac->count - ac->start);
469
470 to->Size = from->Size;
471 to->StrideB = 4 * sizeof(GLfloat);
472 to->Type = GL_FLOAT;
473 ac->IsCached.Attrib[index] = GL_TRUE;
474 }
475
476
477
478 /*
479 * Externals to request arrays with specific properties:
480 */
481
482
483 struct gl_client_array *_ac_import_texcoord( GLcontext *ctx,
484 GLuint unit,
485 GLenum type,
486 GLuint reqstride,
487 GLuint reqsize,
488 GLboolean reqwriteable,
489 GLboolean *writeable )
490 {
491 ACcontext *ac = AC_CONTEXT(ctx);
492
493 ASSERT(unit < ctx->Const.MaxTextureCoordUnits);
494
495 /* Can we keep the existing version?
496 */
497 if (ac->NewArrayState & _NEW_ARRAY_TEXCOORD(unit))
498 reset_texcoord( ctx, unit );
499
500 /* Is the request impossible?
501 */
502 if (reqsize != 0 && ac->Raw.TexCoord[unit].Size > (GLint) reqsize)
503 return 0;
504
505 /* Do we need to pull in a copy of the client data:
506 */
507 if (ac->Raw.TexCoord[unit].Type != type ||
508 (reqstride != 0 && ac->Raw.TexCoord[unit].StrideB != (GLint)reqstride) ||
509 reqwriteable)
510 {
511 if (!ac->IsCached.TexCoord[unit])
512 import_texcoord(ctx, unit, type, reqstride );
513 *writeable = GL_TRUE;
514 return &ac->Cache.TexCoord[unit];
515 }
516 else {
517 *writeable = GL_FALSE;
518 return &ac->Raw.TexCoord[unit];
519 }
520 }
521
522 struct gl_client_array *_ac_import_vertex( GLcontext *ctx,
523 GLenum type,
524 GLuint reqstride,
525 GLuint reqsize,
526 GLboolean reqwriteable,
527 GLboolean *writeable )
528 {
529 ACcontext *ac = AC_CONTEXT(ctx);
530
531 /* Can we keep the existing version?
532 */
533 if (ac->NewArrayState & _NEW_ARRAY_VERTEX)
534 reset_vertex( ctx );
535
536 /* Is the request impossible?
537 */
538 if (reqsize != 0 && ac->Raw.Vertex.Size > (GLint) reqsize)
539 return 0;
540
541 /* Do we need to pull in a copy of the client data:
542 */
543 if (ac->Raw.Vertex.Type != type ||
544 (reqstride != 0 && ac->Raw.Vertex.StrideB != (GLint) reqstride) ||
545 reqwriteable)
546 {
547 if (!ac->IsCached.Vertex)
548 import_vertex(ctx, type, reqstride );
549 *writeable = GL_TRUE;
550 return &ac->Cache.Vertex;
551 }
552 else {
553 *writeable = GL_FALSE;
554 return &ac->Raw.Vertex;
555 }
556 }
557
558 struct gl_client_array *_ac_import_normal( GLcontext *ctx,
559 GLenum type,
560 GLuint reqstride,
561 GLboolean reqwriteable,
562 GLboolean *writeable )
563 {
564 ACcontext *ac = AC_CONTEXT(ctx);
565
566 /* Can we keep the existing version?
567 */
568 if (ac->NewArrayState & _NEW_ARRAY_NORMAL)
569 reset_normal( ctx );
570
571 /* Do we need to pull in a copy of the client data:
572 */
573 if (ac->Raw.Normal.Type != type ||
574 (reqstride != 0 && ac->Raw.Normal.StrideB != (GLint) reqstride) ||
575 reqwriteable)
576 {
577 if (!ac->IsCached.Normal)
578 import_normal(ctx, type, reqstride );
579 *writeable = GL_TRUE;
580 return &ac->Cache.Normal;
581 }
582 else {
583 *writeable = GL_FALSE;
584 return &ac->Raw.Normal;
585 }
586 }
587
588 struct gl_client_array *_ac_import_color( GLcontext *ctx,
589 GLenum type,
590 GLuint reqstride,
591 GLuint reqsize,
592 GLboolean reqwriteable,
593 GLboolean *writeable )
594 {
595 ACcontext *ac = AC_CONTEXT(ctx);
596
597 /* Can we keep the existing version?
598 */
599 if (ac->NewArrayState & _NEW_ARRAY_COLOR0)
600 reset_color( ctx );
601
602 /* Is the request impossible?
603 */
604 if (reqsize != 0 && ac->Raw.Color.Size > (GLint) reqsize) {
605 return 0;
606 }
607
608 /* Do we need to pull in a copy of the client data:
609 */
610 if ((type != 0 && ac->Raw.Color.Type != type) ||
611 (reqstride != 0 && ac->Raw.Color.StrideB != (GLint) reqstride) ||
612 reqwriteable)
613 {
614 if (!ac->IsCached.Color)
615 import_color(ctx, type, reqstride );
616 *writeable = GL_TRUE;
617 return &ac->Cache.Color;
618 }
619 else {
620 *writeable = GL_FALSE;
621 return &ac->Raw.Color;
622 }
623 }
624
625 struct gl_client_array *_ac_import_index( GLcontext *ctx,
626 GLenum type,
627 GLuint reqstride,
628 GLboolean reqwriteable,
629 GLboolean *writeable )
630 {
631 ACcontext *ac = AC_CONTEXT(ctx);
632
633 /* Can we keep the existing version?
634 */
635 if (ac->NewArrayState & _NEW_ARRAY_INDEX)
636 reset_index( ctx );
637
638
639 /* Do we need to pull in a copy of the client data:
640 */
641 if (ac->Raw.Index.Type != type ||
642 (reqstride != 0 && ac->Raw.Index.StrideB != (GLint) reqstride) ||
643 reqwriteable)
644 {
645 if (!ac->IsCached.Index)
646 import_index(ctx, type, reqstride );
647 *writeable = GL_TRUE;
648 return &ac->Cache.Index;
649 }
650 else {
651 *writeable = GL_FALSE;
652 return &ac->Raw.Index;
653 }
654 }
655
656 struct gl_client_array *_ac_import_secondarycolor( GLcontext *ctx,
657 GLenum type,
658 GLuint reqstride,
659 GLuint reqsize,
660 GLboolean reqwriteable,
661 GLboolean *writeable )
662 {
663 ACcontext *ac = AC_CONTEXT(ctx);
664
665 /* Can we keep the existing version?
666 */
667 if (ac->NewArrayState & _NEW_ARRAY_COLOR1)
668 reset_secondarycolor( ctx );
669
670 /* Is the request impossible?
671 */
672 if (reqsize != 0 && ac->Raw.SecondaryColor.Size > (GLint) reqsize)
673 return 0;
674
675 /* Do we need to pull in a copy of the client data:
676 */
677 if ((type != 0 && ac->Raw.SecondaryColor.Type != type) ||
678 (reqstride != 0 && ac->Raw.SecondaryColor.StrideB != (GLint)reqstride) ||
679 reqwriteable)
680 {
681 if (!ac->IsCached.SecondaryColor)
682 import_secondarycolor(ctx, type, reqstride );
683 *writeable = GL_TRUE;
684 return &ac->Cache.SecondaryColor;
685 }
686 else {
687 *writeable = GL_FALSE;
688 return &ac->Raw.SecondaryColor;
689 }
690 }
691
692 struct gl_client_array *_ac_import_fogcoord( GLcontext *ctx,
693 GLenum type,
694 GLuint reqstride,
695 GLboolean reqwriteable,
696 GLboolean *writeable )
697 {
698 ACcontext *ac = AC_CONTEXT(ctx);
699
700 /* Can we keep the existing version?
701 */
702 if (ac->NewArrayState & _NEW_ARRAY_FOGCOORD)
703 reset_fogcoord( ctx );
704
705 /* Do we need to pull in a copy of the client data:
706 */
707 if (ac->Raw.FogCoord.Type != type ||
708 (reqstride != 0 && ac->Raw.FogCoord.StrideB != (GLint) reqstride) ||
709 reqwriteable)
710 {
711 if (!ac->IsCached.FogCoord)
712 import_fogcoord(ctx, type, reqstride );
713 *writeable = GL_TRUE;
714 return &ac->Cache.FogCoord;
715 }
716 else {
717 *writeable = GL_FALSE;
718 return &ac->Raw.FogCoord;
719 }
720 }
721
722 struct gl_client_array *_ac_import_edgeflag( GLcontext *ctx,
723 GLenum type,
724 GLuint reqstride,
725 GLboolean reqwriteable,
726 GLboolean *writeable )
727 {
728 ACcontext *ac = AC_CONTEXT(ctx);
729
730 /* Can we keep the existing version?
731 */
732 if (ac->NewArrayState & _NEW_ARRAY_EDGEFLAG)
733 reset_edgeflag( ctx );
734
735 /* Do we need to pull in a copy of the client data:
736 */
737 if (ac->Raw.EdgeFlag.Type != type ||
738 (reqstride != 0 && ac->Raw.EdgeFlag.StrideB != (GLint) reqstride) ||
739 reqwriteable)
740 {
741 if (!ac->IsCached.EdgeFlag)
742 import_edgeflag(ctx, type, reqstride );
743 *writeable = GL_TRUE;
744 return &ac->Cache.EdgeFlag;
745 }
746 else {
747 *writeable = GL_FALSE;
748 return &ac->Raw.EdgeFlag;
749 }
750 }
751
752 /* GL_NV_vertex_program */
753 struct gl_client_array *_ac_import_attrib( GLcontext *ctx,
754 GLuint index,
755 GLenum type,
756 GLuint reqstride,
757 GLuint reqsize,
758 GLboolean reqwriteable,
759 GLboolean *writeable )
760 {
761 ACcontext *ac = AC_CONTEXT(ctx);
762
763 ASSERT(index < VERT_ATTRIB_MAX);
764
765 /* Can we keep the existing version?
766 */
767 if (ac->NewArrayState & _NEW_ARRAY_ATTRIB(index))
768 reset_attrib( ctx, index );
769
770 /* Is the request impossible?
771 */
772 if (reqsize != 0 && ac->Raw.Attrib[index].Size > (GLint) reqsize)
773 return NULL;
774
775 /* Do we need to pull in a copy of the client data:
776 */
777 if (ac->Raw.Attrib[index].Type != type ||
778 (reqstride != 0 && ac->Raw.Attrib[index].StrideB != (GLint)reqstride) ||
779 reqwriteable)
780 {
781 if (!ac->IsCached.Attrib[index])
782 import_attrib(ctx, index, type, reqstride );
783 *writeable = GL_TRUE;
784 return &ac->Cache.Attrib[index];
785 }
786 else {
787 *writeable = GL_FALSE;
788 return &ac->Raw.Attrib[index];
789 }
790 }
791
792
793 /* Clients must call this function to validate state and set bounds
794 * before importing any data:
795 */
796 void _ac_import_range( GLcontext *ctx, GLuint start, GLuint count )
797 {
798 ACcontext *ac = AC_CONTEXT(ctx);
799
800 if (!ctx->Array.LockCount) {
801 /* Not locked, discard cached data. Changes to lock
802 * status are caught via. _ac_invalidate_state().
803 */
804 ac->NewArrayState = _NEW_ARRAY_ALL;
805 ac->start = start;
806 ac->count = count;
807 }
808 else {
809 /* Locked, discard data for any disabled arrays. Require that
810 * the whole locked range always be dealt with, otherwise hard to
811 * maintain cached data in the face of clipping.
812 */
813 ac->NewArrayState |= ~ctx->Array._Enabled;
814 ac->start = ctx->Array.LockFirst;
815 ac->count = ctx->Array.LockCount;
816 ASSERT(ac->start == start); /* hmm? */
817 ASSERT(ac->count == count);
818 }
819 }
820
821
822
823 /* Additional convienence function for importing the element list
824 * for glDrawElements() and glDrawRangeElements().
825 */
826 CONST void *
827 _ac_import_elements( GLcontext *ctx,
828 GLenum new_type,
829 GLuint count,
830 GLenum old_type,
831 CONST void *indices )
832 {
833 ACcontext *ac = AC_CONTEXT(ctx);
834
835 if (old_type == new_type)
836 return indices;
837
838 if (ac->elt_size < count * sizeof(GLuint)) {
839 if (ac->Elts) FREE(ac->Elts);
840 while (ac->elt_size < count * sizeof(GLuint))
841 ac->elt_size *= 2;
842 ac->Elts = (GLuint *) MALLOC(ac->elt_size);
843 }
844
845 switch (new_type) {
846 case GL_UNSIGNED_BYTE:
847 ASSERT(0);
848 return 0;
849 case GL_UNSIGNED_SHORT:
850 ASSERT(0);
851 return 0;
852 case GL_UNSIGNED_INT: {
853 GLuint *out = (GLuint *)ac->Elts;
854 GLuint i;
855
856 switch (old_type) {
857 case GL_UNSIGNED_BYTE: {
858 CONST GLubyte *in = (CONST GLubyte *)indices;
859 for (i = 0 ; i < count ; i++)
860 out[i] = in[i];
861 break;
862 }
863 case GL_UNSIGNED_SHORT: {
864 CONST GLushort *in = (CONST GLushort *)indices;
865 for (i = 0 ; i < count ; i++)
866 out[i] = in[i];
867 break;
868 }
869 default:
870 ASSERT(0);
871 }
872
873 return (CONST void *)out;
874 }
875 default:
876 ASSERT(0);
877 break;
878 }
879
880 return 0;
881 }