1 /* $Id: ac_import.c,v 1.2 2000/12/28 22:11:05 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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 "array_cache/ac_context.h"
40 /* Set the array pointer back to its source when the cached data is
44 static void reset_texcoord( GLcontext
*ctx
, GLuint unit
)
46 ACcontext
*ac
= AC_CONTEXT(ctx
);
48 /* fprintf(stderr, "%s %d\n", __FUNCTION__, unit); */
50 if (ctx
->Array
._Enabled
& _NEW_ARRAY_TEXCOORD(unit
))
51 ac
->Current
.TexCoord
[unit
] = &ctx
->Array
.TexCoord
[unit
];
53 ac
->Current
.TexCoord
[unit
] = &ac
->Fallback
.TexCoord
[unit
];
55 if (ctx
->Current
.Texcoord
[unit
][4] != 1.0)
56 ac
->Current
.TexCoord
[unit
]->Size
= 4;
57 else if (ctx
->Current
.Texcoord
[unit
][3] != 0.0)
58 ac
->Current
.TexCoord
[unit
]->Size
= 3;
60 ac
->Current
.TexCoord
[unit
]->Size
= 2;
63 ac
->Writeable
.TexCoord
[unit
] = GL_FALSE
;
64 ac
->NewArrayState
&= ~_NEW_ARRAY_TEXCOORD(unit
);
67 static void reset_vertex( GLcontext
*ctx
)
69 ACcontext
*ac
= AC_CONTEXT(ctx
);
70 ASSERT(ctx
->Array
.Vertex
.Enabled
);
71 ac
->Current
.Vertex
= &ctx
->Array
.Vertex
;
72 ac
->Writeable
.Vertex
= GL_FALSE
;
73 ac
->NewArrayState
&= ~_NEW_ARRAY_VERTEX
;
75 /* fprintf(stderr, "%s\n", __FUNCTION__); */
79 static void reset_normal( GLcontext
*ctx
)
81 ACcontext
*ac
= AC_CONTEXT(ctx
);
83 if (ctx
->Array
._Enabled
& _NEW_ARRAY_NORMAL
) {
84 /* fprintf(stderr, "reset normal: using client array enab %d\n", */
85 /* ctx->Array.Normal.Enabled); */
86 ac
->Current
.Normal
= &ctx
->Array
.Normal
;
89 /* fprintf(stderr, "reset normal: using fallback enab %d\n", */
90 /* ctx->Array.Normal.Enabled); */
91 ac
->Current
.Normal
= &ac
->Fallback
.Normal
;
94 ac
->Writeable
.Normal
= GL_FALSE
;
95 ac
->NewArrayState
&= ~_NEW_ARRAY_NORMAL
;
99 static void reset_color( GLcontext
*ctx
)
101 ACcontext
*ac
= AC_CONTEXT(ctx
);
104 if (ctx
->Array
._Enabled
& _NEW_ARRAY_COLOR
)
105 ac
->Current
.Color
= &ctx
->Array
.Color
;
107 ac
->Current
.Color
= &ac
->Fallback
.Color
;
109 /* fprintf(stderr, "reset_color, stride now %d\n", ac->Current.Color->StrideB); */
111 ac
->Writeable
.Color
= GL_FALSE
;
112 ac
->NewArrayState
&= ~_NEW_ARRAY_COLOR
;
116 static void reset_secondarycolor( GLcontext
*ctx
)
118 ACcontext
*ac
= AC_CONTEXT(ctx
);
120 if (ctx
->Array
._Enabled
& _NEW_ARRAY_SECONDARYCOLOR
)
121 ac
->Current
.SecondaryColor
= &ctx
->Array
.SecondaryColor
;
123 ac
->Current
.SecondaryColor
= &ac
->Fallback
.SecondaryColor
;
125 ac
->Writeable
.SecondaryColor
= GL_FALSE
;
126 ac
->NewArrayState
&= ~_NEW_ARRAY_SECONDARYCOLOR
;
130 static void reset_index( GLcontext
*ctx
)
132 ACcontext
*ac
= AC_CONTEXT(ctx
);
134 if (ctx
->Array
._Enabled
& _NEW_ARRAY_INDEX
)
135 ac
->Current
.Index
= &ctx
->Array
.Index
;
137 ac
->Current
.Index
= &ac
->Fallback
.Index
;
139 ac
->Writeable
.Index
= GL_FALSE
;
140 ac
->NewArrayState
&= ~_NEW_ARRAY_INDEX
;
143 static void reset_fogcoord( GLcontext
*ctx
)
145 ACcontext
*ac
= AC_CONTEXT(ctx
);
147 if (ctx
->Array
._Enabled
& _NEW_ARRAY_FOGCOORD
)
148 ac
->Current
.FogCoord
= &ctx
->Array
.FogCoord
;
150 ac
->Current
.FogCoord
= &ac
->Fallback
.FogCoord
;
152 ac
->Writeable
.FogCoord
= GL_FALSE
;
153 ac
->NewArrayState
&= ~_NEW_ARRAY_FOGCOORD
;
156 static void reset_edgeflag( GLcontext
*ctx
)
158 ACcontext
*ac
= AC_CONTEXT(ctx
);
160 if (ctx
->Array
._Enabled
& _NEW_ARRAY_EDGEFLAG
)
161 ac
->Current
.EdgeFlag
= &ctx
->Array
.EdgeFlag
;
163 ac
->Current
.EdgeFlag
= &ac
->Fallback
.EdgeFlag
;
165 ac
->Writeable
.EdgeFlag
= GL_FALSE
;
166 ac
->NewArrayState
&= ~_NEW_ARRAY_EDGEFLAG
;
170 /* Functions to import array ranges with specified types and strides.
172 static void import_texcoord( GLcontext
*ctx
, GLuint unit
,
173 GLenum type
, GLuint stride
)
175 ACcontext
*ac
= AC_CONTEXT(ctx
);
176 struct gl_client_array
*from
= ac
->Current
.TexCoord
[unit
];
177 struct gl_client_array
*to
= &ac
->Cache
.TexCoord
[unit
];
179 /* Limited choices at this stage:
181 ASSERT(type
== GL_FLOAT
);
182 ASSERT(stride
== 4*sizeof(GLfloat
) || stride
== 0);
183 ASSERT(ac
->count
- ac
->start
< ctx
->Const
.MaxArrayLockSize
);
185 /* fprintf(stderr, "%s %d old ptr %p\n", __FUNCTION__, unit, from->Ptr); */
187 _math_trans_4f( to
->Ptr
,
195 to
->Size
= from
->Size
;
196 to
->StrideB
= 4 * sizeof(GLfloat
);
198 ac
->Current
.TexCoord
[unit
] = to
;
199 ac
->Writeable
.TexCoord
[unit
] = GL_TRUE
;
201 /* fprintf(stderr, "%s %d new ptr %p\n", __FUNCTION__, unit, to->Ptr); */
204 static void import_vertex( GLcontext
*ctx
,
205 GLenum type
, GLuint stride
)
207 ACcontext
*ac
= AC_CONTEXT(ctx
);
208 struct gl_client_array
*from
= ac
->Current
.Vertex
;
209 struct gl_client_array
*to
= &ac
->Cache
.Vertex
;
211 /* fprintf(stderr, "(ac) %s\n", __FUNCTION__); */
213 /* Limited choices at this stage:
215 ASSERT(type
== GL_FLOAT
);
216 ASSERT(stride
== 4*sizeof(GLfloat
) || stride
== 0);
218 _math_trans_4f( to
->Ptr
,
226 to
->Size
= from
->Size
;
227 to
->StrideB
= 4 * sizeof(GLfloat
);
229 ac
->Current
.Vertex
= to
;
230 ac
->Writeable
.Vertex
= GL_TRUE
;
233 static void import_normal( GLcontext
*ctx
,
234 GLenum type
, GLuint stride
)
236 ACcontext
*ac
= AC_CONTEXT(ctx
);
237 struct gl_client_array
*from
= ac
->Current
.Normal
;
238 struct gl_client_array
*to
= &ac
->Cache
.Normal
;
241 /* fprintf(stderr, "ac: import_normal\n"); */
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
,
255 to
->StrideB
= 3 * sizeof(GLfloat
);
257 ac
->Current
.Normal
= to
;
258 ac
->Writeable
.Normal
= GL_TRUE
;
261 static void import_color( GLcontext
*ctx
,
262 GLenum type
, GLuint stride
)
264 ACcontext
*ac
= AC_CONTEXT(ctx
);
265 struct gl_client_array
*from
= ac
->Current
.Color
;
266 struct gl_client_array
*to
= &ac
->Cache
.Color
;
268 /* fprintf(stderr, "(ac) %s\n", __FUNCTION__); */
270 /* Limited choices at this stage:
272 ASSERT(type
== GL_UNSIGNED_BYTE
);
273 ASSERT(stride
== 4*sizeof(GLubyte
) || stride
== 0);
275 _math_trans_4ub( to
->Ptr
,
283 to
->Size
= from
->Size
;
284 to
->StrideB
= 4 * sizeof(GLubyte
);
286 ac
->Current
.Color
= to
;
287 ac
->Writeable
.Color
= GL_TRUE
;
290 static void import_index( GLcontext
*ctx
,
291 GLenum type
, GLuint stride
)
293 ACcontext
*ac
= AC_CONTEXT(ctx
);
294 struct gl_client_array
*from
= ac
->Current
.Index
;
295 struct gl_client_array
*to
= &ac
->Cache
.Index
;
297 /* Limited choices at this stage:
299 ASSERT(type
== GL_UNSIGNED_INT
);
300 ASSERT(stride
== sizeof(GLuint
) || stride
== 0);
302 _math_trans_1ui( to
->Ptr
,
309 to
->StrideB
= sizeof(GLuint
);
310 to
->Type
= GL_UNSIGNED_INT
;
311 ac
->Current
.Index
= to
;
312 ac
->Writeable
.Index
= GL_TRUE
;
315 static void import_secondarycolor( GLcontext
*ctx
,
316 GLenum type
, GLuint stride
)
318 ACcontext
*ac
= AC_CONTEXT(ctx
);
319 struct gl_client_array
*from
= ac
->Current
.SecondaryColor
;
320 struct gl_client_array
*to
= &ac
->Cache
.SecondaryColor
;
322 /* Limited choices at this stage:
324 ASSERT(type
== GL_UNSIGNED_BYTE
);
325 ASSERT(stride
== 4*sizeof(GLubyte
) || stride
== 0);
327 _math_trans_4ub( to
->Ptr
,
335 to
->StrideB
= 4 * sizeof(GLubyte
);
336 to
->Type
= GL_UNSIGNED_BYTE
;
337 ac
->Current
.SecondaryColor
= to
;
338 ac
->Writeable
.SecondaryColor
= GL_TRUE
;
341 static void import_fogcoord( GLcontext
*ctx
,
342 GLenum type
, GLuint stride
)
344 ACcontext
*ac
= AC_CONTEXT(ctx
);
345 struct gl_client_array
*from
= ac
->Current
.FogCoord
;
346 struct gl_client_array
*to
= &ac
->Cache
.FogCoord
;
348 /* Limited choices at this stage:
350 ASSERT(type
== GL_FLOAT
);
351 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
353 _math_trans_1f( to
->Ptr
,
360 to
->StrideB
= sizeof(GLfloat
);
362 ac
->Current
.FogCoord
= to
;
363 ac
->Writeable
.FogCoord
= GL_TRUE
;
366 static void import_edgeflag( GLcontext
*ctx
,
367 GLenum type
, GLuint stride
)
369 ACcontext
*ac
= AC_CONTEXT(ctx
);
370 struct gl_client_array
*from
= ac
->Current
.EdgeFlag
;
371 struct gl_client_array
*to
= &ac
->Cache
.EdgeFlag
;
373 /* Limited choices at this stage:
375 ASSERT(type
== GL_FLOAT
);
376 ASSERT(stride
== sizeof(GLfloat
) || stride
== 0);
378 _math_trans_1f( to
->Ptr
,
385 to
->StrideB
= sizeof(GLfloat
);
387 ac
->Current
.EdgeFlag
= to
;
388 ac
->Writeable
.EdgeFlag
= GL_TRUE
;
393 /* Externals to request arrays with specific properties:
395 struct gl_client_array
*_ac_import_texcoord( GLcontext
*ctx
,
400 GLboolean reqwriteable
,
401 GLboolean
*writeable
)
403 ACcontext
*ac
= AC_CONTEXT(ctx
);
405 /* Can we keep the existing version?
407 if (ac
->NewArrayState
& _NEW_ARRAY_TEXCOORD(unit
))
408 reset_texcoord( ctx
, unit
);
410 /* Is the request impossible?
412 if (reqsize
!= 0 && ac
->Current
.TexCoord
[unit
]->Size
> reqsize
)
415 /* Do we need to pull in a copy of the client data:
417 if (ac
->Current
.TexCoord
[unit
]->Type
!= type
||
418 (reqstride
!= 0 && ac
->Current
.TexCoord
[unit
]->StrideB
!= reqstride
) ||
419 (reqwriteable
&& !ac
->Writeable
.TexCoord
[unit
]))
420 import_texcoord(ctx
, unit
, type
, reqstride
);
422 *writeable
= ac
->Writeable
.TexCoord
[unit
];
423 return ac
->Current
.TexCoord
[unit
];
426 struct gl_client_array
*_ac_import_vertex( GLcontext
*ctx
,
430 GLboolean reqwriteable
,
431 GLboolean
*writeable
)
433 ACcontext
*ac
= AC_CONTEXT(ctx
);
435 /* Can we keep the existing version?
437 if (ac
->NewArrayState
& _NEW_ARRAY_VERTEX
)
440 /* Is the request impossible?
442 if (reqsize
!= 0 && ac
->Current
.Vertex
->Size
> reqsize
)
445 /* Do we need to pull in a copy of the client data:
447 if (ac
->Current
.Vertex
->Type
!= type
||
448 (reqstride
!= 0 && ac
->Current
.Vertex
->StrideB
!= reqstride
) ||
449 (reqwriteable
&& !ac
->Writeable
.Vertex
))
450 import_vertex(ctx
, type
, reqstride
);
452 *writeable
= ac
->Writeable
.Vertex
;
453 return ac
->Current
.Vertex
;
456 struct gl_client_array
*_ac_import_normal( GLcontext
*ctx
,
459 GLboolean reqwriteable
,
460 GLboolean
*writeable
)
462 ACcontext
*ac
= AC_CONTEXT(ctx
);
464 /* fprintf(stderr, "%s %d\n", __FUNCTION__, ac->NewArrayState & _NEW_ARRAY_NORMAL); */
466 /* Can we keep the existing version?
468 if (ac
->NewArrayState
& _NEW_ARRAY_NORMAL
)
471 /* Do we need to pull in a copy of the client data:
473 if (ac
->Current
.Normal
->Type
!= type
||
474 (reqstride
!= 0 && ac
->Current
.Normal
->StrideB
!= reqstride
) ||
475 (reqwriteable
&& !ac
->Writeable
.Normal
))
476 import_normal(ctx
, type
, reqstride
);
478 *writeable
= ac
->Writeable
.Normal
;
479 return ac
->Current
.Normal
;
482 struct gl_client_array
*_ac_import_color( GLcontext
*ctx
,
486 GLboolean reqwriteable
,
487 GLboolean
*writeable
)
489 ACcontext
*ac
= AC_CONTEXT(ctx
);
491 /* fprintf(stderr, "%s stride %d sz %d wr %d\n", __FUNCTION__, */
492 /* reqstride, reqsize, reqwriteable); */
494 /* Can we keep the existing version?
496 if (ac
->NewArrayState
& _NEW_ARRAY_COLOR
)
499 /* Is the request impossible?
501 if (reqsize
!= 0 && ac
->Current
.Color
->Size
> reqsize
) {
502 /* fprintf(stderr, "%s -- failed\n", __FUNCTION__); */
506 /* Do we need to pull in a copy of the client data:
508 if (ac
->Current
.Color
->Type
!= type
||
509 (reqstride
!= 0 && ac
->Current
.Color
->StrideB
!= reqstride
) ||
510 (reqwriteable
&& !ac
->Writeable
.Color
))
511 import_color(ctx
, type
, reqstride
);
513 *writeable
= ac
->Writeable
.Color
;
514 return ac
->Current
.Color
;
517 struct gl_client_array
*_ac_import_index( GLcontext
*ctx
,
520 GLboolean reqwriteable
,
521 GLboolean
*writeable
)
523 ACcontext
*ac
= AC_CONTEXT(ctx
);
525 /* Can we keep the existing version?
527 if (ac
->NewArrayState
& _NEW_ARRAY_INDEX
)
531 /* Do we need to pull in a copy of the client data:
533 if (ac
->Current
.Index
->Type
!= type
||
534 (reqstride
!= 0 && ac
->Current
.Index
->StrideB
!= reqstride
) ||
535 (reqwriteable
&& !ac
->Writeable
.Index
))
536 import_index(ctx
, type
, reqstride
);
538 *writeable
= ac
->Writeable
.Index
;
539 return ac
->Current
.Index
;
542 struct gl_client_array
*_ac_import_secondarycolor( GLcontext
*ctx
,
546 GLboolean reqwriteable
,
547 GLboolean
*writeable
)
549 ACcontext
*ac
= AC_CONTEXT(ctx
);
551 /* Can we keep the existing version?
553 if (ac
->NewArrayState
& _NEW_ARRAY_SECONDARYCOLOR
)
554 reset_secondarycolor( ctx
);
556 /* Is the request impossible?
558 if (reqsize
!= 0 && ac
->Current
.SecondaryColor
->Size
> reqsize
)
561 /* Do we need to pull in a copy of the client data:
563 if (ac
->Current
.SecondaryColor
->Type
!= type
||
564 (reqstride
!= 0 && ac
->Current
.SecondaryColor
->StrideB
!= reqstride
) ||
565 (reqwriteable
&& !ac
->Writeable
.SecondaryColor
))
566 import_secondarycolor( ctx
, type
, reqstride
);
568 *writeable
= ac
->Writeable
.SecondaryColor
;
569 return ac
->Current
.SecondaryColor
;
572 struct gl_client_array
*_ac_import_fogcoord( GLcontext
*ctx
,
575 GLboolean reqwriteable
,
576 GLboolean
*writeable
)
578 ACcontext
*ac
= AC_CONTEXT(ctx
);
580 /* Can we keep the existing version?
582 if (ac
->NewArrayState
& _NEW_ARRAY_FOGCOORD
)
583 reset_fogcoord( ctx
);
585 /* Do we need to pull in a copy of the client data:
587 if (ac
->Current
.FogCoord
->Type
!= type
||
588 (reqstride
!= 0 && ac
->Current
.FogCoord
->StrideB
!= reqstride
) ||
589 (reqwriteable
&& !ac
->Writeable
.FogCoord
))
590 import_fogcoord(ctx
, type
, reqstride
);
592 *writeable
= ac
->Writeable
.FogCoord
;
593 return ac
->Current
.FogCoord
;
599 struct gl_client_array
*_ac_import_edgeflag( GLcontext
*ctx
,
602 GLboolean reqwriteable
,
603 GLboolean
*writeable
)
605 ACcontext
*ac
= AC_CONTEXT(ctx
);
607 /* Can we keep the existing version?
609 if (ac
->NewArrayState
& _NEW_ARRAY_EDGEFLAG
)
610 reset_edgeflag( ctx
);
612 /* Do we need to pull in a copy of the client data:
614 if (ac
->Current
.EdgeFlag
->Type
!= type
||
615 (reqstride
!= 0 && ac
->Current
.EdgeFlag
->StrideB
!= reqstride
) ||
616 (reqwriteable
&& !ac
->Writeable
.EdgeFlag
))
617 import_edgeflag(ctx
, type
, reqstride
);
619 *writeable
= ac
->Writeable
.EdgeFlag
;
620 return ac
->Current
.EdgeFlag
;
627 /* Clients must call this function to validate state and set bounds
628 * before importing any data:
630 void _ac_import_range( GLcontext
*ctx
, GLuint start
, GLuint count
)
632 ACcontext
*ac
= AC_CONTEXT(ctx
);
634 /* Discard cached data which has been invalidated by state changes
635 * since last time. **ALREADY DONE**
637 _ac_update_state( ctx );
640 if (!ctx
->Array
.LockCount
) {
641 /* Not locked, discard cached data. Changes to lock
642 * status are caught via. _ac_invalidate_state().
644 ac
->NewArrayState
= _NEW_ARRAY_ALL
;
649 /* Locked, discard data for any disabled arrays. Require that
650 * the whole locked range always be dealt with, otherwise hard to
651 * maintain cached data in the face of clipping.
653 ac
->NewArrayState
|= ~ctx
->Array
._Enabled
;
654 ac
->start
= ctx
->Array
.LockFirst
;
655 ac
->count
= ctx
->Array
.LockCount
;
656 ASSERT(ac
->start
== start
); /* hmm? */
657 ASSERT(ac
->count
== count
);
663 /* Additional convienence function for importing a the element list
664 * for drawelements, drawrangeelements:
667 _ac_import_elements( GLcontext
*ctx
,
671 CONST
void *indices
)
673 ACcontext
*ac
= AC_CONTEXT(ctx
);
675 if (old_type
== new_type
)
678 if (ac
->elt_size
< count
* sizeof(GLuint
)) {
679 if (ac
->Elts
) FREE(ac
->Elts
);
680 while (ac
->elt_size
< count
* sizeof(GLuint
))
682 ac
->Elts
= MALLOC(ac
->elt_size
);
686 case GL_UNSIGNED_BYTE
:
689 case GL_UNSIGNED_SHORT
:
692 case GL_UNSIGNED_INT
: {
693 GLuint
*out
= (GLuint
*)ac
->Elts
;
697 case GL_UNSIGNED_BYTE
: {
698 CONST GLubyte
*in
= (CONST GLubyte
*)indices
;
699 for (i
= 0 ; i
< count
; i
++)
703 case GL_UNSIGNED_SHORT
: {
704 CONST GLushort
*in
= (CONST GLushort
*)indices
;
705 for (i
= 0 ; i
< count
; i
++)
713 return (CONST
void *)out
;