1 /* $Id: ac_import.c,v 1.12 2001/04/17 20:37:44 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
,
202 ac
->count
- ac
->start
);
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 ASSERT(type
== CHAN_TYPE
);
270 ASSERT(stride
== 4 * sizeof(GLchan
) || stride
== 0);
272 _math_trans_4chan( (GLchan (*)[4]) to
->Ptr
,
278 ac
->count
- ac
->start
);
280 to
->Size
= from
->Size
;
281 to
->StrideB
= 4 * sizeof(GLchan
);
282 to
->Type
= CHAN_TYPE
;
283 ac
->IsCached
.Color
= GL_TRUE
;
286 static void import_index( GLcontext
*ctx
,
287 GLenum type
, GLuint stride
)
289 ACcontext
*ac
= AC_CONTEXT(ctx
);
290 struct gl_client_array
*from
= &ac
->Raw
.Index
;
291 struct gl_client_array
*to
= &ac
->Cache
.Index
;
293 /* Limited choices at this stage:
295 ASSERT(type
== GL_UNSIGNED_INT
);
296 ASSERT(stride
== sizeof(GLuint
) || stride
== 0);
298 _math_trans_1ui( (GLuint
*) to
->Ptr
,
303 ac
->count
- ac
->start
);
305 to
->StrideB
= sizeof(GLuint
);
306 to
->Type
= GL_UNSIGNED_INT
;
307 ac
->IsCached
.Index
= GL_TRUE
;
310 static void import_secondarycolor( GLcontext
*ctx
,
311 GLenum type
, GLuint stride
)
313 ACcontext
*ac
= AC_CONTEXT(ctx
);
314 struct gl_client_array
*from
= &ac
->Raw
.SecondaryColor
;
315 struct gl_client_array
*to
= &ac
->Cache
.SecondaryColor
;
317 /* Limited choices at this stage:
319 ASSERT(type
== CHAN_TYPE
);
320 ASSERT(stride
== 4 * sizeof(GLchan
) || stride
== 0);
322 _math_trans_4chan( (GLchan (*)[4]) to
->Ptr
,
328 ac
->count
- ac
->start
);
330 to
->StrideB
= 4 * sizeof(GLchan
);
331 to
->Type
= CHAN_TYPE
;
332 ac
->IsCached
.SecondaryColor
= GL_TRUE
;
335 static void import_fogcoord( GLcontext
*ctx
,
336 GLenum type
, GLuint stride
)
338 ACcontext
*ac
= AC_CONTEXT(ctx
);
339 struct gl_client_array
*from
= &ac
->Raw
.FogCoord
;
340 struct gl_client_array
*to
= &ac
->Cache
.FogCoord
;
342 /* Limited choices at this stage:
344 ASSERT(type
== GL_FLOAT
);
345 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
347 _math_trans_1f( (GLfloat
*) to
->Ptr
,
352 ac
->count
- ac
->start
);
354 to
->StrideB
= sizeof(GLfloat
);
356 ac
->IsCached
.FogCoord
= GL_TRUE
;
359 static void import_edgeflag( GLcontext
*ctx
,
360 GLenum type
, GLuint stride
)
362 ACcontext
*ac
= AC_CONTEXT(ctx
);
363 struct gl_client_array
*from
= &ac
->Raw
.EdgeFlag
;
364 struct gl_client_array
*to
= &ac
->Cache
.EdgeFlag
;
366 /* Limited choices at this stage:
368 ASSERT(type
== GL_UNSIGNED_BYTE
);
369 ASSERT(stride
== sizeof(GLubyte
) || stride
== 0);
371 _math_trans_1ub( (GLubyte
*) to
->Ptr
,
376 ac
->count
- ac
->start
);
378 to
->StrideB
= sizeof(GLubyte
);
379 to
->Type
= GL_UNSIGNED_BYTE
;
380 ac
->IsCached
.EdgeFlag
= GL_TRUE
;
385 /* Externals to request arrays with specific properties:
387 struct gl_client_array
*_ac_import_texcoord( GLcontext
*ctx
,
392 GLboolean reqwriteable
,
393 GLboolean
*writeable
)
395 ACcontext
*ac
= AC_CONTEXT(ctx
);
397 /* Can we keep the existing version?
399 if (ac
->NewArrayState
& _NEW_ARRAY_TEXCOORD(unit
))
400 reset_texcoord( ctx
, unit
);
402 /* Is the request impossible?
404 if (reqsize
!= 0 && ac
->Raw
.TexCoord
[unit
].Size
> (GLint
) reqsize
)
407 /* Do we need to pull in a copy of the client data:
409 if (ac
->Raw
.TexCoord
[unit
].Type
!= type
||
410 (reqstride
!= 0 && ac
->Raw
.TexCoord
[unit
].StrideB
!= (GLint
)reqstride
) ||
413 if (!ac
->IsCached
.TexCoord
[unit
])
414 import_texcoord(ctx
, unit
, type
, reqstride
);
415 *writeable
= GL_TRUE
;
416 return &ac
->Cache
.TexCoord
[unit
];
419 *writeable
= GL_FALSE
;
420 return &ac
->Raw
.TexCoord
[unit
];
424 struct gl_client_array
*_ac_import_vertex( GLcontext
*ctx
,
428 GLboolean reqwriteable
,
429 GLboolean
*writeable
)
431 ACcontext
*ac
= AC_CONTEXT(ctx
);
433 /* Can we keep the existing version?
435 if (ac
->NewArrayState
& _NEW_ARRAY_VERTEX
)
438 /* Is the request impossible?
440 if (reqsize
!= 0 && ac
->Raw
.Vertex
.Size
> (GLint
) reqsize
)
443 /* Do we need to pull in a copy of the client data:
445 if (ac
->Raw
.Vertex
.Type
!= type
||
446 (reqstride
!= 0 && ac
->Raw
.Vertex
.StrideB
!= (GLint
) reqstride
) ||
449 if (!ac
->IsCached
.Vertex
)
450 import_vertex(ctx
, type
, reqstride
);
451 *writeable
= GL_TRUE
;
452 return &ac
->Cache
.Vertex
;
455 *writeable
= GL_FALSE
;
456 return &ac
->Raw
.Vertex
;
460 struct gl_client_array
*_ac_import_normal( GLcontext
*ctx
,
463 GLboolean reqwriteable
,
464 GLboolean
*writeable
)
466 ACcontext
*ac
= AC_CONTEXT(ctx
);
468 /* Can we keep the existing version?
470 if (ac
->NewArrayState
& _NEW_ARRAY_NORMAL
)
473 /* Do we need to pull in a copy of the client data:
475 if (ac
->Raw
.Normal
.Type
!= type
||
476 (reqstride
!= 0 && ac
->Raw
.Normal
.StrideB
!= (GLint
) reqstride
) ||
479 if (!ac
->IsCached
.Normal
)
480 import_normal(ctx
, type
, reqstride
);
481 *writeable
= GL_TRUE
;
482 return &ac
->Cache
.Normal
;
485 *writeable
= GL_FALSE
;
486 return &ac
->Raw
.Normal
;
490 struct gl_client_array
*_ac_import_color( GLcontext
*ctx
,
494 GLboolean reqwriteable
,
495 GLboolean
*writeable
)
497 ACcontext
*ac
= AC_CONTEXT(ctx
);
499 /* Can we keep the existing version?
501 if (ac
->NewArrayState
& _NEW_ARRAY_COLOR
)
504 /* Is the request impossible?
506 if (reqsize
!= 0 && ac
->Raw
.Color
.Size
> (GLint
) reqsize
) {
510 /* Do we need to pull in a copy of the client data:
512 if (ac
->Raw
.Color
.Type
!= type
||
513 (reqstride
!= 0 && ac
->Raw
.Color
.StrideB
!= (GLint
) reqstride
) ||
516 if (!ac
->IsCached
.Color
)
517 import_color(ctx
, type
, reqstride
);
518 *writeable
= GL_TRUE
;
519 return &ac
->Cache
.Color
;
522 *writeable
= GL_FALSE
;
523 return &ac
->Raw
.Color
;
527 struct gl_client_array
*_ac_import_index( GLcontext
*ctx
,
530 GLboolean reqwriteable
,
531 GLboolean
*writeable
)
533 ACcontext
*ac
= AC_CONTEXT(ctx
);
535 /* Can we keep the existing version?
537 if (ac
->NewArrayState
& _NEW_ARRAY_INDEX
)
541 /* Do we need to pull in a copy of the client data:
543 if (ac
->Raw
.Index
.Type
!= type
||
544 (reqstride
!= 0 && ac
->Raw
.Index
.StrideB
!= (GLint
) reqstride
) ||
547 if (!ac
->IsCached
.Index
)
548 import_index(ctx
, type
, reqstride
);
549 *writeable
= GL_TRUE
;
550 return &ac
->Cache
.Index
;
553 *writeable
= GL_FALSE
;
554 return &ac
->Raw
.Index
;
558 struct gl_client_array
*_ac_import_secondarycolor( GLcontext
*ctx
,
562 GLboolean reqwriteable
,
563 GLboolean
*writeable
)
565 ACcontext
*ac
= AC_CONTEXT(ctx
);
567 /* Can we keep the existing version?
569 if (ac
->NewArrayState
& _NEW_ARRAY_SECONDARYCOLOR
)
570 reset_secondarycolor( ctx
);
572 /* Is the request impossible?
574 if (reqsize
!= 0 && ac
->Raw
.SecondaryColor
.Size
> (GLint
) reqsize
)
577 /* Do we need to pull in a copy of the client data:
579 if (ac
->Raw
.SecondaryColor
.Type
!= type
||
580 (reqstride
!= 0 && ac
->Raw
.SecondaryColor
.StrideB
!= (GLint
)reqstride
) ||
583 if (!ac
->IsCached
.SecondaryColor
)
584 import_secondarycolor(ctx
, type
, reqstride
);
585 *writeable
= GL_TRUE
;
586 return &ac
->Cache
.SecondaryColor
;
589 *writeable
= GL_FALSE
;
590 return &ac
->Raw
.SecondaryColor
;
594 struct gl_client_array
*_ac_import_fogcoord( GLcontext
*ctx
,
597 GLboolean reqwriteable
,
598 GLboolean
*writeable
)
600 ACcontext
*ac
= AC_CONTEXT(ctx
);
602 /* Can we keep the existing version?
604 if (ac
->NewArrayState
& _NEW_ARRAY_FOGCOORD
)
605 reset_fogcoord( ctx
);
607 /* Do we need to pull in a copy of the client data:
609 if (ac
->Raw
.FogCoord
.Type
!= type
||
610 (reqstride
!= 0 && ac
->Raw
.FogCoord
.StrideB
!= (GLint
) reqstride
) ||
613 if (!ac
->IsCached
.FogCoord
)
614 import_fogcoord(ctx
, type
, reqstride
);
615 *writeable
= GL_TRUE
;
616 return &ac
->Cache
.FogCoord
;
619 *writeable
= GL_FALSE
;
620 return &ac
->Raw
.FogCoord
;
627 struct gl_client_array
*_ac_import_edgeflag( GLcontext
*ctx
,
630 GLboolean reqwriteable
,
631 GLboolean
*writeable
)
633 ACcontext
*ac
= AC_CONTEXT(ctx
);
635 /* Can we keep the existing version?
637 if (ac
->NewArrayState
& _NEW_ARRAY_EDGEFLAG
)
638 reset_edgeflag( ctx
);
640 /* Do we need to pull in a copy of the client data:
642 if (ac
->Raw
.EdgeFlag
.Type
!= type
||
643 (reqstride
!= 0 && ac
->Raw
.EdgeFlag
.StrideB
!= (GLint
) reqstride
) ||
646 if (!ac
->IsCached
.EdgeFlag
)
647 import_edgeflag(ctx
, type
, reqstride
);
648 *writeable
= GL_TRUE
;
649 return &ac
->Cache
.EdgeFlag
;
652 *writeable
= GL_FALSE
;
653 return &ac
->Raw
.EdgeFlag
;
661 /* Clients must call this function to validate state and set bounds
662 * before importing any data:
664 void _ac_import_range( GLcontext
*ctx
, GLuint start
, GLuint count
)
666 ACcontext
*ac
= AC_CONTEXT(ctx
);
668 if (!ctx
->Array
.LockCount
) {
669 /* Not locked, discard cached data. Changes to lock
670 * status are caught via. _ac_invalidate_state().
672 ac
->NewArrayState
= _NEW_ARRAY_ALL
;
677 /* Locked, discard data for any disabled arrays. Require that
678 * the whole locked range always be dealt with, otherwise hard to
679 * maintain cached data in the face of clipping.
681 ac
->NewArrayState
|= ~ctx
->Array
._Enabled
;
682 ac
->start
= ctx
->Array
.LockFirst
;
683 ac
->count
= ctx
->Array
.LockCount
;
684 ASSERT(ac
->start
== start
); /* hmm? */
685 ASSERT(ac
->count
== count
);
691 /* Additional convienence function for importing a the element list
692 * for drawelements, drawrangeelements:
695 _ac_import_elements( GLcontext
*ctx
,
699 CONST
void *indices
)
701 ACcontext
*ac
= AC_CONTEXT(ctx
);
703 if (old_type
== new_type
)
706 if (ac
->elt_size
< count
* sizeof(GLuint
)) {
707 if (ac
->Elts
) FREE(ac
->Elts
);
708 while (ac
->elt_size
< count
* sizeof(GLuint
))
710 ac
->Elts
= (GLuint
*) MALLOC(ac
->elt_size
);
714 case GL_UNSIGNED_BYTE
:
717 case GL_UNSIGNED_SHORT
:
720 case GL_UNSIGNED_INT
: {
721 GLuint
*out
= (GLuint
*)ac
->Elts
;
725 case GL_UNSIGNED_BYTE
: {
726 CONST GLubyte
*in
= (CONST GLubyte
*)indices
;
727 for (i
= 0 ; i
< count
; i
++)
731 case GL_UNSIGNED_SHORT
: {
732 CONST GLushort
*in
= (CONST GLushort
*)indices
;
733 for (i
= 0 ; i
< count
; i
++)
741 return (CONST
void *)out
;