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