1 /* $Id: ac_import.c,v 1.8 2001/03/07 05:06:12 brianp 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 = (char *) (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
][3] != 1.0)
63 ac
->Raw
.TexCoord
[unit
].Size
= 4;
64 else if (ctx
->Current
.Texcoord
[unit
][2] != 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( (GLfloat (*)[4]) 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( (GLfloat (*)[4]) 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( (GLfloat (*)[3]) 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 _math_trans_4chan( (GLchan (*)[4]) to
->Ptr
,
279 ac
->count
- ac
->start
);
281 to
->Size
= from
->Size
;
282 to
->StrideB
= 4 * sizeof(GLchan
);
283 to
->Type
= CHAN_TYPE
;
284 ac
->IsCached
.Color
= GL_TRUE
;
287 static void import_index( GLcontext
*ctx
,
288 GLenum type
, GLuint stride
)
290 ACcontext
*ac
= AC_CONTEXT(ctx
);
291 struct gl_client_array
*from
= &ac
->Raw
.Index
;
292 struct gl_client_array
*to
= &ac
->Cache
.Index
;
294 /* Limited choices at this stage:
296 ASSERT(type
== GL_UNSIGNED_INT
);
297 ASSERT(stride
== sizeof(GLuint
) || stride
== 0);
299 _math_trans_1ui( (GLuint
*) to
->Ptr
,
304 ac
->count
- ac
->start
);
306 to
->StrideB
= sizeof(GLuint
);
307 to
->Type
= GL_UNSIGNED_INT
;
308 ac
->IsCached
.Index
= GL_TRUE
;
311 static void import_secondarycolor( GLcontext
*ctx
,
312 GLenum type
, GLuint stride
)
314 ACcontext
*ac
= AC_CONTEXT(ctx
);
315 struct gl_client_array
*from
= &ac
->Raw
.SecondaryColor
;
316 struct gl_client_array
*to
= &ac
->Cache
.SecondaryColor
;
318 /* Limited choices at this stage:
320 ASSERT(type
== CHAN_TYPE
);
321 ASSERT(stride
== 4 * sizeof(GLchan
) || stride
== 0);
323 _math_trans_4chan( (GLchan (*)[4]) to
->Ptr
,
329 ac
->count
- ac
->start
);
331 to
->StrideB
= 4 * sizeof(GLchan
);
332 to
->Type
= CHAN_TYPE
;
333 ac
->IsCached
.SecondaryColor
= GL_TRUE
;
336 static void import_fogcoord( GLcontext
*ctx
,
337 GLenum type
, GLuint stride
)
339 ACcontext
*ac
= AC_CONTEXT(ctx
);
340 struct gl_client_array
*from
= &ac
->Raw
.FogCoord
;
341 struct gl_client_array
*to
= &ac
->Cache
.FogCoord
;
343 /* Limited choices at this stage:
345 ASSERT(type
== GL_FLOAT
);
346 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
348 _math_trans_1f( (GLfloat
*) to
->Ptr
,
353 ac
->count
- ac
->start
);
355 to
->StrideB
= sizeof(GLfloat
);
357 ac
->IsCached
.FogCoord
= GL_TRUE
;
360 static void import_edgeflag( GLcontext
*ctx
,
361 GLenum type
, GLuint stride
)
363 ACcontext
*ac
= AC_CONTEXT(ctx
);
364 struct gl_client_array
*from
= &ac
->Raw
.EdgeFlag
;
365 struct gl_client_array
*to
= &ac
->Cache
.EdgeFlag
;
367 /* Limited choices at this stage:
369 ASSERT(type
== GL_FLOAT
);
370 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
372 _math_trans_1f( (GLfloat
*) to
->Ptr
,
377 ac
->count
- ac
->start
);
379 to
->StrideB
= sizeof(GLfloat
);
381 ac
->IsCached
.EdgeFlag
= GL_TRUE
;
386 /* Externals to request arrays with specific properties:
388 struct gl_client_array
*_ac_import_texcoord( GLcontext
*ctx
,
393 GLboolean reqwriteable
,
394 GLboolean
*writeable
)
396 ACcontext
*ac
= AC_CONTEXT(ctx
);
398 /* Can we keep the existing version?
400 if (ac
->NewArrayState
& _NEW_ARRAY_TEXCOORD(unit
))
401 reset_texcoord( ctx
, unit
);
403 /* Is the request impossible?
405 if (reqsize
!= 0 && ac
->Raw
.TexCoord
[unit
].Size
> (GLint
) reqsize
)
408 /* Do we need to pull in a copy of the client data:
410 if (ac
->Raw
.TexCoord
[unit
].Type
!= type
||
411 (reqstride
!= 0 && ac
->Raw
.TexCoord
[unit
].StrideB
!= (GLint
) reqstride
) ||
414 if (!ac
->IsCached
.TexCoord
[unit
])
415 import_texcoord(ctx
, unit
, type
, reqstride
);
416 *writeable
= GL_TRUE
;
417 return &ac
->Cache
.TexCoord
[unit
];
420 *writeable
= GL_FALSE
;
421 return &ac
->Raw
.TexCoord
[unit
];
425 struct gl_client_array
*_ac_import_vertex( 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_VERTEX
)
439 /* Is the request impossible?
441 if (reqsize
!= 0 && ac
->Raw
.Vertex
.Size
> (GLint
) reqsize
)
444 /* Do we need to pull in a copy of the client data:
446 if (ac
->Raw
.Vertex
.Type
!= type
||
447 (reqstride
!= 0 && ac
->Raw
.Vertex
.StrideB
!= (GLint
) reqstride
) ||
450 if (!ac
->IsCached
.Vertex
)
451 import_vertex(ctx
, type
, reqstride
);
452 *writeable
= GL_TRUE
;
453 return &ac
->Cache
.Vertex
;
456 *writeable
= GL_FALSE
;
457 return &ac
->Raw
.Vertex
;
461 struct gl_client_array
*_ac_import_normal( GLcontext
*ctx
,
464 GLboolean reqwriteable
,
465 GLboolean
*writeable
)
467 ACcontext
*ac
= AC_CONTEXT(ctx
);
469 /* Can we keep the existing version?
471 if (ac
->NewArrayState
& _NEW_ARRAY_NORMAL
)
474 /* Do we need to pull in a copy of the client data:
476 if (ac
->Raw
.Normal
.Type
!= type
||
477 (reqstride
!= 0 && ac
->Raw
.Normal
.StrideB
!= (GLint
) reqstride
) ||
480 if (!ac
->IsCached
.Normal
)
481 import_normal(ctx
, type
, reqstride
);
482 *writeable
= GL_TRUE
;
483 return &ac
->Cache
.Normal
;
486 *writeable
= GL_FALSE
;
487 return &ac
->Raw
.Normal
;
491 struct gl_client_array
*_ac_import_color( GLcontext
*ctx
,
495 GLboolean reqwriteable
,
496 GLboolean
*writeable
)
498 ACcontext
*ac
= AC_CONTEXT(ctx
);
500 /* Can we keep the existing version?
502 if (ac
->NewArrayState
& _NEW_ARRAY_COLOR
)
505 /* Is the request impossible?
507 if (reqsize
!= 0 && ac
->Raw
.Color
.Size
> (GLint
) reqsize
) {
511 /* Do we need to pull in a copy of the client data:
513 if (ac
->Raw
.Color
.Type
!= type
||
514 (reqstride
!= 0 && ac
->Raw
.Color
.StrideB
!= (GLint
) reqstride
) ||
517 if (!ac
->IsCached
.Color
)
518 import_color(ctx
, type
, reqstride
);
519 *writeable
= GL_TRUE
;
520 return &ac
->Cache
.Color
;
523 *writeable
= GL_FALSE
;
524 return &ac
->Raw
.Color
;
528 struct gl_client_array
*_ac_import_index( 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_INDEX
)
542 /* Do we need to pull in a copy of the client data:
544 if (ac
->Raw
.Index
.Type
!= type
||
545 (reqstride
!= 0 && ac
->Raw
.Index
.StrideB
!= (GLint
) reqstride
) ||
548 if (!ac
->IsCached
.Index
)
549 import_index(ctx
, type
, reqstride
);
550 *writeable
= GL_TRUE
;
551 return &ac
->Cache
.Index
;
554 *writeable
= GL_FALSE
;
555 return &ac
->Raw
.Index
;
559 struct gl_client_array
*_ac_import_secondarycolor( GLcontext
*ctx
,
563 GLboolean reqwriteable
,
564 GLboolean
*writeable
)
566 ACcontext
*ac
= AC_CONTEXT(ctx
);
568 /* Can we keep the existing version?
570 if (ac
->NewArrayState
& _NEW_ARRAY_SECONDARYCOLOR
)
571 reset_secondarycolor( ctx
);
573 /* Is the request impossible?
575 if (reqsize
!= 0 && ac
->Raw
.SecondaryColor
.Size
> (GLint
) reqsize
)
578 /* Do we need to pull in a copy of the client data:
580 if (ac
->Raw
.SecondaryColor
.Type
!= type
||
581 (reqstride
!= 0 && ac
->Raw
.SecondaryColor
.StrideB
!= (GLint
) reqstride
) ||
584 if (!ac
->IsCached
.SecondaryColor
)
585 import_secondarycolor(ctx
, type
, reqstride
);
586 *writeable
= GL_TRUE
;
587 return &ac
->Cache
.SecondaryColor
;
590 *writeable
= GL_FALSE
;
591 return &ac
->Raw
.SecondaryColor
;
595 struct gl_client_array
*_ac_import_fogcoord( GLcontext
*ctx
,
598 GLboolean reqwriteable
,
599 GLboolean
*writeable
)
601 ACcontext
*ac
= AC_CONTEXT(ctx
);
603 /* Can we keep the existing version?
605 if (ac
->NewArrayState
& _NEW_ARRAY_FOGCOORD
)
606 reset_fogcoord( ctx
);
608 /* Do we need to pull in a copy of the client data:
610 if (ac
->Raw
.FogCoord
.Type
!= type
||
611 (reqstride
!= 0 && ac
->Raw
.FogCoord
.StrideB
!= (GLint
) reqstride
) ||
614 if (!ac
->IsCached
.FogCoord
)
615 import_fogcoord(ctx
, type
, reqstride
);
616 *writeable
= GL_TRUE
;
617 return &ac
->Cache
.FogCoord
;
620 *writeable
= GL_FALSE
;
621 return &ac
->Raw
.FogCoord
;
628 struct gl_client_array
*_ac_import_edgeflag( GLcontext
*ctx
,
631 GLboolean reqwriteable
,
632 GLboolean
*writeable
)
634 ACcontext
*ac
= AC_CONTEXT(ctx
);
636 /* Can we keep the existing version?
638 if (ac
->NewArrayState
& _NEW_ARRAY_EDGEFLAG
)
639 reset_edgeflag( ctx
);
641 /* Do we need to pull in a copy of the client data:
643 if (ac
->Raw
.EdgeFlag
.Type
!= type
||
644 (reqstride
!= 0 && ac
->Raw
.EdgeFlag
.StrideB
!= (GLint
) reqstride
) ||
647 if (!ac
->IsCached
.EdgeFlag
)
648 import_edgeflag(ctx
, type
, reqstride
);
649 *writeable
= GL_TRUE
;
650 return &ac
->Cache
.EdgeFlag
;
653 *writeable
= GL_FALSE
;
654 return &ac
->Raw
.EdgeFlag
;
662 /* Clients must call this function to validate state and set bounds
663 * before importing any data:
665 void _ac_import_range( GLcontext
*ctx
, GLuint start
, GLuint count
)
667 ACcontext
*ac
= AC_CONTEXT(ctx
);
669 /* Discard cached data which has been invalidated by state changes
670 * since last time. **ALREADY DONE**
672 _ac_update_state( ctx );
675 if (!ctx
->Array
.LockCount
) {
676 /* Not locked, discard cached data. Changes to lock
677 * status are caught via. _ac_invalidate_state().
679 ac
->NewArrayState
= _NEW_ARRAY_ALL
;
684 /* Locked, discard data for any disabled arrays. Require that
685 * the whole locked range always be dealt with, otherwise hard to
686 * maintain cached data in the face of clipping.
688 ac
->NewArrayState
|= ~ctx
->Array
._Enabled
;
689 ac
->start
= ctx
->Array
.LockFirst
;
690 ac
->count
= ctx
->Array
.LockCount
;
691 ASSERT(ac
->start
== start
); /* hmm? */
692 ASSERT(ac
->count
== count
);
698 /* Additional convienence function for importing a the element list
699 * for drawelements, drawrangeelements:
702 _ac_import_elements( GLcontext
*ctx
,
706 CONST
void *indices
)
708 ACcontext
*ac
= AC_CONTEXT(ctx
);
710 if (old_type
== new_type
)
713 if (ac
->elt_size
< count
* sizeof(GLuint
)) {
714 if (ac
->Elts
) FREE(ac
->Elts
);
715 while (ac
->elt_size
< count
* sizeof(GLuint
))
717 ac
->Elts
= (GLuint
*) MALLOC(ac
->elt_size
);
721 case GL_UNSIGNED_BYTE
:
724 case GL_UNSIGNED_SHORT
:
727 case GL_UNSIGNED_INT
: {
728 GLuint
*out
= (GLuint
*)ac
->Elts
;
732 case GL_UNSIGNED_BYTE
: {
733 CONST GLubyte
*in
= (CONST GLubyte
*)indices
;
734 for (i
= 0 ; i
< count
; i
++)
738 case GL_UNSIGNED_SHORT
: {
739 CONST GLushort
*in
= (CONST GLushort
*)indices
;
740 for (i
= 0 ; i
< count
; i
++)
748 return (CONST
void *)out
;