1 /* $Id: ac_import.c,v 1.5 2001/02/04 00:47:28 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Keith Whitwell <keithw@valinux.com>
36 #include "math/m_translate.h"
37 #include "array_cache/ac_context.h"
38 #include "math/m_translate.h"
40 #define STRIDE_ARRAY( array, offset ) \
42 char *tmp = (array).Ptr; \
43 tmp += (offset) * (array).StrideB; \
47 /* Set the array pointer back to its source when the cached data is
51 static void reset_texcoord( GLcontext
*ctx
, GLuint unit
)
53 ACcontext
*ac
= AC_CONTEXT(ctx
);
55 if (ctx
->Array
._Enabled
& _NEW_ARRAY_TEXCOORD(unit
)) {
56 ac
->Raw
.TexCoord
[unit
] = ctx
->Array
.TexCoord
[unit
];
57 STRIDE_ARRAY(ac
->Raw
.TexCoord
[unit
], ac
->start
);
60 ac
->Raw
.TexCoord
[unit
] = ac
->Fallback
.TexCoord
[unit
];
62 if (ctx
->Current
.Texcoord
[unit
][4] != 1.0)
63 ac
->Raw
.TexCoord
[unit
].Size
= 4;
64 else if (ctx
->Current
.Texcoord
[unit
][3] != 0.0)
65 ac
->Raw
.TexCoord
[unit
].Size
= 3;
67 ac
->Raw
.TexCoord
[unit
].Size
= 2;
70 ac
->IsCached
.TexCoord
[unit
] = GL_FALSE
;
71 ac
->NewArrayState
&= ~_NEW_ARRAY_TEXCOORD(unit
);
74 static void reset_vertex( GLcontext
*ctx
)
76 ACcontext
*ac
= AC_CONTEXT(ctx
);
77 ASSERT(ctx
->Array
.Vertex
.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
;
85 static void reset_normal( GLcontext
*ctx
)
87 ACcontext
*ac
= AC_CONTEXT(ctx
);
89 if (ctx
->Array
._Enabled
& _NEW_ARRAY_NORMAL
) {
90 ac
->Raw
.Normal
= ctx
->Array
.Normal
;
91 STRIDE_ARRAY(ac
->Raw
.Normal
, ac
->start
);
94 ac
->Raw
.Normal
= ac
->Fallback
.Normal
;
97 ac
->IsCached
.Normal
= GL_FALSE
;
98 ac
->NewArrayState
&= ~_NEW_ARRAY_NORMAL
;
102 static void reset_color( GLcontext
*ctx
)
104 ACcontext
*ac
= AC_CONTEXT(ctx
);
107 if (ctx
->Array
._Enabled
& _NEW_ARRAY_COLOR
) {
108 ac
->Raw
.Color
= ctx
->Array
.Color
;
109 STRIDE_ARRAY(ac
->Raw
.Color
, ac
->start
);
112 ac
->Raw
.Color
= ac
->Fallback
.Color
;
114 ac
->IsCached
.Color
= GL_FALSE
;
115 ac
->NewArrayState
&= ~_NEW_ARRAY_COLOR
;
119 static void reset_secondarycolor( GLcontext
*ctx
)
121 ACcontext
*ac
= AC_CONTEXT(ctx
);
123 if (ctx
->Array
._Enabled
& _NEW_ARRAY_SECONDARYCOLOR
) {
124 ac
->Raw
.SecondaryColor
= ctx
->Array
.SecondaryColor
;
125 STRIDE_ARRAY(ac
->Raw
.SecondaryColor
, ac
->start
);
128 ac
->Raw
.SecondaryColor
= ac
->Fallback
.SecondaryColor
;
130 ac
->IsCached
.SecondaryColor
= GL_FALSE
;
131 ac
->NewArrayState
&= ~_NEW_ARRAY_SECONDARYCOLOR
;
135 static void reset_index( GLcontext
*ctx
)
137 ACcontext
*ac
= AC_CONTEXT(ctx
);
139 if (ctx
->Array
._Enabled
& _NEW_ARRAY_INDEX
) {
140 ac
->Raw
.Index
= ctx
->Array
.Index
;
141 STRIDE_ARRAY(ac
->Raw
.Index
, ac
->start
);
144 ac
->Raw
.Index
= ac
->Fallback
.Index
;
146 ac
->IsCached
.Index
= GL_FALSE
;
147 ac
->NewArrayState
&= ~_NEW_ARRAY_INDEX
;
150 static void reset_fogcoord( GLcontext
*ctx
)
152 ACcontext
*ac
= AC_CONTEXT(ctx
);
154 if (ctx
->Array
._Enabled
& _NEW_ARRAY_FOGCOORD
) {
155 ac
->Raw
.FogCoord
= ctx
->Array
.FogCoord
;
156 STRIDE_ARRAY(ac
->Raw
.FogCoord
, ac
->start
);
159 ac
->Raw
.FogCoord
= ac
->Fallback
.FogCoord
;
161 ac
->IsCached
.FogCoord
= GL_FALSE
;
162 ac
->NewArrayState
&= ~_NEW_ARRAY_FOGCOORD
;
165 static void reset_edgeflag( GLcontext
*ctx
)
167 ACcontext
*ac
= AC_CONTEXT(ctx
);
169 if (ctx
->Array
._Enabled
& _NEW_ARRAY_EDGEFLAG
) {
170 ac
->Raw
.EdgeFlag
= ctx
->Array
.EdgeFlag
;
171 STRIDE_ARRAY(ac
->Raw
.EdgeFlag
, ac
->start
);
174 ac
->Raw
.EdgeFlag
= ac
->Fallback
.EdgeFlag
;
176 ac
->IsCached
.EdgeFlag
= GL_FALSE
;
177 ac
->NewArrayState
&= ~_NEW_ARRAY_EDGEFLAG
;
181 /* Functions to import array ranges with specified types and strides.
183 static void import_texcoord( GLcontext
*ctx
, GLuint unit
,
184 GLenum type
, GLuint stride
)
186 ACcontext
*ac
= AC_CONTEXT(ctx
);
187 struct gl_client_array
*from
= &ac
->Raw
.TexCoord
[unit
];
188 struct gl_client_array
*to
= &ac
->Cache
.TexCoord
[unit
];
190 /* Limited choices at this stage:
192 ASSERT(type
== GL_FLOAT
);
193 ASSERT(stride
== 4*sizeof(GLfloat
) || stride
== 0);
194 ASSERT(ac
->count
- ac
->start
< ctx
->Const
.MaxArrayLockSize
);
196 _math_trans_4f( to
->Ptr
,
204 to
->Size
= from
->Size
;
205 to
->StrideB
= 4 * sizeof(GLfloat
);
207 ac
->IsCached
.TexCoord
[unit
] = GL_TRUE
;
210 static void import_vertex( GLcontext
*ctx
,
211 GLenum type
, GLuint stride
)
213 ACcontext
*ac
= AC_CONTEXT(ctx
);
214 struct gl_client_array
*from
= &ac
->Raw
.Vertex
;
215 struct gl_client_array
*to
= &ac
->Cache
.Vertex
;
217 /* Limited choices at this stage:
219 ASSERT(type
== GL_FLOAT
);
220 ASSERT(stride
== 4*sizeof(GLfloat
) || stride
== 0);
222 _math_trans_4f( to
->Ptr
,
228 ac
->count
- ac
->start
);
230 to
->Size
= from
->Size
;
231 to
->StrideB
= 4 * sizeof(GLfloat
);
233 ac
->IsCached
.Vertex
= GL_TRUE
;
236 static void import_normal( GLcontext
*ctx
,
237 GLenum type
, GLuint stride
)
239 ACcontext
*ac
= AC_CONTEXT(ctx
);
240 struct gl_client_array
*from
= &ac
->Raw
.Normal
;
241 struct gl_client_array
*to
= &ac
->Cache
.Normal
;
243 /* Limited choices at this stage:
245 ASSERT(type
== GL_FLOAT
);
246 ASSERT(stride
== 3*sizeof(GLfloat
) || stride
== 0);
248 _math_trans_3f( to
->Ptr
,
253 ac
->count
- ac
->start
);
255 to
->StrideB
= 3 * sizeof(GLfloat
);
257 ac
->IsCached
.Normal
= GL_TRUE
;
260 static void import_color( GLcontext
*ctx
,
261 GLenum type
, GLuint stride
)
263 ACcontext
*ac
= AC_CONTEXT(ctx
);
264 struct gl_client_array
*from
= &ac
->Raw
.Color
;
265 struct gl_client_array
*to
= &ac
->Cache
.Color
;
267 /* Limited choices at this stage:
269 /* XXX GLchan: is this right for GLchan? */
270 ASSERT(type
== CHAN_TYPE
);
271 ASSERT(stride
== 4 * sizeof(GLchan
) || stride
== 0);
273 #if CHAN_TYPE == GL_UNSIGNED_BYTE
274 _math_trans_4ub( to
->Ptr
,
280 ac
->count
- ac
->start
);
281 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
282 _math_trans_4us( to
->Ptr
,
288 ac
->count
- ac
->start
);
289 #elif CHAN_TYPE == GL_FLOAT
290 _math_trans_4f( to
->Ptr
,
296 ac
->count
- ac
->start
);
299 to
->Size
= from
->Size
;
300 to
->StrideB
= 4 * sizeof(GLchan
);
301 to
->Type
= CHAN_TYPE
;
302 ac
->IsCached
.Color
= GL_TRUE
;
305 static void import_index( GLcontext
*ctx
,
306 GLenum type
, GLuint stride
)
308 ACcontext
*ac
= AC_CONTEXT(ctx
);
309 struct gl_client_array
*from
= &ac
->Raw
.Index
;
310 struct gl_client_array
*to
= &ac
->Cache
.Index
;
312 /* Limited choices at this stage:
314 ASSERT(type
== GL_UNSIGNED_INT
);
315 ASSERT(stride
== sizeof(GLuint
) || stride
== 0);
317 _math_trans_1ui( to
->Ptr
,
322 ac
->count
- ac
->start
);
324 to
->StrideB
= sizeof(GLuint
);
325 to
->Type
= GL_UNSIGNED_INT
;
326 ac
->IsCached
.Index
= GL_TRUE
;
329 static void import_secondarycolor( GLcontext
*ctx
,
330 GLenum type
, GLuint stride
)
332 ACcontext
*ac
= AC_CONTEXT(ctx
);
333 struct gl_client_array
*from
= &ac
->Raw
.SecondaryColor
;
334 struct gl_client_array
*to
= &ac
->Cache
.SecondaryColor
;
336 /* Limited choices at this stage:
338 ASSERT(type
== CHAN_TYPE
);
339 ASSERT(stride
== 4 * sizeof(GLchan
) || stride
== 0);
341 #if CHAN_TYPE == GL_UNSIGNED_BYTE
342 _math_trans_4ub( to
->Ptr
,
348 ac
->count
- ac
->start
);
349 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
350 _math_trans_4us( to
->Ptr
,
356 ac
->count
- ac
->start
);
357 #elif CHAN_TYPE == GL_FLOAT
358 _math_trans_4f( to
->Ptr
,
364 ac
->count
- ac
->start
);
367 to
->StrideB
= 4 * sizeof(GLchan
);
368 to
->Type
= CHAN_TYPE
;
369 ac
->IsCached
.SecondaryColor
= GL_TRUE
;
372 static void import_fogcoord( GLcontext
*ctx
,
373 GLenum type
, GLuint stride
)
375 ACcontext
*ac
= AC_CONTEXT(ctx
);
376 struct gl_client_array
*from
= &ac
->Raw
.FogCoord
;
377 struct gl_client_array
*to
= &ac
->Cache
.FogCoord
;
379 /* Limited choices at this stage:
381 ASSERT(type
== GL_FLOAT
);
382 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
384 _math_trans_1f( to
->Ptr
,
389 ac
->count
- ac
->start
);
391 to
->StrideB
= sizeof(GLfloat
);
393 ac
->IsCached
.FogCoord
= GL_TRUE
;
396 static void import_edgeflag( GLcontext
*ctx
,
397 GLenum type
, GLuint stride
)
399 ACcontext
*ac
= AC_CONTEXT(ctx
);
400 struct gl_client_array
*from
= &ac
->Raw
.EdgeFlag
;
401 struct gl_client_array
*to
= &ac
->Cache
.EdgeFlag
;
403 /* Limited choices at this stage:
405 ASSERT(type
== GL_FLOAT
);
406 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
408 _math_trans_1f( to
->Ptr
,
413 ac
->count
- ac
->start
);
415 to
->StrideB
= sizeof(GLfloat
);
417 ac
->IsCached
.EdgeFlag
= GL_TRUE
;
422 /* Externals to request arrays with specific properties:
424 struct gl_client_array
*_ac_import_texcoord( GLcontext
*ctx
,
429 GLboolean reqwriteable
,
430 GLboolean
*writeable
)
432 ACcontext
*ac
= AC_CONTEXT(ctx
);
434 /* Can we keep the existing version?
436 if (ac
->NewArrayState
& _NEW_ARRAY_TEXCOORD(unit
))
437 reset_texcoord( ctx
, unit
);
439 /* Is the request impossible?
441 if (reqsize
!= 0 && ac
->Raw
.TexCoord
[unit
].Size
> reqsize
)
444 /* Do we need to pull in a copy of the client data:
446 if (ac
->Raw
.TexCoord
[unit
].Type
!= type
||
447 (reqstride
!= 0 && ac
->Raw
.TexCoord
[unit
].StrideB
!= reqstride
) ||
450 if (!ac
->IsCached
.TexCoord
[unit
])
451 import_texcoord(ctx
, unit
, type
, reqstride
);
452 *writeable
= GL_TRUE
;
453 return &ac
->Cache
.TexCoord
[unit
];
456 *writeable
= GL_FALSE
;
457 return &ac
->Raw
.TexCoord
[unit
];
461 struct gl_client_array
*_ac_import_vertex( GLcontext
*ctx
,
465 GLboolean reqwriteable
,
466 GLboolean
*writeable
)
468 ACcontext
*ac
= AC_CONTEXT(ctx
);
470 /* Can we keep the existing version?
472 if (ac
->NewArrayState
& _NEW_ARRAY_VERTEX
)
475 /* Is the request impossible?
477 if (reqsize
!= 0 && ac
->Raw
.Vertex
.Size
> reqsize
)
480 /* Do we need to pull in a copy of the client data:
482 if (ac
->Raw
.Vertex
.Type
!= type
||
483 (reqstride
!= 0 && ac
->Raw
.Vertex
.StrideB
!= reqstride
) ||
486 if (!ac
->IsCached
.Vertex
)
487 import_vertex(ctx
, type
, reqstride
);
488 *writeable
= GL_TRUE
;
489 return &ac
->Cache
.Vertex
;
492 *writeable
= GL_FALSE
;
493 return &ac
->Raw
.Vertex
;
497 struct gl_client_array
*_ac_import_normal( GLcontext
*ctx
,
500 GLboolean reqwriteable
,
501 GLboolean
*writeable
)
503 ACcontext
*ac
= AC_CONTEXT(ctx
);
505 /* Can we keep the existing version?
507 if (ac
->NewArrayState
& _NEW_ARRAY_NORMAL
)
510 /* Do we need to pull in a copy of the client data:
512 if (ac
->Raw
.Normal
.Type
!= type
||
513 (reqstride
!= 0 && ac
->Raw
.Normal
.StrideB
!= reqstride
) ||
516 if (!ac
->IsCached
.Normal
)
517 import_normal(ctx
, type
, reqstride
);
518 *writeable
= GL_TRUE
;
519 return &ac
->Cache
.Normal
;
522 *writeable
= GL_FALSE
;
523 return &ac
->Raw
.Normal
;
527 struct gl_client_array
*_ac_import_color( GLcontext
*ctx
,
531 GLboolean reqwriteable
,
532 GLboolean
*writeable
)
534 ACcontext
*ac
= AC_CONTEXT(ctx
);
536 /* Can we keep the existing version?
538 if (ac
->NewArrayState
& _NEW_ARRAY_COLOR
)
541 /* Is the request impossible?
543 if (reqsize
!= 0 && ac
->Raw
.Color
.Size
> reqsize
) {
547 /* Do we need to pull in a copy of the client data:
549 if (ac
->Raw
.Color
.Type
!= type
||
550 (reqstride
!= 0 && ac
->Raw
.Color
.StrideB
!= reqstride
) ||
553 if (!ac
->IsCached
.Color
)
554 import_color(ctx
, type
, reqstride
);
555 *writeable
= GL_TRUE
;
556 return &ac
->Cache
.Color
;
559 *writeable
= GL_FALSE
;
560 return &ac
->Raw
.Color
;
564 struct gl_client_array
*_ac_import_index( GLcontext
*ctx
,
567 GLboolean reqwriteable
,
568 GLboolean
*writeable
)
570 ACcontext
*ac
= AC_CONTEXT(ctx
);
572 /* Can we keep the existing version?
574 if (ac
->NewArrayState
& _NEW_ARRAY_INDEX
)
578 /* Do we need to pull in a copy of the client data:
580 if (ac
->Raw
.Index
.Type
!= type
||
581 (reqstride
!= 0 && ac
->Raw
.Index
.StrideB
!= reqstride
) ||
584 if (!ac
->IsCached
.Index
)
585 import_index(ctx
, type
, reqstride
);
586 *writeable
= GL_TRUE
;
587 return &ac
->Cache
.Index
;
590 *writeable
= GL_FALSE
;
591 return &ac
->Raw
.Index
;
595 struct gl_client_array
*_ac_import_secondarycolor( GLcontext
*ctx
,
599 GLboolean reqwriteable
,
600 GLboolean
*writeable
)
602 ACcontext
*ac
= AC_CONTEXT(ctx
);
604 /* Can we keep the existing version?
606 if (ac
->NewArrayState
& _NEW_ARRAY_SECONDARYCOLOR
)
607 reset_secondarycolor( ctx
);
609 /* Is the request impossible?
611 if (reqsize
!= 0 && ac
->Raw
.SecondaryColor
.Size
> reqsize
)
614 /* Do we need to pull in a copy of the client data:
616 if (ac
->Raw
.SecondaryColor
.Type
!= type
||
617 (reqstride
!= 0 && ac
->Raw
.SecondaryColor
.StrideB
!= reqstride
) ||
620 if (!ac
->IsCached
.SecondaryColor
)
621 import_secondarycolor(ctx
, type
, reqstride
);
622 *writeable
= GL_TRUE
;
623 return &ac
->Cache
.SecondaryColor
;
626 *writeable
= GL_FALSE
;
627 return &ac
->Raw
.SecondaryColor
;
631 struct gl_client_array
*_ac_import_fogcoord( GLcontext
*ctx
,
634 GLboolean reqwriteable
,
635 GLboolean
*writeable
)
637 ACcontext
*ac
= AC_CONTEXT(ctx
);
639 /* Can we keep the existing version?
641 if (ac
->NewArrayState
& _NEW_ARRAY_FOGCOORD
)
642 reset_fogcoord( ctx
);
644 /* Do we need to pull in a copy of the client data:
646 if (ac
->Raw
.FogCoord
.Type
!= type
||
647 (reqstride
!= 0 && ac
->Raw
.FogCoord
.StrideB
!= reqstride
) ||
650 if (!ac
->IsCached
.FogCoord
)
651 import_fogcoord(ctx
, type
, reqstride
);
652 *writeable
= GL_TRUE
;
653 return &ac
->Cache
.FogCoord
;
656 *writeable
= GL_FALSE
;
657 return &ac
->Raw
.FogCoord
;
664 struct gl_client_array
*_ac_import_edgeflag( GLcontext
*ctx
,
667 GLboolean reqwriteable
,
668 GLboolean
*writeable
)
670 ACcontext
*ac
= AC_CONTEXT(ctx
);
672 /* Can we keep the existing version?
674 if (ac
->NewArrayState
& _NEW_ARRAY_EDGEFLAG
)
675 reset_edgeflag( ctx
);
677 /* Do we need to pull in a copy of the client data:
679 if (ac
->Raw
.EdgeFlag
.Type
!= type
||
680 (reqstride
!= 0 && ac
->Raw
.EdgeFlag
.StrideB
!= reqstride
) ||
683 if (!ac
->IsCached
.EdgeFlag
)
684 import_edgeflag(ctx
, type
, reqstride
);
685 *writeable
= GL_TRUE
;
686 return &ac
->Cache
.EdgeFlag
;
689 *writeable
= GL_FALSE
;
690 return &ac
->Raw
.EdgeFlag
;
698 /* Clients must call this function to validate state and set bounds
699 * before importing any data:
701 void _ac_import_range( GLcontext
*ctx
, GLuint start
, GLuint count
)
703 ACcontext
*ac
= AC_CONTEXT(ctx
);
705 /* Discard cached data which has been invalidated by state changes
706 * since last time. **ALREADY DONE**
708 _ac_update_state( ctx );
711 if (!ctx
->Array
.LockCount
) {
712 /* Not locked, discard cached data. Changes to lock
713 * status are caught via. _ac_invalidate_state().
715 ac
->NewArrayState
= _NEW_ARRAY_ALL
;
720 /* Locked, discard data for any disabled arrays. Require that
721 * the whole locked range always be dealt with, otherwise hard to
722 * maintain cached data in the face of clipping.
724 ac
->NewArrayState
|= ~ctx
->Array
._Enabled
;
725 ac
->start
= ctx
->Array
.LockFirst
;
726 ac
->count
= ctx
->Array
.LockCount
;
727 ASSERT(ac
->start
== start
); /* hmm? */
728 ASSERT(ac
->count
== count
);
734 /* Additional convienence function for importing a the element list
735 * for drawelements, drawrangeelements:
738 _ac_import_elements( GLcontext
*ctx
,
742 CONST
void *indices
)
744 ACcontext
*ac
= AC_CONTEXT(ctx
);
746 if (old_type
== new_type
)
749 if (ac
->elt_size
< count
* sizeof(GLuint
)) {
750 if (ac
->Elts
) FREE(ac
->Elts
);
751 while (ac
->elt_size
< count
* sizeof(GLuint
))
753 ac
->Elts
= MALLOC(ac
->elt_size
);
757 case GL_UNSIGNED_BYTE
:
760 case GL_UNSIGNED_SHORT
:
763 case GL_UNSIGNED_INT
: {
764 GLuint
*out
= (GLuint
*)ac
->Elts
;
768 case GL_UNSIGNED_BYTE
: {
769 CONST GLubyte
*in
= (CONST GLubyte
*)indices
;
770 for (i
= 0 ; i
< count
; i
++)
774 case GL_UNSIGNED_SHORT
: {
775 CONST GLushort
*in
= (CONST GLushort
*)indices
;
776 for (i
= 0 ; i
< count
; i
++)
784 return (CONST
void *)out
;